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 /* The generic part of a generic pointer should
1311 * not participate in it's truth value.
1313 * i.e. 0x10000000 is zero.
1317 D(emitcode(";", "toBoolean: generic ptr special case."););
1321 if (AOP_NEEDSACC(oper))
1323 emitcode("push", "b");
1324 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1328 MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1332 if (AOP_NEEDSACC(oper))
1334 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1338 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1342 if (AOP_NEEDSACC(oper))
1344 emitcode("mov", "a,b");
1345 emitcode("pop", "b");
1350 /*-----------------------------------------------------------------*/
1351 /* genNot - generate code for ! operation */
1352 /*-----------------------------------------------------------------*/
1353 static void genNot (iCode *ic)
1356 link *optype = operandType(IC_LEFT(ic));
1358 D(emitcode(";", "genNot "););
1360 /* assign asmOps to operand & result */
1361 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1362 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1364 /* if in bit space then a special case */
1365 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1366 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1367 emitcode("cpl","c");
1368 outBitC(IC_RESULT(ic));
1372 /* if type float then do float */
1373 if (IS_FLOAT(optype)) {
1374 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1378 toBoolean(IC_LEFT(ic));
1380 tlbl = newiTempLabel(NULL);
1381 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1382 emitcode("","%05d$:",tlbl->key+100);
1383 outBitC(IC_RESULT(ic));
1386 /* release the aops */
1387 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1388 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1392 /*-----------------------------------------------------------------*/
1393 /* genCpl - generate code for complement */
1394 /*-----------------------------------------------------------------*/
1395 static void genCpl (iCode *ic)
1400 D(emitcode(";", "genCpl "););
1403 /* assign asmOps to operand & result */
1404 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1405 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1407 /* if both are in bit space then
1409 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1410 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1412 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1413 emitcode("cpl","c");
1414 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1418 size = AOP_SIZE(IC_RESULT(ic));
1420 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1422 emitcode("cpl","a");
1423 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1428 /* release the aops */
1429 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1430 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1433 /*-----------------------------------------------------------------*/
1434 /* genUminusFloat - unary minus for floating points */
1435 /*-----------------------------------------------------------------*/
1436 static void genUminusFloat(operand *op,operand *result)
1438 int size ,offset =0 ;
1440 /* for this we just need to flip the
1441 first it then copy the rest in place */
1442 D(emitcode(";", "genUminusFloat"););
1444 size = AOP_SIZE(op) - 1;
1445 l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1448 emitcode("cpl","acc.7");
1449 aopPut(AOP(result),"a",3);
1453 aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1459 /*-----------------------------------------------------------------*/
1460 /* genUminus - unary minus code generation */
1461 /*-----------------------------------------------------------------*/
1462 static void genUminus (iCode *ic)
1465 link *optype, *rtype;
1467 D(emitcode(";", "genUminus "););
1471 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1472 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1474 /* if both in bit space then special
1476 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1477 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1479 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1480 emitcode("cpl","c");
1481 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1485 optype = operandType(IC_LEFT(ic));
1486 rtype = operandType(IC_RESULT(ic));
1488 /* if float then do float stuff */
1489 if (IS_FLOAT(optype)) {
1490 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1494 /* otherwise subtract from zero */
1495 size = AOP_SIZE(IC_LEFT(ic));
1499 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1500 if (!strcmp(l,"a")) {
1503 emitcode("cpl","a");
1504 emitcode("addc", "a,#0");
1508 emitcode("clr","a");
1509 emitcode("subb","a,%s",l);
1511 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1514 /* if any remaining bytes in the result */
1515 /* we just need to propagate the sign */
1516 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1517 emitcode("rlc","a");
1518 emitcode("subb","a,acc");
1520 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1524 /* release the aops */
1525 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1526 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1529 /*-----------------------------------------------------------------*/
1530 /* saveRegisters - will look for a call and save the registers */
1531 /*-----------------------------------------------------------------*/
1532 static void saveRegisters(iCode *lic)
1540 for (ic = lic ; ic ; ic = ic->next)
1541 if (ic->op == CALL || ic->op == PCALL)
1545 fprintf(stderr,"found parameter push with no function call\n");
1549 /* if the registers have been saved already then
1551 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1554 /* find the registers in use at this time
1555 and push them away to safety */
1556 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1560 if (options.useXstack) {
1561 if (bitVectBitValue(rsave,R0_IDX))
1562 emitcode("mov","b,r0");
1563 emitcode("mov","r0,%s",spname);
1564 for (i = 0 ; i < ds390_nRegs ; i++) {
1565 if (bitVectBitValue(rsave,i)) {
1567 emitcode("mov","a,b");
1569 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1570 emitcode("movx","@r0,a");
1571 emitcode("inc","r0");
1574 emitcode("mov","%s,r0",spname);
1575 if (bitVectBitValue(rsave,R0_IDX))
1576 emitcode("mov","r0,b");
1578 for (i = 0 ; i < ds390_nRegs ; i++) {
1579 if (bitVectBitValue(rsave,i))
1580 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1583 detype = getSpec(operandType(IC_LEFT(ic)));
1585 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1586 IS_ISR(currFunc->etype) &&
1589 saverbank(SPEC_BANK(detype),ic,TRUE);
1592 /*-----------------------------------------------------------------*/
1593 /* unsaveRegisters - pop the pushed registers */
1594 /*-----------------------------------------------------------------*/
1595 static void unsaveRegisters (iCode *ic)
1599 /* find the registers in use at this time
1600 and push them away to safety */
1601 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1604 if (options.useXstack) {
1605 emitcode("mov","r0,%s",spname);
1606 for (i = ds390_nRegs ; i >= 0 ; i--) {
1607 if (bitVectBitValue(rsave,i)) {
1608 emitcode("dec","r0");
1609 emitcode("movx","a,@r0");
1611 emitcode("mov","b,a");
1613 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1617 emitcode("mov","%s,r0",spname);
1618 if (bitVectBitValue(rsave,R0_IDX))
1619 emitcode("mov","r0,b");
1621 for (i = ds390_nRegs ; i >= 0 ; i--) {
1622 if (bitVectBitValue(rsave,i))
1623 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1629 /*-----------------------------------------------------------------*/
1631 /*-----------------------------------------------------------------*/
1632 static void pushSide(operand * oper, int size)
1636 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1637 if (AOP_TYPE(oper) != AOP_REG &&
1638 AOP_TYPE(oper) != AOP_DIR &&
1640 emitcode("mov","a,%s",l);
1641 emitcode("push","acc");
1643 emitcode("push","%s",l);
1647 /*-----------------------------------------------------------------*/
1648 /* assignResultValue - */
1649 /*-----------------------------------------------------------------*/
1650 static void assignResultValue(operand * oper)
1653 int size = AOP_SIZE(oper);
1655 aopPut(AOP(oper),fReturn[offset],offset);
1661 /*-----------------------------------------------------------------*/
1662 /* genXpush - pushes onto the external stack */
1663 /*-----------------------------------------------------------------*/
1664 static void genXpush (iCode *ic)
1666 asmop *aop = newAsmop(0);
1668 int size,offset = 0;
1670 D(emitcode(";", "genXpush "););
1672 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1673 r = getFreePtr(ic,&aop,FALSE);
1676 emitcode("mov","%s,_spx",r->name);
1678 size = AOP_SIZE(IC_LEFT(ic));
1681 char *l = aopGet(AOP(IC_LEFT(ic)),
1682 offset++,FALSE,FALSE,TRUE);
1684 emitcode("movx","@%s,a",r->name);
1685 emitcode("inc","%s",r->name);
1690 emitcode("mov","_spx,%s",r->name);
1692 freeAsmop(NULL,aop,ic,TRUE);
1693 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1696 /*-----------------------------------------------------------------*/
1697 /* genIpush - genrate code for pushing this gets a little complex */
1698 /*-----------------------------------------------------------------*/
1699 static void genIpush (iCode *ic)
1701 int size, offset = 0 ;
1704 D(emitcode(";", "genIpush "););
1707 /* if this is not a parm push : ie. it is spill push
1708 and spill push is always done on the local stack */
1709 if (!ic->parmPush) {
1711 /* and the item is spilt then do nothing */
1712 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1715 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1716 size = AOP_SIZE(IC_LEFT(ic));
1717 /* push it on the stack */
1719 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1724 emitcode("push","%s",l);
1729 /* this is a paramter push: in this case we call
1730 the routine to find the call and save those
1731 registers that need to be saved */
1734 /* if use external stack then call the external
1735 stack pushing routine */
1736 if (options.useXstack) {
1741 /* then do the push */
1742 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1745 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1746 size = AOP_SIZE(IC_LEFT(ic));
1749 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1750 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1751 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1753 emitcode("mov","a,%s",l);
1754 emitcode("push","acc");
1756 emitcode("push","%s",l);
1759 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1762 /*-----------------------------------------------------------------*/
1763 /* genIpop - recover the registers: can happen only for spilling */
1764 /*-----------------------------------------------------------------*/
1765 static void genIpop (iCode *ic)
1769 D(emitcode(";", "genIpop "););
1772 /* if the temp was not pushed then */
1773 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1776 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1777 size = AOP_SIZE(IC_LEFT(ic));
1780 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1783 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1786 /*-----------------------------------------------------------------*/
1787 /* unsaverbank - restores the resgister bank from stack */
1788 /*-----------------------------------------------------------------*/
1789 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1796 if (options.useXstack) {
1798 r = getFreePtr(ic,&aop,FALSE);
1801 emitcode("mov","%s,_spx",r->name);
1802 emitcode("movx","a,@%s",r->name);
1803 emitcode("mov","psw,a");
1804 emitcode("dec","%s",r->name);
1807 emitcode ("pop","psw");
1810 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1811 if (options.useXstack) {
1812 emitcode("movx","a,@%s",r->name);
1813 emitcode("mov","(%s+%d),a",
1814 regs390[i].base,8*bank+regs390[i].offset);
1815 emitcode("dec","%s",r->name);
1818 emitcode("pop","(%s+%d)",
1819 regs390[i].base,8*bank+regs390[i].offset);
1822 if (options.useXstack) {
1824 emitcode("mov","_spx,%s",r->name);
1825 freeAsmop(NULL,aop,ic,TRUE);
1830 /*-----------------------------------------------------------------*/
1831 /* saverbank - saves an entire register bank on the stack */
1832 /*-----------------------------------------------------------------*/
1833 static void saverbank (int bank, iCode *ic, bool pushPsw)
1839 if (options.useXstack) {
1842 r = getFreePtr(ic,&aop,FALSE);
1843 emitcode("mov","%s,_spx",r->name);
1847 for (i = 0 ; i < ds390_nRegs ;i++) {
1848 if (options.useXstack) {
1849 emitcode("inc","%s",r->name);
1850 emitcode("mov","a,(%s+%d)",
1851 regs390[i].base,8*bank+regs390[i].offset);
1852 emitcode("movx","@%s,a",r->name);
1854 emitcode("push","(%s+%d)",
1855 regs390[i].base,8*bank+regs390[i].offset);
1859 if (options.useXstack) {
1860 emitcode("mov","a,psw");
1861 emitcode("movx","@%s,a",r->name);
1862 emitcode("inc","%s",r->name);
1863 emitcode("mov","_spx,%s",r->name);
1864 freeAsmop (NULL,aop,ic,TRUE);
1867 emitcode("push","psw");
1869 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1875 /*-----------------------------------------------------------------*/
1876 /* genCall - generates a call statement */
1877 /*-----------------------------------------------------------------*/
1878 static void genCall (iCode *ic)
1882 D(emitcode(";", "genCall "););
1884 /* if caller saves & we have not saved then */
1888 /* if we are calling a function that is not using
1889 the same register bank then we need to save the
1890 destination registers on the stack */
1891 detype = getSpec(operandType(IC_LEFT(ic)));
1893 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1894 IS_ISR(currFunc->etype) &&
1897 saverbank(SPEC_BANK(detype),ic,TRUE);
1899 /* if send set is not empty the assign */
1903 for (sic = setFirstItem(_G.sendSet) ; sic ;
1904 sic = setNextItem(_G.sendSet)) {
1905 int size, offset = 0;
1906 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
1907 size = AOP_SIZE(IC_LEFT(sic));
1909 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1910 FALSE, FALSE, FALSE);
1911 if (strcmp(l,fReturn[offset]))
1912 emitcode("mov","%s,%s",
1917 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1922 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1923 OP_SYMBOL(IC_LEFT(ic))->rname :
1924 OP_SYMBOL(IC_LEFT(ic))->name));
1926 /* if we need assign a result value */
1927 if ((IS_ITEMP(IC_RESULT(ic)) &&
1928 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1929 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1930 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1932 if (!isOperandInFarSpace(IC_RESULT(ic)))
1935 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1938 assignResultValue(IC_RESULT(ic));
1940 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1944 /* Result is in far space, and requires DPTR to access
1945 * it. Push the result onto the stack and restore from
1948 int size = getSize(operandType(IC_RESULT(ic)));
1949 int offset = size - 1;
1952 emitcode(";", "Kevin function call abuse #1");
1954 /* first push the right side on to the stack */
1955 /* NB: this relies on the fact that "a" is the last
1956 * register in fReturn. If it were not, the MOVA
1957 * would potentially clobber a returned byte in A.
1960 l = fReturn[offset--];
1962 emitcode ("push","acc");
1965 /* now assign DPTR to result */
1966 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1967 size = AOP_SIZE(IC_RESULT(ic));
1968 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
1970 emitcode ("pop","acc");
1971 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
1973 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1977 /* adjust the stack for parameters if
1979 if (IC_LEFT(ic)->parmBytes) {
1981 if (IC_LEFT(ic)->parmBytes > 3) {
1982 emitcode("mov","a,%s",spname);
1983 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1984 emitcode("mov","%s,a",spname);
1986 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1987 emitcode("dec","%s",spname);
1991 /* if register bank was saved then pop them */
1993 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1995 /* if we hade saved some registers then unsave them */
1996 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1997 unsaveRegisters (ic);
2002 /*-----------------------------------------------------------------*/
2003 /* genPcall - generates a call by pointer statement */
2004 /*-----------------------------------------------------------------*/
2005 static void genPcall (iCode *ic)
2008 symbol *rlbl = newiTempLabel(NULL);
2010 D(emitcode(";", "genPcall "););
2013 /* if caller saves & we have not saved then */
2017 /* if we are calling a function that is not using
2018 the same register bank then we need to save the
2019 destination registers on the stack */
2020 detype = getSpec(operandType(IC_LEFT(ic)));
2022 IS_ISR(currFunc->etype) &&
2023 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2024 saverbank(SPEC_BANK(detype),ic,TRUE);
2027 /* push the return address on to the stack */
2028 emitcode("mov","a,#%05d$",(rlbl->key+100));
2029 emitcode("push","acc");
2030 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2031 emitcode("push","acc");
2033 if (options.model == MODEL_FLAT24)
2035 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2036 emitcode("push","acc");
2039 /* now push the calling address */
2040 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2042 pushSide(IC_LEFT(ic), FPTRSIZE);
2044 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2046 /* if send set is not empty the assign */
2050 for (sic = setFirstItem(_G.sendSet) ; sic ;
2051 sic = setNextItem(_G.sendSet)) {
2052 int size, offset = 0;
2053 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2054 size = AOP_SIZE(IC_LEFT(sic));
2056 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2058 if (strcmp(l,fReturn[offset]))
2059 emitcode("mov","%s,%s",
2064 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2070 emitcode("","%05d$:",(rlbl->key+100));
2073 /* if we need assign a result value */
2074 if ((IS_ITEMP(IC_RESULT(ic)) &&
2075 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2076 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2077 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2080 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2083 assignResultValue(IC_RESULT(ic));
2085 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2088 /* adjust the stack for parameters if
2090 if (IC_LEFT(ic)->parmBytes) {
2092 if (IC_LEFT(ic)->parmBytes > 3) {
2093 emitcode("mov","a,%s",spname);
2094 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2095 emitcode("mov","%s,a",spname);
2097 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2098 emitcode("dec","%s",spname);
2102 /* if register bank was saved then unsave them */
2104 (SPEC_BANK(currFunc->etype) !=
2106 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2108 /* if we hade saved some registers then
2111 unsaveRegisters (ic);
2115 /*-----------------------------------------------------------------*/
2116 /* resultRemat - result is rematerializable */
2117 /*-----------------------------------------------------------------*/
2118 static int resultRemat (iCode *ic)
2120 if (SKIP_IC(ic) || ic->op == IFX)
2123 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2124 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2125 if (sym->remat && !POINTER_SET(ic))
2133 #define STRCASECMP stricmp
2135 #define STRCASECMP strcasecmp
2138 /*-----------------------------------------------------------------*/
2139 /* inExcludeList - return 1 if the string is in exclude Reg list */
2140 /*-----------------------------------------------------------------*/
2141 static bool inExcludeList(char *s)
2145 if (options.excludeRegs[i] &&
2146 STRCASECMP(options.excludeRegs[i],"none") == 0)
2149 for ( i = 0 ; options.excludeRegs[i]; i++) {
2150 if (options.excludeRegs[i] &&
2151 STRCASECMP(s,options.excludeRegs[i]) == 0)
2157 /*-----------------------------------------------------------------*/
2158 /* genFunction - generated code for function entry */
2159 /*-----------------------------------------------------------------*/
2160 static void genFunction (iCode *ic)
2165 D(emitcode(";", "genFunction "););
2168 /* create the function header */
2169 emitcode(";","-----------------------------------------");
2170 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2171 emitcode(";","-----------------------------------------");
2173 emitcode("","%s:",sym->rname);
2174 fetype = getSpec(operandType(IC_LEFT(ic)));
2176 /* if critical function then turn interrupts off */
2177 if (SPEC_CRTCL(fetype))
2178 emitcode("clr","ea");
2180 /* here we need to generate the equates for the
2181 register bank if required */
2182 if (SPEC_BANK(fetype) != rbank) {
2185 rbank = SPEC_BANK(fetype);
2186 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2187 if (strcmp(regs390[i].base,"0") == 0)
2188 emitcode("","%s = 0x%02x",
2190 8*rbank+regs390[i].offset);
2192 emitcode ("","%s = %s + 0x%02x",
2195 8*rbank+regs390[i].offset);
2199 /* if this is an interrupt service routine then
2200 save acc, b, dpl, dph */
2201 if (IS_ISR(sym->etype)) {
2203 if (!inExcludeList("acc"))
2204 emitcode ("push","acc");
2205 if (!inExcludeList("b"))
2206 emitcode ("push","b");
2207 if (!inExcludeList("dpl"))
2208 emitcode ("push","dpl");
2209 if (!inExcludeList("dph"))
2210 emitcode ("push","dph");
2211 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2213 emitcode ("push", "dpx");
2214 /* Make sure we're using standard DPTR */
2215 emitcode ("push", "dps");
2216 emitcode ("mov", "dps, #0x00");
2217 if (options.stack10bit)
2219 /* This ISR could conceivably use DPTR2. Better save it. */
2220 emitcode ("push", "dpl1");
2221 emitcode ("push", "dph1");
2222 emitcode ("push", "dpx1");
2223 emitcode ("push", "ap");
2226 /* if this isr has no bank i.e. is going to
2227 run with bank 0 , then we need to save more
2229 if (!SPEC_BANK(sym->etype)) {
2231 /* if this function does not call any other
2232 function then we can be economical and
2233 save only those registers that are used */
2234 if (! sym->hasFcall) {
2237 /* if any registers used */
2238 if (sym->regsUsed) {
2239 /* save the registers used */
2240 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2241 if (bitVectBitValue(sym->regsUsed,i) ||
2242 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2243 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2248 /* this function has a function call cannot
2249 determines register usage so we will have the
2251 saverbank(0,ic,FALSE);
2255 /* if callee-save to be used for this function
2256 then save the registers being used in this function */
2257 if (sym->calleeSave) {
2260 /* if any registers used */
2261 if (sym->regsUsed) {
2262 /* save the registers used */
2263 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2264 if (bitVectBitValue(sym->regsUsed,i) ||
2265 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2266 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2274 /* set the register bank to the desired value */
2275 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2276 emitcode("push","psw");
2277 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2280 if (IS_RENT(sym->etype) || options.stackAuto) {
2282 if (options.useXstack) {
2283 emitcode("mov","r0,%s",spname);
2284 emitcode("mov","a,_bp");
2285 emitcode("movx","@r0,a");
2286 emitcode("inc","%s",spname);
2290 /* set up the stack */
2291 emitcode ("push","_bp"); /* save the callers stack */
2293 emitcode ("mov","_bp,%s",spname);
2296 /* adjust the stack for the function */
2301 werror(W_STACK_OVERFLOW,sym->name);
2303 if (i > 3 && sym->recvSize < 4) {
2305 emitcode ("mov","a,sp");
2306 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2307 emitcode ("mov","sp,a");
2312 emitcode("inc","sp");
2317 emitcode ("mov","a,_spx");
2318 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2319 emitcode ("mov","_spx,a");
2324 /*-----------------------------------------------------------------*/
2325 /* genEndFunction - generates epilogue for functions */
2326 /*-----------------------------------------------------------------*/
2327 static void genEndFunction (iCode *ic)
2329 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2331 D(emitcode(";", "genEndFunction "););
2333 if (IS_RENT(sym->etype) || options.stackAuto)
2335 emitcode ("mov","%s,_bp",spname);
2338 /* if use external stack but some variables were
2339 added to the local stack then decrement the
2341 if (options.useXstack && sym->stack) {
2342 emitcode("mov","a,sp");
2343 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2344 emitcode("mov","sp,a");
2348 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2349 if (options.useXstack) {
2350 emitcode("mov","r0,%s",spname);
2351 emitcode("movx","a,@r0");
2352 emitcode("mov","_bp,a");
2353 emitcode("dec","%s",spname);
2357 emitcode ("pop","_bp");
2361 /* restore the register bank */
2362 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2363 emitcode ("pop","psw");
2365 if (IS_ISR(sym->etype)) {
2367 /* now we need to restore the registers */
2368 /* if this isr has no bank i.e. is going to
2369 run with bank 0 , then we need to save more
2371 if (!SPEC_BANK(sym->etype)) {
2373 /* if this function does not call any other
2374 function then we can be economical and
2375 save only those registers that are used */
2376 if (! sym->hasFcall) {
2379 /* if any registers used */
2380 if (sym->regsUsed) {
2381 /* save the registers used */
2382 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2383 if (bitVectBitValue(sym->regsUsed,i) ||
2384 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2385 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2390 /* this function has a function call cannot
2391 determines register usage so we will have the
2393 unsaverbank(0,ic,FALSE);
2397 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2399 if (options.stack10bit)
2401 emitcode ("pop", "ap");
2402 emitcode ("pop", "dpx1");
2403 emitcode ("pop", "dph1");
2404 emitcode ("pop", "dpl1");
2406 emitcode ("pop", "dps");
2407 emitcode ("pop", "dpx");
2409 if (!inExcludeList("dph"))
2410 emitcode ("pop","dph");
2411 if (!inExcludeList("dpl"))
2412 emitcode ("pop","dpl");
2413 if (!inExcludeList("b"))
2414 emitcode ("pop","b");
2415 if (!inExcludeList("acc"))
2416 emitcode ("pop","acc");
2418 if (SPEC_CRTCL(sym->etype))
2419 emitcode("setb","ea");
2421 /* if debug then send end of function */
2422 /* if (options.debug && currFunc) { */
2425 emitcode("","C$%s$%d$%d$%d ==.",
2426 ic->filename,currFunc->lastLine,
2427 ic->level,ic->block);
2428 if (IS_STATIC(currFunc->etype))
2429 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2431 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2435 emitcode ("reti","");
2438 if (SPEC_CRTCL(sym->etype))
2439 emitcode("setb","ea");
2441 if (sym->calleeSave) {
2444 /* if any registers used */
2445 if (sym->regsUsed) {
2446 /* save the registers used */
2447 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2448 if (bitVectBitValue(sym->regsUsed,i) ||
2449 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2450 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2456 /* if debug then send end of function */
2459 emitcode("","C$%s$%d$%d$%d ==.",
2460 ic->filename,currFunc->lastLine,
2461 ic->level,ic->block);
2462 if (IS_STATIC(currFunc->etype))
2463 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2465 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2469 emitcode ("ret","");
2474 /*-----------------------------------------------------------------*/
2475 /* genRet - generate code for return statement */
2476 /*-----------------------------------------------------------------*/
2477 static void genRet (iCode *ic)
2479 int size,offset = 0 , pushed = 0;
2481 D(emitcode(";", "genRet "););
2483 /* if we have no return value then
2484 just generate the "ret" */
2488 /* we have something to return then
2489 move the return value into place */
2490 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2491 size = AOP_SIZE(IC_LEFT(ic));
2495 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2496 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2498 emitcode("push","%s",l);
2501 l = aopGet(AOP(IC_LEFT(ic)),offset,
2503 if (strcmp(fReturn[offset],l))
2504 emitcode("mov","%s,%s",fReturn[offset++],l);
2511 if (strcmp(fReturn[pushed],"a"))
2512 emitcode("pop",fReturn[pushed]);
2514 emitcode("pop","acc");
2517 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2520 /* generate a jump to the return label
2521 if the next is not the return statement */
2522 if (!(ic->next && ic->next->op == LABEL &&
2523 IC_LABEL(ic->next) == returnLabel))
2525 emitcode("ljmp","%05d$",(returnLabel->key+100));
2529 /*-----------------------------------------------------------------*/
2530 /* genLabel - generates a label */
2531 /*-----------------------------------------------------------------*/
2532 static void genLabel (iCode *ic)
2534 /* special case never generate */
2535 if (IC_LABEL(ic) == entryLabel)
2538 D(emitcode(";", "genLabel "););
2540 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2543 /*-----------------------------------------------------------------*/
2544 /* genGoto - generates a ljmp */
2545 /*-----------------------------------------------------------------*/
2546 static void genGoto (iCode *ic)
2548 D(emitcode(";", "genGoto "););
2549 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2552 /*-----------------------------------------------------------------*/
2553 /* findLabelBackwards: walks back through the iCode chain looking */
2554 /* for the given label. Returns number of iCode instructions */
2555 /* between that label and given ic. */
2556 /* Returns zero if label not found. */
2557 /*-----------------------------------------------------------------*/
2558 static int findLabelBackwards(iCode *ic, int key)
2567 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2569 /* printf("findLabelBackwards = %d\n", count); */
2577 /*-----------------------------------------------------------------*/
2578 /* genPlusIncr :- does addition with increment if possible */
2579 /*-----------------------------------------------------------------*/
2580 static bool genPlusIncr (iCode *ic)
2582 unsigned int icount ;
2583 unsigned int size = getDataSize(IC_RESULT(ic));
2585 /* will try to generate an increment */
2586 /* if the right side is not a literal
2588 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2591 /* if the literal value of the right hand side
2592 is greater than 4 then it is not worth it */
2593 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2596 /* if increment 16 bits in register */
2598 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2599 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2600 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2607 /* If the next instruction is a goto and the goto target
2608 * is <= 5 instructions previous to this, we can generate
2609 * jumps straight to that target.
2611 if (ic->next && ic->next->op == GOTO
2612 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2613 && labelRange <= 5 )
2615 emitcode(";", "tail increment optimized (range %d)", labelRange);
2616 tlbl = IC_LABEL(ic->next);
2621 tlbl = newiTempLabel(NULL);
2624 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2625 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2626 IS_AOP_PREG(IC_RESULT(ic)))
2627 emitcode("cjne","%s,#0x00,%05d$"
2628 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2631 emitcode("clr","a");
2632 emitcode("cjne","a,%s,%05d$"
2633 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2637 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2640 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2641 IS_AOP_PREG(IC_RESULT(ic)))
2642 emitcode("cjne","%s,#0x00,%05d$"
2643 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2646 emitcode("cjne","a,%s,%05d$"
2647 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2650 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2654 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2655 IS_AOP_PREG(IC_RESULT(ic)))
2656 emitcode("cjne","%s,#0x00,%05d$"
2657 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2660 emitcode("cjne","a,%s,%05d$"
2661 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2664 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2669 emitcode("","%05d$:",tlbl->key+100);
2674 /* if the sizes are greater than 1 then we cannot */
2675 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2676 AOP_SIZE(IC_LEFT(ic)) > 1 )
2679 /* we can if the aops of the left & result match or
2680 if they are in registers and the registers are the
2683 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2684 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2685 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2688 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2689 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2690 aopPut(AOP(IC_RESULT(ic)),"a",0);
2694 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2703 /*-----------------------------------------------------------------*/
2704 /* outBitAcc - output a bit in acc */
2705 /*-----------------------------------------------------------------*/
2706 static void outBitAcc(operand *result)
2708 symbol *tlbl = newiTempLabel(NULL);
2709 /* if the result is a bit */
2710 if (AOP_TYPE(result) == AOP_CRY){
2711 aopPut(AOP(result),"a",0);
2714 emitcode("jz","%05d$",tlbl->key+100);
2715 emitcode("mov","a,%s",one);
2716 emitcode("","%05d$:",tlbl->key+100);
2721 /*-----------------------------------------------------------------*/
2722 /* genPlusBits - generates code for addition of two bits */
2723 /*-----------------------------------------------------------------*/
2724 static void genPlusBits (iCode *ic)
2726 D(emitcode(";", "genPlusBits "););
2727 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2728 symbol *lbl = newiTempLabel(NULL);
2729 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2730 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2731 emitcode("cpl","c");
2732 emitcode("","%05d$:",(lbl->key+100));
2733 outBitC(IC_RESULT(ic));
2736 emitcode("clr","a");
2737 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2738 emitcode("rlc","a");
2739 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2740 emitcode("addc","a,#0x00");
2741 outAcc(IC_RESULT(ic));
2745 static void adjustArithmeticResult(iCode *ic)
2747 if (opIsGptr(IC_RESULT(ic)) &&
2748 opIsGptr(IC_LEFT(ic)) &&
2749 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2751 aopPut(AOP(IC_RESULT(ic)),
2752 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2756 if (opIsGptr(IC_RESULT(ic)) &&
2757 opIsGptr(IC_RIGHT(ic)) &&
2758 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2760 aopPut(AOP(IC_RESULT(ic)),
2761 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2765 if (opIsGptr(IC_RESULT(ic)) &&
2766 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2767 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2768 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2769 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2771 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2772 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2776 #define AOP_OP_3(ic) \
2777 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2778 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2779 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2780 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2781 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2783 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2785 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2788 #define AOP_SET_LOCALS(ic) \
2789 left = IC_LEFT(ic); \
2790 right = IC_RIGHT(ic); \
2791 result = IC_RESULT(ic);
2793 /*-----------------------------------------------------------------*/
2794 /* genPlus - generates code for addition */
2795 /*-----------------------------------------------------------------*/
2796 static void genPlus (iCode *ic)
2798 int size, offset = 0;
2799 bool pushResult = FALSE;
2802 D(emitcode(";", "genPlus "););
2804 /* special cases :- */
2806 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2807 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2808 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2809 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2815 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR);
2817 /* if literal, literal on the right or
2818 if left requires ACC or right is already
2820 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2821 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2822 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2823 operand *t = IC_RIGHT(ic);
2824 IC_RIGHT(ic) = IC_LEFT(ic);
2828 /* if both left & right are in bit
2830 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2831 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2836 /* if left in bit space & right literal */
2837 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2838 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2839 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2840 /* if result in bit space */
2841 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2842 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2843 emitcode("cpl","c");
2844 outBitC(IC_RESULT(ic));
2846 size = getDataSize(IC_RESULT(ic));
2848 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
2849 emitcode("addc","a,#00");
2850 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2856 /* if I can do an increment instead
2857 of add then GOOD for ME */
2858 if (genPlusIncr (ic) == TRUE)
2862 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
2865 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2866 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
2868 emitcode("add","a,%s",
2869 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
2871 emitcode("addc","a,%s",
2872 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
2874 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
2876 emitcode("add","a,%s",
2877 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
2879 emitcode("addc","a,%s",
2880 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
2884 aopPut(AOP(IC_RESULT(ic)),"a",offset);
2888 emitcode("push", "acc");
2895 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2897 size = getDataSize(IC_LEFT(ic));
2898 rSize = getDataSize(IC_RESULT(ic));
2900 /* If the pushed data is bigger than the result,
2901 * simply discard unused bytes. Icky, but works.
2903 * Should we throw a warning here? We're losing data...
2905 while (size > rSize)
2907 D(emitcode(";", "discarding unused result byte."););
2908 emitcode("pop", "acc");
2914 emitcode("clr", "a");
2915 /* Conversly, we haven't pushed enough here.
2916 * just zero-pad, and all is well.
2918 while (size < rSize)
2920 emitcode("push", "acc");
2928 emitcode("pop", "acc");
2929 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
2933 adjustArithmeticResult(ic);
2936 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2937 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2938 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2941 /*-----------------------------------------------------------------*/
2942 /* genMinusDec :- does subtraction with deccrement if possible */
2943 /*-----------------------------------------------------------------*/
2944 static bool genMinusDec (iCode *ic)
2946 unsigned int icount ;
2947 unsigned int size = getDataSize(IC_RESULT(ic));
2949 /* will try to generate an increment */
2950 /* if the right side is not a literal
2952 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2955 /* if the literal value of the right hand side
2956 is greater than 4 then it is not worth it */
2957 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2960 /* if decrement 16 bits in register */
2961 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2962 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2963 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2970 /* If the next instruction is a goto and the goto target
2971 * is <= 5 instructions previous to this, we can generate
2972 * jumps straight to that target.
2974 if (ic->next && ic->next->op == GOTO
2975 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2976 && labelRange <= 5 )
2978 emitcode(";", "tail decrement optimized (range %d)", labelRange);
2979 tlbl = IC_LABEL(ic->next);
2984 tlbl = newiTempLabel(NULL);
2988 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2989 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2990 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2991 IS_AOP_PREG(IC_RESULT(ic)))
2992 emitcode("cjne","%s,#0xff,%05d$"
2993 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2996 emitcode("mov","a,#0xff");
2997 emitcode("cjne","a,%s,%05d$"
2998 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3001 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3004 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3005 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3006 IS_AOP_PREG(IC_RESULT(ic)))
3007 emitcode("cjne","%s,#0xff,%05d$"
3008 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3011 emitcode("cjne","a,%s,%05d$"
3012 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3015 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3019 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3020 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3021 IS_AOP_PREG(IC_RESULT(ic)))
3022 emitcode("cjne","%s,#0xff,%05d$"
3023 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3026 emitcode("cjne","a,%s,%05d$"
3027 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3030 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3034 emitcode("","%05d$:",tlbl->key+100);
3039 /* if the sizes are greater than 1 then we cannot */
3040 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3041 AOP_SIZE(IC_LEFT(ic)) > 1 )
3044 /* we can if the aops of the left & result match or
3045 if they are in registers and the registers are the
3048 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3049 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3050 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3053 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3061 /*-----------------------------------------------------------------*/
3062 /* addSign - complete with sign */
3063 /*-----------------------------------------------------------------*/
3064 static void addSign(operand *result, int offset, int sign)
3066 int size = (getDataSize(result) - offset);
3069 emitcode("rlc","a");
3070 emitcode("subb","a,acc");
3072 aopPut(AOP(result),"a",offset++);
3075 aopPut(AOP(result),zero,offset++);
3079 /*-----------------------------------------------------------------*/
3080 /* genMinusBits - generates code for subtraction of two bits */
3081 /*-----------------------------------------------------------------*/
3082 static void genMinusBits (iCode *ic)
3084 symbol *lbl = newiTempLabel(NULL);
3086 D(emitcode(";", "genMinusBits "););
3088 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3089 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3090 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3091 emitcode("cpl","c");
3092 emitcode("","%05d$:",(lbl->key+100));
3093 outBitC(IC_RESULT(ic));
3096 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3097 emitcode("subb","a,acc");
3098 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3099 emitcode("inc","a");
3100 emitcode("","%05d$:",(lbl->key+100));
3101 aopPut(AOP(IC_RESULT(ic)),"a",0);
3102 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3106 /*-----------------------------------------------------------------*/
3107 /* genMinus - generates code for subtraction */
3108 /*-----------------------------------------------------------------*/
3109 static void genMinus (iCode *ic)
3111 int size, offset = 0;
3113 unsigned long lit = 0L;
3114 bool pushResult = FALSE;
3116 D(emitcode(";", "genMinus "););
3118 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3119 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3120 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3121 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3127 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3129 /* special cases :- */
3130 /* if both left & right are in bit space */
3131 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3132 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3137 /* if I can do an decrement instead
3138 of subtract then GOOD for ME */
3139 if (genMinusDec (ic) == TRUE)
3144 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3146 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3150 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3155 /* if literal, add a,#-lit, else normal subb */
3157 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3158 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3159 emitcode("subb","a,%s",
3160 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3162 /* first add without previous c */
3164 emitcode("add","a,#0x%02x",
3165 (unsigned int)(lit & 0x0FFL));
3167 emitcode("addc","a,#0x%02x",
3168 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3173 emitcode("push", "acc");
3177 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3184 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3186 size = getDataSize(IC_LEFT(ic));
3187 rSize = getDataSize(IC_RESULT(ic));
3189 /* If the pushed data is bigger than the result,
3190 * simply discard unused bytes. Icky, but works.
3192 * Should we throw a warning here? We're losing data...
3194 while (size > getDataSize(IC_RESULT(ic)))
3196 emitcode(";", "discarding unused result byte.");
3197 emitcode("pop", "acc");
3203 emitcode("clr", "a");
3204 /* Conversly, we haven't pushed enough here.
3205 * just zero-pad, and all is well.
3207 while (size < rSize)
3209 emitcode("push", "acc");
3217 emitcode("pop", "acc");
3218 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3222 adjustArithmeticResult(ic);
3225 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3226 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3227 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3231 /*-----------------------------------------------------------------*/
3232 /* genMultbits :- multiplication of bits */
3233 /*-----------------------------------------------------------------*/
3234 static void genMultbits (operand *left,
3238 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3239 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3244 /*-----------------------------------------------------------------*/
3245 /* genMultOneByte : 8 bit multiplication & division */
3246 /*-----------------------------------------------------------------*/
3247 static void genMultOneByte (operand *left,
3251 link *opetype = operandType(result);
3256 /* (if two literals, the value is computed before) */
3257 /* if one literal, literal on the right */
3258 if (AOP_TYPE(left) == AOP_LIT){
3264 size = AOP_SIZE(result);
3265 /* signed or unsigned */
3266 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3267 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3269 emitcode("mul","ab");
3270 /* if result size = 1, mul signed = mul unsigned */
3271 aopPut(AOP(result),"a",0);
3273 if (SPEC_USIGN(opetype)){
3274 aopPut(AOP(result),"b",1);
3276 /* for filling the MSBs */
3277 emitcode("clr","a");
3280 emitcode("mov","a,b");
3282 /* adjust the MSB if left or right neg */
3284 /* if one literal */
3285 if (AOP_TYPE(right) == AOP_LIT){
3286 /* AND literal negative */
3287 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3288 /* adjust MSB (c==0 after mul) */
3289 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3293 lbl = newiTempLabel(NULL);
3294 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3295 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3296 emitcode("","%05d$:",(lbl->key+100));
3297 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3298 lbl = newiTempLabel(NULL);
3299 emitcode("jc","%05d$",(lbl->key+100));
3300 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3301 emitcode("","%05d$:",(lbl->key+100));
3304 lbl = newiTempLabel(NULL);
3305 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3306 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3307 emitcode("","%05d$:",(lbl->key+100));
3308 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3309 lbl = newiTempLabel(NULL);
3310 emitcode("jc","%05d$",(lbl->key+100));
3311 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3312 emitcode("","%05d$:",(lbl->key+100));
3314 aopPut(AOP(result),"a",1);
3317 emitcode("rlc","a");
3318 emitcode("subb","a,acc");
3325 aopPut(AOP(result),"a",offset++);
3329 /*-----------------------------------------------------------------*/
3330 /* genMult - generates code for multiplication */
3331 /*-----------------------------------------------------------------*/
3332 static void genMult (iCode *ic)
3334 operand *left = IC_LEFT(ic);
3335 operand *right = IC_RIGHT(ic);
3336 operand *result= IC_RESULT(ic);
3338 D(emitcode(";", "genMult "););
3340 /* assign the amsops */
3343 aopOp (left,ic,FALSE, FALSE);
3344 aopOp (right,ic,FALSE, TRUE);
3345 aopOp (result,ic,TRUE, FALSE);
3348 /* special cases first */
3350 if (AOP_TYPE(left) == AOP_CRY &&
3351 AOP_TYPE(right)== AOP_CRY) {
3352 genMultbits(left,right,result);
3356 /* if both are of size == 1 */
3357 if (AOP_SIZE(left) == 1 &&
3358 AOP_SIZE(right) == 1 ) {
3359 genMultOneByte(left,right,result);
3363 /* should have been converted to function call */
3367 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3368 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3369 freeAsmop(result,NULL,ic,TRUE);
3372 /*-----------------------------------------------------------------*/
3373 /* genDivbits :- division of bits */
3374 /*-----------------------------------------------------------------*/
3375 static void genDivbits (operand *left,
3382 /* the result must be bit */
3383 LOAD_AB_FOR_DIV(left, right, l);
3384 emitcode("div","ab");
3385 emitcode("rrc","a");
3386 aopPut(AOP(result),"c",0);
3389 /*-----------------------------------------------------------------*/
3390 /* genDivOneByte : 8 bit division */
3391 /*-----------------------------------------------------------------*/
3392 static void genDivOneByte (operand *left,
3396 link *opetype = operandType(result);
3401 size = AOP_SIZE(result) - 1;
3403 /* signed or unsigned */
3404 if (SPEC_USIGN(opetype)) {
3405 /* unsigned is easy */
3406 LOAD_AB_FOR_DIV(left, right, l);
3407 emitcode("div","ab");
3408 aopPut(AOP(result),"a",0);
3410 aopPut(AOP(result),zero,offset++);
3414 /* signed is a little bit more difficult */
3416 /* save the signs of the operands */
3417 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3419 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3420 emitcode("push","acc"); /* save it on the stack */
3422 /* now sign adjust for both left & right */
3423 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3425 lbl = newiTempLabel(NULL);
3426 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3427 emitcode("cpl","a");
3428 emitcode("inc","a");
3429 emitcode("","%05d$:",(lbl->key+100));
3430 emitcode("mov","b,a");
3432 /* sign adjust left side */
3433 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3436 lbl = newiTempLabel(NULL);
3437 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3438 emitcode("cpl","a");
3439 emitcode("inc","a");
3440 emitcode("","%05d$:",(lbl->key+100));
3442 /* now the division */
3443 emitcode("nop", "; workaround for DS80C390 div bug.");
3444 emitcode("div","ab");
3445 /* we are interested in the lower order
3447 emitcode("mov","b,a");
3448 lbl = newiTempLabel(NULL);
3449 emitcode("pop","acc");
3450 /* if there was an over flow we don't
3451 adjust the sign of the result */
3452 emitcode("jb","ov,%05d$",(lbl->key+100));
3453 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3455 emitcode("clr","a");
3456 emitcode("subb","a,b");
3457 emitcode("mov","b,a");
3458 emitcode("","%05d$:",(lbl->key+100));
3460 /* now we are done */
3461 aopPut(AOP(result),"b",0);
3463 emitcode("mov","c,b.7");
3464 emitcode("subb","a,acc");
3467 aopPut(AOP(result),"a",offset++);
3471 /*-----------------------------------------------------------------*/
3472 /* genDiv - generates code for division */
3473 /*-----------------------------------------------------------------*/
3474 static void genDiv (iCode *ic)
3476 operand *left = IC_LEFT(ic);
3477 operand *right = IC_RIGHT(ic);
3478 operand *result= IC_RESULT(ic);
3480 D(emitcode(";", "genDiv "););
3482 /* assign the amsops */
3485 aopOp (left,ic,FALSE, FALSE);
3486 aopOp (right,ic,FALSE, TRUE);
3487 aopOp (result,ic,TRUE, FALSE);
3490 /* special cases first */
3492 if (AOP_TYPE(left) == AOP_CRY &&
3493 AOP_TYPE(right)== AOP_CRY) {
3494 genDivbits(left,right,result);
3498 /* if both are of size == 1 */
3499 if (AOP_SIZE(left) == 1 &&
3500 AOP_SIZE(right) == 1 ) {
3501 genDivOneByte(left,right,result);
3505 /* should have been converted to function call */
3508 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3509 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3510 freeAsmop(result,NULL,ic,TRUE);
3513 /*-----------------------------------------------------------------*/
3514 /* genModbits :- modulus of bits */
3515 /*-----------------------------------------------------------------*/
3516 static void genModbits (operand *left,
3523 /* the result must be bit */
3524 LOAD_AB_FOR_DIV(left, right, l);
3525 emitcode("div","ab");
3526 emitcode("mov","a,b");
3527 emitcode("rrc","a");
3528 aopPut(AOP(result),"c",0);
3531 /*-----------------------------------------------------------------*/
3532 /* genModOneByte : 8 bit modulus */
3533 /*-----------------------------------------------------------------*/
3534 static void genModOneByte (operand *left,
3538 link *opetype = operandType(result);
3542 /* signed or unsigned */
3543 if (SPEC_USIGN(opetype)) {
3544 /* unsigned is easy */
3545 LOAD_AB_FOR_DIV(left, right, l);
3546 emitcode("div","ab");
3547 aopPut(AOP(result),"b",0);
3551 /* signed is a little bit more difficult */
3553 /* save the signs of the operands */
3554 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3557 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3558 emitcode("push","acc"); /* save it on the stack */
3560 /* now sign adjust for both left & right */
3561 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3564 lbl = newiTempLabel(NULL);
3565 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3566 emitcode("cpl","a");
3567 emitcode("inc","a");
3568 emitcode("","%05d$:",(lbl->key+100));
3569 emitcode("mov","b,a");
3571 /* sign adjust left side */
3572 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3575 lbl = newiTempLabel(NULL);
3576 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3577 emitcode("cpl","a");
3578 emitcode("inc","a");
3579 emitcode("","%05d$:",(lbl->key+100));
3581 /* now the multiplication */
3582 emitcode("nop", "; workaround for DS80C390 div bug.");
3583 emitcode("div","ab");
3584 /* we are interested in the lower order
3586 lbl = newiTempLabel(NULL);
3587 emitcode("pop","acc");
3588 /* if there was an over flow we don't
3589 adjust the sign of the result */
3590 emitcode("jb","ov,%05d$",(lbl->key+100));
3591 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3593 emitcode("clr","a");
3594 emitcode("subb","a,b");
3595 emitcode("mov","b,a");
3596 emitcode("","%05d$:",(lbl->key+100));
3598 /* now we are done */
3599 aopPut(AOP(result),"b",0);
3603 /*-----------------------------------------------------------------*/
3604 /* genMod - generates code for division */
3605 /*-----------------------------------------------------------------*/
3606 static void genMod (iCode *ic)
3608 operand *left = IC_LEFT(ic);
3609 operand *right = IC_RIGHT(ic);
3610 operand *result= IC_RESULT(ic);
3612 D(emitcode(";", "genMod "););
3614 /* assign the amsops */
3617 aopOp (left,ic,FALSE, FALSE);
3618 aopOp (right,ic,FALSE, TRUE);
3619 aopOp (result,ic,TRUE, FALSE);
3622 /* special cases first */
3624 if (AOP_TYPE(left) == AOP_CRY &&
3625 AOP_TYPE(right)== AOP_CRY) {
3626 genModbits(left,right,result);
3630 /* if both are of size == 1 */
3631 if (AOP_SIZE(left) == 1 &&
3632 AOP_SIZE(right) == 1 ) {
3633 genModOneByte(left,right,result);
3637 /* should have been converted to function call */
3641 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3642 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3643 freeAsmop(result,NULL,ic,TRUE);
3646 /*-----------------------------------------------------------------*/
3647 /* genIfxJump :- will create a jump depending on the ifx */
3648 /*-----------------------------------------------------------------*/
3649 static void genIfxJump (iCode *ic, char *jval)
3652 symbol *tlbl = newiTempLabel(NULL);
3655 D(emitcode(";", "genIfxJump "););
3657 /* if true label then we jump if condition
3659 if ( IC_TRUE(ic) ) {
3661 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3662 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3665 /* false label is present */
3666 jlbl = IC_FALSE(ic) ;
3667 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3668 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3670 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3671 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3673 emitcode(inst,"%05d$",tlbl->key+100);
3674 emitcode("ljmp","%05d$",jlbl->key+100);
3675 emitcode("","%05d$:",tlbl->key+100);
3677 /* mark the icode as generated */
3681 /*-----------------------------------------------------------------*/
3682 /* genCmp :- greater or less than comparison */
3683 /*-----------------------------------------------------------------*/
3684 static void genCmp (operand *left,operand *right,
3685 operand *result, iCode *ifx, int sign)
3687 int size, offset = 0 ;
3688 unsigned long lit = 0L;
3689 bool swappedOps = FALSE;
3691 D(emitcode(";", "genCmp"););
3694 /* If left if lit and right isn't, swap 'em. */
3695 if (AOP_TYPE(left) == AOP_LIT &&
3696 AOP_TYPE(right) != AOP_LIT)
3698 operand *tmp = left;
3701 D(emitcode(";", "kevin literal hack"););
3702 swappedOps = !swappedOps;
3705 if (AOP_NEEDSACC(right))
3707 if (AOP_NEEDSACC(left))
3709 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3710 "both CMP operands need ACC!");
3715 operand *tmp = left;
3718 D(emitcode(";", "kevin ACC hack"););
3719 swappedOps = !swappedOps;
3724 /* if left & right are bit variables */
3725 if (AOP_TYPE(left) == AOP_CRY &&
3726 AOP_TYPE(right) == AOP_CRY ) {
3727 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3728 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3730 /* subtract right from left if at the
3731 end the carry flag is set then we know that
3732 left is greater than right */
3733 size = max(AOP_SIZE(left),AOP_SIZE(right));
3735 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3736 if((size == 1) && !sign &&
3737 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3738 symbol *lbl = newiTempLabel(NULL);
3739 emitcode("cjne","%s,%s,%05d$",
3740 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3741 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3743 emitcode("","%05d$:",lbl->key+100);
3745 if(AOP_TYPE(right) == AOP_LIT){
3746 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3747 /* optimize if(x < 0) or if(x >= 0) */
3753 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3754 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3755 genIfxJump (ifx,"acc.7");
3759 emitcode("rlc","a");
3767 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3768 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3769 emitcode(";", "genCmp #2");
3770 if (sign && (size == 0))
3772 emitcode(";", "genCmp #3");
3773 emitcode("xrl","a,#0x80");
3774 if (AOP_TYPE(right) == AOP_LIT)
3776 unsigned long lit = (unsigned long)
3777 floatFromVal(AOP(right)->aopu.aop_lit);
3778 emitcode(";", "genCmp #3.1");
3779 emitcode("subb","a,#0x%02x",
3780 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3784 emitcode(";", "genCmp #3.2");
3785 if (AOP_NEEDSACC(right))
3787 emitcode("push", "acc");
3789 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3790 FALSE,FALSE,FALSE));
3791 emitcode("xrl","b,#0x80");
3792 if (AOP_NEEDSACC(right))
3794 emitcode("pop", "acc");
3796 emitcode("subb","a,b");
3803 emitcode(";", "genCmp #4");
3804 if (AOP_NEEDSACC(right))
3807 emitcode(";", "genCmp #4.1");
3808 emitcode("xch", "a, b");
3809 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3810 emitcode("xch", "a, b");
3815 emitcode(";", "genCmp #4.2");
3816 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
3819 emitcode("subb","a,%s",s);
3828 D(emitcode(";","kevHack: flip carry."););
3829 emitcode("cpl", "c");
3832 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3835 /* if the result is used in the next
3836 ifx conditional branch then generate
3837 code a little differently */
3839 genIfxJump (ifx,"c");
3842 /* leave the result in acc */
3846 /*-----------------------------------------------------------------*/
3847 /* genCmpGt :- greater than comparison */
3848 /*-----------------------------------------------------------------*/
3849 static void genCmpGt (iCode *ic, iCode *ifx)
3851 operand *left, *right, *result;
3852 link *letype , *retype;
3855 D(emitcode(";", "genCmpGt "););
3858 right= IC_RIGHT(ic);
3859 result = IC_RESULT(ic);
3861 letype = getSpec(operandType(left));
3862 retype =getSpec(operandType(right));
3863 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3864 /* assign the amsops */
3867 aopOp (left,ic,FALSE, TRUE);
3868 aopOp (right,ic,FALSE, FALSE);
3869 aopOp (result,ic,TRUE, FALSE);
3872 genCmp(right, left, result, ifx, sign);
3874 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3875 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3876 freeAsmop(result,NULL,ic,TRUE);
3879 /*-----------------------------------------------------------------*/
3880 /* genCmpLt - less than comparisons */
3881 /*-----------------------------------------------------------------*/
3882 static void genCmpLt (iCode *ic, iCode *ifx)
3884 operand *left, *right, *result;
3885 link *letype , *retype;
3888 D(emitcode(";", "genCmpLt "););
3891 right= IC_RIGHT(ic);
3892 result = IC_RESULT(ic);
3894 letype = getSpec(operandType(left));
3895 retype =getSpec(operandType(right));
3896 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3898 /* assign the amsops */
3901 aopOp (left,ic,FALSE, FALSE);
3902 aopOp (right,ic,FALSE, TRUE);
3903 aopOp (result,ic,TRUE, FALSE);
3906 genCmp(left, right, result, ifx, sign);
3908 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3909 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3910 freeAsmop(result,NULL,ic,TRUE);
3913 /*-----------------------------------------------------------------*/
3914 /* gencjneshort - compare and jump if not equal */
3915 /*-----------------------------------------------------------------*/
3916 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3918 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3920 unsigned long lit = 0L;
3922 D(emitcode(";", "gencjneshort"););
3924 /* if the left side is a literal or
3925 if the right is in a pointer register and left
3927 if ((AOP_TYPE(left) == AOP_LIT) ||
3928 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3934 if(AOP_TYPE(right) == AOP_LIT)
3935 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3937 if (opIsGptr(left) || opIsGptr(right))
3939 /* We are comparing a generic pointer to something.
3940 * Exclude the generic type byte from the comparison.
3943 D(emitcode(";", "cjneshort: generic ptr special case.");)
3947 /* if the right side is a literal then anything goes */
3948 if (AOP_TYPE(right) == AOP_LIT &&
3949 AOP_TYPE(left) != AOP_DIR ) {
3951 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
3953 emitcode("cjne","a,%s,%05d$",
3954 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3960 /* if the right side is in a register or in direct space or
3961 if the left is a pointer register & right is not */
3962 else if (AOP_TYPE(right) == AOP_REG ||
3963 AOP_TYPE(right) == AOP_DIR ||
3964 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3965 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3967 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3968 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3969 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3970 emitcode("jnz","%05d$",lbl->key+100);
3972 emitcode("cjne","a,%s,%05d$",
3973 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
3978 /* right is a pointer reg need both a & b */
3980 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
3982 emitcode("mov","b,%s",l);
3983 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
3984 emitcode("cjne","a,b,%05d$",lbl->key+100);
3990 /*-----------------------------------------------------------------*/
3991 /* gencjne - compare and jump if not equal */
3992 /*-----------------------------------------------------------------*/
3993 static void gencjne(operand *left, operand *right, symbol *lbl)
3995 symbol *tlbl = newiTempLabel(NULL);
3997 D(emitcode(";", "gencjne"););
3999 gencjneshort(left, right, lbl);
4001 emitcode("mov","a,%s",one);
4002 emitcode("sjmp","%05d$",tlbl->key+100);
4003 emitcode("","%05d$:",lbl->key+100);
4004 emitcode("clr","a");
4005 emitcode("","%05d$:",tlbl->key+100);
4008 /*-----------------------------------------------------------------*/
4009 /* genCmpEq - generates code for equal to */
4010 /*-----------------------------------------------------------------*/
4011 static void genCmpEq (iCode *ic, iCode *ifx)
4013 operand *left, *right, *result;
4015 D(emitcode(";", "genCmpEq "););
4020 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4021 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4022 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4025 /* if literal, literal on the right or
4026 if the right is in a pointer register and left
4028 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4029 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4030 operand *t = IC_RIGHT(ic);
4031 IC_RIGHT(ic) = IC_LEFT(ic);
4035 if(ifx && !AOP_SIZE(result)){
4037 /* if they are both bit variables */
4038 if (AOP_TYPE(left) == AOP_CRY &&
4039 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4040 if(AOP_TYPE(right) == AOP_LIT){
4041 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4043 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4044 emitcode("cpl","c");
4045 } else if(lit == 1L) {
4046 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4048 emitcode("clr","c");
4050 /* AOP_TYPE(right) == AOP_CRY */
4052 symbol *lbl = newiTempLabel(NULL);
4053 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4054 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4055 emitcode("cpl","c");
4056 emitcode("","%05d$:",(lbl->key+100));
4058 /* if true label then we jump if condition
4060 tlbl = newiTempLabel(NULL);
4061 if ( IC_TRUE(ifx) ) {
4062 emitcode("jnc","%05d$",tlbl->key+100);
4063 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4065 emitcode("jc","%05d$",tlbl->key+100);
4066 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4068 emitcode("","%05d$:",tlbl->key+100);
4070 tlbl = newiTempLabel(NULL);
4071 gencjneshort(left, right, tlbl);
4072 if ( IC_TRUE(ifx) ) {
4073 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4074 emitcode("","%05d$:",tlbl->key+100);
4076 symbol *lbl = newiTempLabel(NULL);
4077 emitcode("sjmp","%05d$",lbl->key+100);
4078 emitcode("","%05d$:",tlbl->key+100);
4079 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4080 emitcode("","%05d$:",lbl->key+100);
4083 /* mark the icode as generated */
4088 /* if they are both bit variables */
4089 if (AOP_TYPE(left) == AOP_CRY &&
4090 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4091 if(AOP_TYPE(right) == AOP_LIT){
4092 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4094 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4095 emitcode("cpl","c");
4096 } else if(lit == 1L) {
4097 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4099 emitcode("clr","c");
4101 /* AOP_TYPE(right) == AOP_CRY */
4103 symbol *lbl = newiTempLabel(NULL);
4104 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4105 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4106 emitcode("cpl","c");
4107 emitcode("","%05d$:",(lbl->key+100));
4110 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4115 genIfxJump (ifx,"c");
4118 /* if the result is used in an arithmetic operation
4119 then put the result in place */
4122 gencjne(left,right,newiTempLabel(NULL));
4123 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4124 aopPut(AOP(result),"a",0);
4128 genIfxJump (ifx,"a");
4131 /* if the result is used in an arithmetic operation
4132 then put the result in place */
4133 if (AOP_TYPE(result) != AOP_CRY)
4135 /* leave the result in acc */
4139 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4140 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4141 freeAsmop(result,NULL,ic,TRUE);
4144 /*-----------------------------------------------------------------*/
4145 /* ifxForOp - returns the icode containing the ifx for operand */
4146 /*-----------------------------------------------------------------*/
4147 static iCode *ifxForOp ( operand *op, iCode *ic )
4149 /* if true symbol then needs to be assigned */
4150 if (IS_TRUE_SYMOP(op))
4153 /* if this has register type condition and
4154 the next instruction is ifx with the same operand
4155 and live to of the operand is upto the ifx only then */
4157 ic->next->op == IFX &&
4158 IC_COND(ic->next)->key == op->key &&
4159 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4164 /*-----------------------------------------------------------------*/
4165 /* genAndOp - for && operation */
4166 /*-----------------------------------------------------------------*/
4167 static void genAndOp (iCode *ic)
4169 operand *left,*right, *result;
4172 D(emitcode(";", "genAndOp "););
4174 /* note here that && operations that are in an
4175 if statement are taken away by backPatchLabels
4176 only those used in arthmetic operations remain */
4180 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4181 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4182 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4185 /* if both are bit variables */
4186 if (AOP_TYPE(left) == AOP_CRY &&
4187 AOP_TYPE(right) == AOP_CRY ) {
4188 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4189 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4192 tlbl = newiTempLabel(NULL);
4194 emitcode("jz","%05d$",tlbl->key+100);
4196 emitcode("","%05d$:",tlbl->key+100);
4200 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4201 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4202 freeAsmop(result,NULL,ic,TRUE);
4206 /*-----------------------------------------------------------------*/
4207 /* genOrOp - for || operation */
4208 /*-----------------------------------------------------------------*/
4209 static void genOrOp (iCode *ic)
4211 operand *left,*right, *result;
4214 D(emitcode(";", "genOrOp "););
4216 /* note here that || operations that are in an
4217 if statement are taken away by backPatchLabels
4218 only those used in arthmetic operations remain */
4222 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4223 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4224 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4227 /* if both are bit variables */
4228 if (AOP_TYPE(left) == AOP_CRY &&
4229 AOP_TYPE(right) == AOP_CRY ) {
4230 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4231 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4234 tlbl = newiTempLabel(NULL);
4236 emitcode("jnz","%05d$",tlbl->key+100);
4238 emitcode("","%05d$:",tlbl->key+100);
4242 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4243 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4244 freeAsmop(result,NULL,ic,TRUE);
4247 /*-----------------------------------------------------------------*/
4248 /* isLiteralBit - test if lit == 2^n */
4249 /*-----------------------------------------------------------------*/
4250 static int isLiteralBit(unsigned long lit)
4252 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4253 0x100L,0x200L,0x400L,0x800L,
4254 0x1000L,0x2000L,0x4000L,0x8000L,
4255 0x10000L,0x20000L,0x40000L,0x80000L,
4256 0x100000L,0x200000L,0x400000L,0x800000L,
4257 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4258 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4261 for(idx = 0; idx < 32; idx++)
4267 /*-----------------------------------------------------------------*/
4268 /* continueIfTrue - */
4269 /*-----------------------------------------------------------------*/
4270 static void continueIfTrue (iCode *ic)
4273 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4277 /*-----------------------------------------------------------------*/
4279 /*-----------------------------------------------------------------*/
4280 static void jumpIfTrue (iCode *ic)
4283 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4287 /*-----------------------------------------------------------------*/
4288 /* jmpTrueOrFalse - */
4289 /*-----------------------------------------------------------------*/
4290 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4292 // ugly but optimized by peephole
4294 symbol *nlbl = newiTempLabel(NULL);
4295 emitcode("sjmp","%05d$",nlbl->key+100);
4296 emitcode("","%05d$:",tlbl->key+100);
4297 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4298 emitcode("","%05d$:",nlbl->key+100);
4301 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4302 emitcode("","%05d$:",tlbl->key+100);
4307 /*-----------------------------------------------------------------*/
4308 /* genAnd - code for and */
4309 /*-----------------------------------------------------------------*/
4310 static void genAnd (iCode *ic, iCode *ifx)
4312 operand *left, *right, *result;
4314 unsigned long lit = 0L;
4318 D(emitcode(";", "genAnd "););
4323 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4324 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4325 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4329 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4331 AOP_TYPE(left), AOP_TYPE(right));
4332 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4334 AOP_SIZE(left), AOP_SIZE(right));
4337 /* if left is a literal & right is not then exchange them */
4338 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4339 AOP_NEEDSACC(left)) {
4340 operand *tmp = right ;
4345 /* if result = right then exchange them */
4346 if(sameRegs(AOP(result),AOP(right))){
4347 operand *tmp = right ;
4352 /* if right is bit then exchange them */
4353 if (AOP_TYPE(right) == AOP_CRY &&
4354 AOP_TYPE(left) != AOP_CRY){
4355 operand *tmp = right ;
4359 if(AOP_TYPE(right) == AOP_LIT)
4360 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4362 size = AOP_SIZE(result);
4365 // result = bit & yy;
4366 if (AOP_TYPE(left) == AOP_CRY){
4367 // c = bit & literal;
4368 if(AOP_TYPE(right) == AOP_LIT){
4370 if(size && sameRegs(AOP(result),AOP(left)))
4373 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4376 if(size && (AOP_TYPE(result) == AOP_CRY)){
4377 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4380 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4384 emitcode("clr","c");
4387 if (AOP_TYPE(right) == AOP_CRY){
4389 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4390 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4393 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4395 emitcode("rrc","a");
4396 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4404 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4405 genIfxJump(ifx, "c");
4409 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4410 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4411 if((AOP_TYPE(right) == AOP_LIT) &&
4412 (AOP_TYPE(result) == AOP_CRY) &&
4413 (AOP_TYPE(left) != AOP_CRY)){
4414 int posbit = isLiteralBit(lit);
4418 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4421 emitcode("mov","c,acc.%d",posbit&0x07);
4425 sprintf(buffer,"acc.%d",posbit&0x07);
4426 genIfxJump(ifx, buffer);
4431 symbol *tlbl = newiTempLabel(NULL);
4432 int sizel = AOP_SIZE(left);
4434 emitcode("setb","c");
4436 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4437 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4439 if((posbit = isLiteralBit(bytelit)) != 0)
4440 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4442 if(bytelit != 0x0FFL)
4443 emitcode("anl","a,%s",
4444 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4445 emitcode("jnz","%05d$",tlbl->key+100);
4450 // bit = left & literal
4452 emitcode("clr","c");
4453 emitcode("","%05d$:",tlbl->key+100);
4455 // if(left & literal)
4458 jmpTrueOrFalse(ifx, tlbl);
4466 /* if left is same as result */
4467 if(sameRegs(AOP(result),AOP(left))){
4468 for(;size--; offset++) {
4469 if(AOP_TYPE(right) == AOP_LIT){
4470 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4474 aopPut(AOP(result),zero,offset);
4476 if (IS_AOP_PREG(result)) {
4477 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4478 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4479 aopPut(AOP(result),"a",offset);
4481 emitcode("anl","%s,%s",
4482 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4483 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4485 if (AOP_TYPE(left) == AOP_ACC)
4486 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4488 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4489 if (IS_AOP_PREG(result)) {
4490 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4491 aopPut(AOP(result),"a",offset);
4494 emitcode("anl","%s,a",
4495 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4500 // left & result in different registers
4501 if(AOP_TYPE(result) == AOP_CRY){
4503 // if(size), result in bit
4504 // if(!size && ifx), conditional oper: if(left & right)
4505 symbol *tlbl = newiTempLabel(NULL);
4506 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4508 emitcode("setb","c");
4510 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4511 emitcode("anl","a,%s",
4512 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4513 emitcode("jnz","%05d$",tlbl->key+100);
4518 emitcode("","%05d$:",tlbl->key+100);
4521 jmpTrueOrFalse(ifx, tlbl);
4523 for(;(size--);offset++) {
4525 // result = left & right
4526 if(AOP_TYPE(right) == AOP_LIT){
4527 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4529 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4532 } else if(bytelit == 0){
4533 aopPut(AOP(result),zero,offset);
4537 // faster than result <- left, anl result,right
4538 // and better if result is SFR
4539 if (AOP_TYPE(left) == AOP_ACC)
4540 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4542 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4543 emitcode("anl","a,%s",
4544 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4546 aopPut(AOP(result),"a",offset);
4552 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4553 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4554 freeAsmop(result,NULL,ic,TRUE);
4557 /*-----------------------------------------------------------------*/
4558 /* genOr - code for or */
4559 /*-----------------------------------------------------------------*/
4560 static void genOr (iCode *ic, iCode *ifx)
4562 operand *left, *right, *result;
4564 unsigned long lit = 0L;
4566 D(emitcode(";", "genOr "););
4571 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4572 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4573 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4577 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4579 AOP_TYPE(left), AOP_TYPE(right));
4580 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4582 AOP_SIZE(left), AOP_SIZE(right));
4585 /* if left is a literal & right is not then exchange them */
4586 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4587 AOP_NEEDSACC(left)) {
4588 operand *tmp = right ;
4593 /* if result = right then exchange them */
4594 if(sameRegs(AOP(result),AOP(right))){
4595 operand *tmp = right ;
4600 /* if right is bit then exchange them */
4601 if (AOP_TYPE(right) == AOP_CRY &&
4602 AOP_TYPE(left) != AOP_CRY){
4603 operand *tmp = right ;
4607 if(AOP_TYPE(right) == AOP_LIT)
4608 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4610 size = AOP_SIZE(result);
4614 if (AOP_TYPE(left) == AOP_CRY){
4615 if(AOP_TYPE(right) == AOP_LIT){
4616 // c = bit & literal;
4618 // lit != 0 => result = 1
4619 if(AOP_TYPE(result) == AOP_CRY){
4621 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4623 continueIfTrue(ifx);
4626 emitcode("setb","c");
4628 // lit == 0 => result = left
4629 if(size && sameRegs(AOP(result),AOP(left)))
4631 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4634 if (AOP_TYPE(right) == AOP_CRY){
4636 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4637 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4641 symbol *tlbl = newiTempLabel(NULL);
4642 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4643 emitcode("setb","c");
4644 emitcode("jb","%s,%05d$",
4645 AOP(left)->aopu.aop_dir,tlbl->key+100);
4647 emitcode("jnz","%05d$",tlbl->key+100);
4648 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4649 jmpTrueOrFalse(ifx, tlbl);
4653 emitcode("","%05d$:",tlbl->key+100);
4662 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4663 genIfxJump(ifx, "c");
4667 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4668 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4669 if((AOP_TYPE(right) == AOP_LIT) &&
4670 (AOP_TYPE(result) == AOP_CRY) &&
4671 (AOP_TYPE(left) != AOP_CRY)){
4675 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4677 continueIfTrue(ifx);
4680 // lit = 0, result = boolean(left)
4682 emitcode("setb","c");
4685 symbol *tlbl = newiTempLabel(NULL);
4686 emitcode("jnz","%05d$",tlbl->key+100);
4688 emitcode("","%05d$:",tlbl->key+100);
4690 genIfxJump (ifx,"a");
4698 /* if left is same as result */
4699 if(sameRegs(AOP(result),AOP(left))){
4700 for(;size--; offset++) {
4701 if(AOP_TYPE(right) == AOP_LIT){
4702 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4705 if (IS_AOP_PREG(left)) {
4706 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4707 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4708 aopPut(AOP(result),"a",offset);
4710 emitcode("orl","%s,%s",
4711 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4712 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4714 if (AOP_TYPE(left) == AOP_ACC)
4715 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4717 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4718 if (IS_AOP_PREG(left)) {
4719 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4720 aopPut(AOP(result),"a",offset);
4722 emitcode("orl","%s,a",
4723 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4728 // left & result in different registers
4729 if(AOP_TYPE(result) == AOP_CRY){
4731 // if(size), result in bit
4732 // if(!size && ifx), conditional oper: if(left | right)
4733 symbol *tlbl = newiTempLabel(NULL);
4734 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4736 emitcode("setb","c");
4738 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4739 emitcode("orl","a,%s",
4740 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4741 emitcode("jnz","%05d$",tlbl->key+100);
4746 emitcode("","%05d$:",tlbl->key+100);
4749 jmpTrueOrFalse(ifx, tlbl);
4750 } else for(;(size--);offset++){
4752 // result = left & right
4753 if(AOP_TYPE(right) == AOP_LIT){
4754 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4756 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4761 // faster than result <- left, anl result,right
4762 // and better if result is SFR
4763 if (AOP_TYPE(left) == AOP_ACC)
4764 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4766 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4767 emitcode("orl","a,%s",
4768 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4770 aopPut(AOP(result),"a",offset);
4775 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4776 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4777 freeAsmop(result,NULL,ic,TRUE);
4780 /*-----------------------------------------------------------------*/
4781 /* genXor - code for xclusive or */
4782 /*-----------------------------------------------------------------*/
4783 static void genXor (iCode *ic, iCode *ifx)
4785 operand *left, *right, *result;
4787 unsigned long lit = 0L;
4789 D(emitcode(";", "genXor "););
4794 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4795 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4796 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4800 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4802 AOP_TYPE(left), AOP_TYPE(right));
4803 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4805 AOP_SIZE(left), AOP_SIZE(right));
4808 /* if left is a literal & right is not ||
4809 if left needs acc & right does not */
4810 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4811 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4812 operand *tmp = right ;
4817 /* if result = right then exchange them */
4818 if(sameRegs(AOP(result),AOP(right))){
4819 operand *tmp = right ;
4824 /* if right is bit then exchange them */
4825 if (AOP_TYPE(right) == AOP_CRY &&
4826 AOP_TYPE(left) != AOP_CRY){
4827 operand *tmp = right ;
4831 if(AOP_TYPE(right) == AOP_LIT)
4832 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4834 size = AOP_SIZE(result);
4838 if (AOP_TYPE(left) == AOP_CRY){
4839 if(AOP_TYPE(right) == AOP_LIT){
4840 // c = bit & literal;
4842 // lit>>1 != 0 => result = 1
4843 if(AOP_TYPE(result) == AOP_CRY){
4845 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4847 continueIfTrue(ifx);
4850 emitcode("setb","c");
4854 // lit == 0, result = left
4855 if(size && sameRegs(AOP(result),AOP(left)))
4857 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4859 // lit == 1, result = not(left)
4860 if(size && sameRegs(AOP(result),AOP(left))){
4861 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4864 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4865 emitcode("cpl","c");
4872 symbol *tlbl = newiTempLabel(NULL);
4873 if (AOP_TYPE(right) == AOP_CRY){
4875 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4878 int sizer = AOP_SIZE(right);
4880 // if val>>1 != 0, result = 1
4881 emitcode("setb","c");
4883 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
4885 // test the msb of the lsb
4886 emitcode("anl","a,#0xfe");
4887 emitcode("jnz","%05d$",tlbl->key+100);
4891 emitcode("rrc","a");
4893 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4894 emitcode("cpl","c");
4895 emitcode("","%05d$:",(tlbl->key+100));
4902 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4903 genIfxJump(ifx, "c");
4907 if(sameRegs(AOP(result),AOP(left))){
4908 /* if left is same as result */
4909 for(;size--; offset++) {
4910 if(AOP_TYPE(right) == AOP_LIT){
4911 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4914 if (IS_AOP_PREG(left)) {
4915 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4916 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4917 aopPut(AOP(result),"a",offset);
4919 emitcode("xrl","%s,%s",
4920 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4921 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4923 if (AOP_TYPE(left) == AOP_ACC)
4924 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4926 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4927 if (IS_AOP_PREG(left)) {
4928 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4929 aopPut(AOP(result),"a",offset);
4931 emitcode("xrl","%s,a",
4932 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4937 // left & result in different registers
4938 if(AOP_TYPE(result) == AOP_CRY){
4940 // if(size), result in bit
4941 // if(!size && ifx), conditional oper: if(left ^ right)
4942 symbol *tlbl = newiTempLabel(NULL);
4943 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4945 emitcode("setb","c");
4947 if((AOP_TYPE(right) == AOP_LIT) &&
4948 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4949 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4951 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4952 emitcode("xrl","a,%s",
4953 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4955 emitcode("jnz","%05d$",tlbl->key+100);
4960 emitcode("","%05d$:",tlbl->key+100);
4963 jmpTrueOrFalse(ifx, tlbl);
4964 } else for(;(size--);offset++){
4966 // result = left & right
4967 if(AOP_TYPE(right) == AOP_LIT){
4968 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4970 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4975 // faster than result <- left, anl result,right
4976 // and better if result is SFR
4977 if (AOP_TYPE(left) == AOP_ACC)
4978 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4980 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4981 emitcode("xrl","a,%s",
4982 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4984 aopPut(AOP(result),"a",offset);
4989 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4990 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4991 freeAsmop(result,NULL,ic,TRUE);
4994 /*-----------------------------------------------------------------*/
4995 /* genInline - write the inline code out */
4996 /*-----------------------------------------------------------------*/
4997 static void genInline (iCode *ic)
4999 char buffer[MAX_INLINEASM];
5003 D(emitcode(";", "genInline "););
5005 _G.inLine += (!options.asmpeep);
5006 strcpy(buffer,IC_INLINE(ic));
5008 /* emit each line as a code */
5027 /* emitcode("",buffer); */
5028 _G.inLine -= (!options.asmpeep);
5031 /*-----------------------------------------------------------------*/
5032 /* genRRC - rotate right with carry */
5033 /*-----------------------------------------------------------------*/
5034 static void genRRC (iCode *ic)
5036 operand *left , *result ;
5037 int size, offset = 0;
5040 D(emitcode(";", "genRRC "););
5042 /* rotate right with carry */
5044 result=IC_RESULT(ic);
5045 aopOp (left,ic,FALSE, FALSE);
5046 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5048 /* move it to the result */
5049 size = AOP_SIZE(result);
5053 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5055 emitcode("rrc","a");
5056 if (AOP_SIZE(result) > 1)
5057 aopPut(AOP(result),"a",offset--);
5059 /* now we need to put the carry into the
5060 highest order byte of the result */
5061 if (AOP_SIZE(result) > 1) {
5062 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5065 emitcode("mov","acc.7,c");
5066 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5067 freeAsmop(left,NULL,ic,TRUE);
5068 freeAsmop(result,NULL,ic,TRUE);
5071 /*-----------------------------------------------------------------*/
5072 /* genRLC - generate code for rotate left with carry */
5073 /*-----------------------------------------------------------------*/
5074 static void genRLC (iCode *ic)
5076 operand *left , *result ;
5077 int size, offset = 0;
5080 D(emitcode(";", "genRLC "););
5082 /* rotate right with carry */
5084 result=IC_RESULT(ic);
5085 aopOp (left,ic,FALSE, FALSE);
5086 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5088 /* move it to the result */
5089 size = AOP_SIZE(result);
5092 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5094 emitcode("add","a,acc");
5095 if (AOP_SIZE(result) > 1)
5096 aopPut(AOP(result),"a",offset++);
5098 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5100 emitcode("rlc","a");
5101 if (AOP_SIZE(result) > 1)
5102 aopPut(AOP(result),"a",offset++);
5105 /* now we need to put the carry into the
5106 highest order byte of the result */
5107 if (AOP_SIZE(result) > 1) {
5108 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5111 emitcode("mov","acc.0,c");
5112 aopPut(AOP(result),"a",0);
5113 freeAsmop(left,NULL,ic,TRUE);
5114 freeAsmop(result,NULL,ic,TRUE);
5117 /*-----------------------------------------------------------------*/
5118 /* genGetHbit - generates code get highest order bit */
5119 /*-----------------------------------------------------------------*/
5120 static void genGetHbit (iCode *ic)
5122 operand *left, *result;
5124 result=IC_RESULT(ic);
5125 aopOp (left,ic,FALSE, FALSE);
5126 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5128 D(emitcode(";", "genGetHbit "););
5130 /* get the highest order byte into a */
5131 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5132 if(AOP_TYPE(result) == AOP_CRY){
5133 emitcode("rlc","a");
5138 emitcode("anl","a,#0x01");
5143 freeAsmop(left,NULL,ic,TRUE);
5144 freeAsmop(result,NULL,ic,TRUE);
5147 /*-----------------------------------------------------------------*/
5148 /* AccRol - rotate left accumulator by known count */
5149 /*-----------------------------------------------------------------*/
5150 static void AccRol (int shCount)
5152 shCount &= 0x0007; // shCount : 0..7
5164 emitcode("swap","a");
5168 emitcode("swap","a");
5171 emitcode("swap","a");
5184 /*-----------------------------------------------------------------*/
5185 /* AccLsh - left shift accumulator by known count */
5186 /*-----------------------------------------------------------------*/
5187 static void AccLsh (int shCount)
5191 emitcode("add","a,acc");
5194 emitcode("add","a,acc");
5195 emitcode("add","a,acc");
5197 /* rotate left accumulator */
5199 /* and kill the lower order bits */
5200 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5205 /*-----------------------------------------------------------------*/
5206 /* AccRsh - right shift accumulator by known count */
5207 /*-----------------------------------------------------------------*/
5208 static void AccRsh (int shCount)
5213 emitcode("rrc","a");
5215 /* rotate right accumulator */
5216 AccRol(8 - shCount);
5217 /* and kill the higher order bits */
5218 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5223 /*-----------------------------------------------------------------*/
5224 /* AccSRsh - signed right shift accumulator by known count */
5225 /*-----------------------------------------------------------------*/
5226 static void AccSRsh (int shCount)
5231 emitcode("mov","c,acc.7");
5232 emitcode("rrc","a");
5233 } else if(shCount == 2){
5234 emitcode("mov","c,acc.7");
5235 emitcode("rrc","a");
5236 emitcode("mov","c,acc.7");
5237 emitcode("rrc","a");
5239 tlbl = newiTempLabel(NULL);
5240 /* rotate right accumulator */
5241 AccRol(8 - shCount);
5242 /* and kill the higher order bits */
5243 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5244 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5245 emitcode("orl","a,#0x%02x",
5246 (unsigned char)~SRMask[shCount]);
5247 emitcode("","%05d$:",tlbl->key+100);
5252 /*-----------------------------------------------------------------*/
5253 /* shiftR1Left2Result - shift right one byte from left to result */
5254 /*-----------------------------------------------------------------*/
5255 static void shiftR1Left2Result (operand *left, int offl,
5256 operand *result, int offr,
5257 int shCount, int sign)
5259 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5260 /* shift right accumulator */
5265 aopPut(AOP(result),"a",offr);
5268 /*-----------------------------------------------------------------*/
5269 /* shiftL1Left2Result - shift left one byte from left to result */
5270 /*-----------------------------------------------------------------*/
5271 static void shiftL1Left2Result (operand *left, int offl,
5272 operand *result, int offr, int shCount)
5275 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5277 /* shift left accumulator */
5279 aopPut(AOP(result),"a",offr);
5282 /*-----------------------------------------------------------------*/
5283 /* movLeft2Result - move byte from left to result */
5284 /*-----------------------------------------------------------------*/
5285 static void movLeft2Result (operand *left, int offl,
5286 operand *result, int offr, int sign)
5289 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5290 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5292 if (*l == '@' && (IS_AOP_PREG(result))) {
5293 emitcode("mov","a,%s",l);
5294 aopPut(AOP(result),"a",offr);
5297 aopPut(AOP(result),l,offr);
5299 /* MSB sign in acc.7 ! */
5300 if(getDataSize(left) == offl+1){
5301 emitcode("mov","a,%s",l);
5302 aopPut(AOP(result),"a",offr);
5309 /*-----------------------------------------------------------------*/
5310 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5311 /*-----------------------------------------------------------------*/
5312 static void AccAXRrl1 (char *x)
5314 emitcode("rrc","a");
5315 emitcode("xch","a,%s", x);
5316 emitcode("rrc","a");
5317 emitcode("xch","a,%s", x);
5320 /*-----------------------------------------------------------------*/
5321 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5322 /*-----------------------------------------------------------------*/
5323 static void AccAXLrl1 (char *x)
5325 emitcode("xch","a,%s",x);
5326 emitcode("rlc","a");
5327 emitcode("xch","a,%s",x);
5328 emitcode("rlc","a");
5331 /*-----------------------------------------------------------------*/
5332 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5333 /*-----------------------------------------------------------------*/
5334 static void AccAXLsh1 (char *x)
5336 emitcode("xch","a,%s",x);
5337 emitcode("add","a,acc");
5338 emitcode("xch","a,%s",x);
5339 emitcode("rlc","a");
5342 /*-----------------------------------------------------------------*/
5343 /* AccAXLsh - left shift a:x by known count (0..7) */
5344 /*-----------------------------------------------------------------*/
5345 static void AccAXLsh (char *x, int shCount)
5359 case 5 : // AAAAABBB:CCCCCDDD
5360 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5361 emitcode("anl","a,#0x%02x",
5362 SLMask[shCount]); // BBB00000:CCCCCDDD
5363 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5364 AccRol(shCount); // DDDCCCCC:BBB00000
5365 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5366 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5367 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5368 emitcode("anl","a,#0x%02x",
5369 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5370 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5371 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5373 case 6 : // AAAAAABB:CCCCCCDD
5374 emitcode("anl","a,#0x%02x",
5375 SRMask[shCount]); // 000000BB:CCCCCCDD
5376 emitcode("mov","c,acc.0"); // c = B
5377 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5378 AccAXRrl1(x); // BCCCCCCD:D000000B
5379 AccAXRrl1(x); // BBCCCCCC:DD000000
5381 case 7 : // a:x <<= 7
5382 emitcode("anl","a,#0x%02x",
5383 SRMask[shCount]); // 0000000B:CCCCCCCD
5384 emitcode("mov","c,acc.0"); // c = B
5385 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5386 AccAXRrl1(x); // BCCCCCCC:D0000000
5393 /*-----------------------------------------------------------------*/
5394 /* AccAXRsh - right shift a:x known count (0..7) */
5395 /*-----------------------------------------------------------------*/
5396 static void AccAXRsh (char *x, int shCount)
5403 AccAXRrl1(x); // 0->a:x
5407 AccAXRrl1(x); // 0->a:x
5409 AccAXRrl1(x); // 0->a:x
5413 case 5 : // AAAAABBB:CCCCCDDD = a:x
5414 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5415 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5416 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5417 emitcode("anl","a,#0x%02x",
5418 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5419 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5420 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5421 emitcode("anl","a,#0x%02x",
5422 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5423 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5424 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5425 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5427 case 6 : // AABBBBBB:CCDDDDDD
5428 emitcode("mov","c,acc.7");
5429 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5430 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5431 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5432 emitcode("anl","a,#0x%02x",
5433 SRMask[shCount]); // 000000AA:BBBBBBCC
5435 case 7 : // ABBBBBBB:CDDDDDDD
5436 emitcode("mov","c,acc.7"); // c = A
5437 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5438 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5439 emitcode("anl","a,#0x%02x",
5440 SRMask[shCount]); // 0000000A:BBBBBBBC
5447 /*-----------------------------------------------------------------*/
5448 /* AccAXRshS - right shift signed a:x known count (0..7) */
5449 /*-----------------------------------------------------------------*/
5450 static void AccAXRshS (char *x, int shCount)
5457 emitcode("mov","c,acc.7");
5458 AccAXRrl1(x); // s->a:x
5461 emitcode("mov","c,acc.7");
5462 AccAXRrl1(x); // s->a:x
5463 emitcode("mov","c,acc.7");
5464 AccAXRrl1(x); // s->a:x
5468 case 5 : // AAAAABBB:CCCCCDDD = a:x
5469 tlbl = newiTempLabel(NULL);
5470 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5471 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5472 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5473 emitcode("anl","a,#0x%02x",
5474 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5475 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5476 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5477 emitcode("anl","a,#0x%02x",
5478 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5479 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5480 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5481 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5482 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5483 emitcode("orl","a,#0x%02x",
5484 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5485 emitcode("","%05d$:",tlbl->key+100);
5486 break; // SSSSAAAA:BBBCCCCC
5487 case 6 : // AABBBBBB:CCDDDDDD
5488 tlbl = newiTempLabel(NULL);
5489 emitcode("mov","c,acc.7");
5490 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5491 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5492 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5493 emitcode("anl","a,#0x%02x",
5494 SRMask[shCount]); // 000000AA:BBBBBBCC
5495 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5496 emitcode("orl","a,#0x%02x",
5497 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5498 emitcode("","%05d$:",tlbl->key+100);
5500 case 7 : // ABBBBBBB:CDDDDDDD
5501 tlbl = newiTempLabel(NULL);
5502 emitcode("mov","c,acc.7"); // c = A
5503 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5504 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5505 emitcode("anl","a,#0x%02x",
5506 SRMask[shCount]); // 0000000A:BBBBBBBC
5507 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5508 emitcode("orl","a,#0x%02x",
5509 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5510 emitcode("","%05d$:",tlbl->key+100);
5517 /*-----------------------------------------------------------------*/
5518 /* shiftL2Left2Result - shift left two bytes from left to result */
5519 /*-----------------------------------------------------------------*/
5520 static void shiftL2Left2Result (operand *left, int offl,
5521 operand *result, int offr, int shCount)
5523 if(sameRegs(AOP(result), AOP(left)) &&
5524 ((offl + MSB16) == offr)){
5525 /* don't crash result[offr] */
5526 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5527 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5529 movLeft2Result(left,offl, result, offr, 0);
5530 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5532 /* ax << shCount (x = lsb(result))*/
5533 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5534 aopPut(AOP(result),"a",offr+MSB16);
5538 /*-----------------------------------------------------------------*/
5539 /* shiftR2Left2Result - shift right two bytes from left to result */
5540 /*-----------------------------------------------------------------*/
5541 static void shiftR2Left2Result (operand *left, int offl,
5542 operand *result, int offr,
5543 int shCount, int sign)
5545 if(sameRegs(AOP(result), AOP(left)) &&
5546 ((offl + MSB16) == offr)){
5547 /* don't crash result[offr] */
5548 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5549 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5551 movLeft2Result(left,offl, result, offr, 0);
5552 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5554 /* a:x >> shCount (x = lsb(result))*/
5556 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5558 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5559 if(getDataSize(result) > 1)
5560 aopPut(AOP(result),"a",offr+MSB16);
5563 /*-----------------------------------------------------------------*/
5564 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5565 /*-----------------------------------------------------------------*/
5566 static void shiftLLeftOrResult (operand *left, int offl,
5567 operand *result, int offr, int shCount)
5569 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5570 /* shift left accumulator */
5572 /* or with result */
5573 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5574 /* back to result */
5575 aopPut(AOP(result),"a",offr);
5578 /*-----------------------------------------------------------------*/
5579 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5580 /*-----------------------------------------------------------------*/
5581 static void shiftRLeftOrResult (operand *left, int offl,
5582 operand *result, int offr, int shCount)
5584 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5585 /* shift right accumulator */
5587 /* or with result */
5588 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5589 /* back to result */
5590 aopPut(AOP(result),"a",offr);
5593 /*-----------------------------------------------------------------*/
5594 /* genlshOne - left shift a one byte quantity by known count */
5595 /*-----------------------------------------------------------------*/
5596 static void genlshOne (operand *result, operand *left, int shCount)
5598 D(emitcode(";", "genlshOne "););
5599 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5602 /*-----------------------------------------------------------------*/
5603 /* genlshTwo - left shift two bytes by known amount != 0 */
5604 /*-----------------------------------------------------------------*/
5605 static void genlshTwo (operand *result,operand *left, int shCount)
5609 D(emitcode(";", "genlshTwo "););
5611 size = getDataSize(result);
5613 /* if shCount >= 8 */
5619 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5621 movLeft2Result(left, LSB, result, MSB16, 0);
5623 aopPut(AOP(result),zero,LSB);
5626 /* 1 <= shCount <= 7 */
5629 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5631 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5635 /*-----------------------------------------------------------------*/
5636 /* shiftLLong - shift left one long from left to result */
5637 /* offl = LSB or MSB16 */
5638 /*-----------------------------------------------------------------*/
5639 static void shiftLLong (operand *left, operand *result, int offr )
5642 int size = AOP_SIZE(result);
5644 if(size >= LSB+offr){
5645 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5647 emitcode("add","a,acc");
5648 if (sameRegs(AOP(left),AOP(result)) &&
5649 size >= MSB16+offr && offr != LSB )
5650 emitcode("xch","a,%s",
5651 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5653 aopPut(AOP(result),"a",LSB+offr);
5656 if(size >= MSB16+offr){
5657 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5658 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5661 emitcode("rlc","a");
5662 if (sameRegs(AOP(left),AOP(result)) &&
5663 size >= MSB24+offr && offr != LSB)
5664 emitcode("xch","a,%s",
5665 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5667 aopPut(AOP(result),"a",MSB16+offr);
5670 if(size >= MSB24+offr){
5671 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5672 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5675 emitcode("rlc","a");
5676 if (sameRegs(AOP(left),AOP(result)) &&
5677 size >= MSB32+offr && offr != LSB )
5678 emitcode("xch","a,%s",
5679 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5681 aopPut(AOP(result),"a",MSB24+offr);
5684 if(size > MSB32+offr){
5685 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5686 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5689 emitcode("rlc","a");
5690 aopPut(AOP(result),"a",MSB32+offr);
5693 aopPut(AOP(result),zero,LSB);
5696 /*-----------------------------------------------------------------*/
5697 /* genlshFour - shift four byte by a known amount != 0 */
5698 /*-----------------------------------------------------------------*/
5699 static void genlshFour (operand *result, operand *left, int shCount)
5703 D(emitcode(";", "genlshFour "););
5705 size = AOP_SIZE(result);
5707 /* if shifting more that 3 bytes */
5708 if (shCount >= 24 ) {
5711 /* lowest order of left goes to the highest
5712 order of the destination */
5713 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5715 movLeft2Result(left, LSB, result, MSB32, 0);
5716 aopPut(AOP(result),zero,LSB);
5717 aopPut(AOP(result),zero,MSB16);
5718 aopPut(AOP(result),zero,MSB32);
5722 /* more than two bytes */
5723 else if ( shCount >= 16 ) {
5724 /* lower order two bytes goes to higher order two bytes */
5726 /* if some more remaining */
5728 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5730 movLeft2Result(left, MSB16, result, MSB32, 0);
5731 movLeft2Result(left, LSB, result, MSB24, 0);
5733 aopPut(AOP(result),zero,MSB16);
5734 aopPut(AOP(result),zero,LSB);
5738 /* if more than 1 byte */
5739 else if ( shCount >= 8 ) {
5740 /* lower order three bytes goes to higher order three bytes */
5744 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5746 movLeft2Result(left, LSB, result, MSB16, 0);
5748 else{ /* size = 4 */
5750 movLeft2Result(left, MSB24, result, MSB32, 0);
5751 movLeft2Result(left, MSB16, result, MSB24, 0);
5752 movLeft2Result(left, LSB, result, MSB16, 0);
5753 aopPut(AOP(result),zero,LSB);
5755 else if(shCount == 1)
5756 shiftLLong(left, result, MSB16);
5758 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5759 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5760 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5761 aopPut(AOP(result),zero,LSB);
5766 /* 1 <= shCount <= 7 */
5767 else if(shCount <= 2){
5768 shiftLLong(left, result, LSB);
5770 shiftLLong(result, result, LSB);
5772 /* 3 <= shCount <= 7, optimize */
5774 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5775 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5776 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5780 /*-----------------------------------------------------------------*/
5781 /* genLeftShiftLiteral - left shifting by known count */
5782 /*-----------------------------------------------------------------*/
5783 static void genLeftShiftLiteral (operand *left,
5788 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5791 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5793 freeAsmop(right,NULL,ic,TRUE);
5795 aopOp(left,ic,FALSE, FALSE);
5796 aopOp(result,ic,FALSE, TRUE);
5798 size = getSize(operandType(result));
5801 emitcode("; shift left ","result %d, left %d",size,
5805 /* I suppose that the left size >= result size */
5808 movLeft2Result(left, size, result, size, 0);
5812 else if(shCount >= (size * 8))
5814 aopPut(AOP(result),zero,size);
5818 genlshOne (result,left,shCount);
5822 case 3: /* bug: this is for generic pointers, I bet. */
5823 genlshTwo (result,left,shCount);
5827 genlshFour (result,left,shCount);
5831 freeAsmop(left,NULL,ic,TRUE);
5832 freeAsmop(result,NULL,ic,TRUE);
5835 /*-----------------------------------------------------------------*/
5836 /* genLeftShift - generates code for left shifting */
5837 /*-----------------------------------------------------------------*/
5838 static void genLeftShift (iCode *ic)
5840 operand *left,*right, *result;
5843 symbol *tlbl , *tlbl1;
5845 D(emitcode(";", "genLeftShift "););
5847 right = IC_RIGHT(ic);
5849 result = IC_RESULT(ic);
5851 aopOp(right,ic,FALSE, FALSE);
5854 /* if the shift count is known then do it
5855 as efficiently as possible */
5856 if (AOP_TYPE(right) == AOP_LIT) {
5857 genLeftShiftLiteral (left,right,result,ic);
5862 /* shift count is unknown then we have to form
5863 a loop get the loop count in B : Note: we take
5864 only the lower order byte since shifting
5865 more that 32 bits make no sense anyway, ( the
5866 largest size of an object can be only 32 bits ) */
5868 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
5869 emitcode("inc","b");
5870 freeAsmop (right,NULL,ic,TRUE);
5871 aopOp(left,ic,FALSE, FALSE);
5872 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5874 /* now move the left to the result if they are not the
5876 if (!sameRegs(AOP(left),AOP(result)) &&
5877 AOP_SIZE(result) > 1) {
5879 size = AOP_SIZE(result);
5882 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
5883 if (*l == '@' && (IS_AOP_PREG(result))) {
5885 emitcode("mov","a,%s",l);
5886 aopPut(AOP(result),"a",offset);
5888 aopPut(AOP(result),l,offset);
5893 tlbl = newiTempLabel(NULL);
5894 size = AOP_SIZE(result);
5896 tlbl1 = newiTempLabel(NULL);
5898 /* if it is only one byte then */
5900 symbol *tlbl1 = newiTempLabel(NULL);
5902 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
5904 emitcode("sjmp","%05d$",tlbl1->key+100);
5905 emitcode("","%05d$:",tlbl->key+100);
5906 emitcode("add","a,acc");
5907 emitcode("","%05d$:",tlbl1->key+100);
5908 emitcode("djnz","b,%05d$",tlbl->key+100);
5909 aopPut(AOP(result),"a",0);
5913 reAdjustPreg(AOP(result));
5915 emitcode("sjmp","%05d$",tlbl1->key+100);
5916 emitcode("","%05d$:",tlbl->key+100);
5917 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
5919 emitcode("add","a,acc");
5920 aopPut(AOP(result),"a",offset++);
5922 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
5924 emitcode("rlc","a");
5925 aopPut(AOP(result),"a",offset++);
5927 reAdjustPreg(AOP(result));
5929 emitcode("","%05d$:",tlbl1->key+100);
5930 emitcode("djnz","b,%05d$",tlbl->key+100);
5932 freeAsmop(left,NULL,ic,TRUE);
5933 freeAsmop(result,NULL,ic,TRUE);
5936 /*-----------------------------------------------------------------*/
5937 /* genrshOne - right shift a one byte quantity by known count */
5938 /*-----------------------------------------------------------------*/
5939 static void genrshOne (operand *result, operand *left,
5940 int shCount, int sign)
5942 D(emitcode(";", "genrshOne"););
5943 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5946 /*-----------------------------------------------------------------*/
5947 /* genrshTwo - right shift two bytes by known amount != 0 */
5948 /*-----------------------------------------------------------------*/
5949 static void genrshTwo (operand *result,operand *left,
5950 int shCount, int sign)
5952 D(emitcode(";", "genrshTwo"););
5954 /* if shCount >= 8 */
5958 shiftR1Left2Result(left, MSB16, result, LSB,
5961 movLeft2Result(left, MSB16, result, LSB, sign);
5962 addSign(result, MSB16, sign);
5965 /* 1 <= shCount <= 7 */
5967 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5970 /*-----------------------------------------------------------------*/
5971 /* shiftRLong - shift right one long from left to result */
5972 /* offl = LSB or MSB16 */
5973 /*-----------------------------------------------------------------*/
5974 static void shiftRLong (operand *left, int offl,
5975 operand *result, int sign)
5978 emitcode("clr","c");
5979 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
5981 emitcode("mov","c,acc.7");
5982 emitcode("rrc","a");
5983 aopPut(AOP(result),"a",MSB32-offl);
5985 /* add sign of "a" */
5986 addSign(result, MSB32, sign);
5988 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
5989 emitcode("rrc","a");
5990 aopPut(AOP(result),"a",MSB24-offl);
5992 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
5993 emitcode("rrc","a");
5994 aopPut(AOP(result),"a",MSB16-offl);
5997 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
5998 emitcode("rrc","a");
5999 aopPut(AOP(result),"a",LSB);
6003 /*-----------------------------------------------------------------*/
6004 /* genrshFour - shift four byte by a known amount != 0 */
6005 /*-----------------------------------------------------------------*/
6006 static void genrshFour (operand *result, operand *left,
6007 int shCount, int sign)
6009 D(emitcode(";", "genrshFour"););
6011 /* if shifting more that 3 bytes */
6012 if(shCount >= 24 ) {
6015 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6017 movLeft2Result(left, MSB32, result, LSB, sign);
6018 addSign(result, MSB16, sign);
6020 else if(shCount >= 16){
6023 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6025 movLeft2Result(left, MSB24, result, LSB, 0);
6026 movLeft2Result(left, MSB32, result, MSB16, sign);
6028 addSign(result, MSB24, sign);
6030 else if(shCount >= 8){
6033 shiftRLong(left, MSB16, result, sign);
6034 else if(shCount == 0){
6035 movLeft2Result(left, MSB16, result, LSB, 0);
6036 movLeft2Result(left, MSB24, result, MSB16, 0);
6037 movLeft2Result(left, MSB32, result, MSB24, sign);
6038 addSign(result, MSB32, sign);
6041 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6042 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6043 /* the last shift is signed */
6044 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6045 addSign(result, MSB32, sign);
6048 else{ /* 1 <= shCount <= 7 */
6050 shiftRLong(left, LSB, result, sign);
6052 shiftRLong(result, LSB, result, sign);
6055 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6056 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6057 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6062 /*-----------------------------------------------------------------*/
6063 /* genRightShiftLiteral - right shifting by known count */
6064 /*-----------------------------------------------------------------*/
6065 static void genRightShiftLiteral (operand *left,
6071 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6074 D(emitcode(";", "genRightShiftLiteral"););
6076 freeAsmop(right,NULL,ic,TRUE);
6078 aopOp(left,ic,FALSE, FALSE);
6079 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6082 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6086 size = getDataSize(left);
6087 /* test the LEFT size !!! */
6089 /* I suppose that the left size >= result size */
6091 size = getDataSize(result);
6093 movLeft2Result(left, size, result, size, 0);
6096 else if(shCount >= (size * 8)){
6098 /* get sign in acc.7 */
6099 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6100 addSign(result, LSB, sign);
6104 genrshOne (result,left,shCount,sign);
6108 genrshTwo (result,left,shCount,sign);
6112 genrshFour (result,left,shCount,sign);
6118 freeAsmop(left,NULL,ic,TRUE);
6119 freeAsmop(result,NULL,ic,TRUE);
6123 /*-----------------------------------------------------------------*/
6124 /* genSignedRightShift - right shift of signed number */
6125 /*-----------------------------------------------------------------*/
6126 static void genSignedRightShift (iCode *ic)
6128 operand *right, *left, *result;
6131 symbol *tlbl, *tlbl1 ;
6133 D(emitcode(";", "genSignedRightShift "););
6135 /* we do it the hard way put the shift count in b
6136 and loop thru preserving the sign */
6138 right = IC_RIGHT(ic);
6140 result = IC_RESULT(ic);
6142 aopOp(right,ic,FALSE, FALSE);
6145 if ( AOP_TYPE(right) == AOP_LIT) {
6146 genRightShiftLiteral (left,right,result,ic,1);
6150 /* shift count is unknown then we have to form
6151 a loop get the loop count in B : Note: we take
6152 only the lower order byte since shifting
6153 more that 32 bits make no sense anyway, ( the
6154 largest size of an object can be only 32 bits ) */
6156 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6157 emitcode("inc","b");
6158 freeAsmop (right,NULL,ic,TRUE);
6159 aopOp(left,ic,FALSE, FALSE);
6160 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6162 /* now move the left to the result if they are not the
6164 if (!sameRegs(AOP(left),AOP(result)) &&
6165 AOP_SIZE(result) > 1) {
6167 size = AOP_SIZE(result);
6170 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6171 if (*l == '@' && IS_AOP_PREG(result)) {
6173 emitcode("mov","a,%s",l);
6174 aopPut(AOP(result),"a",offset);
6176 aopPut(AOP(result),l,offset);
6181 /* mov the highest order bit to OVR */
6182 tlbl = newiTempLabel(NULL);
6183 tlbl1= newiTempLabel(NULL);
6185 size = AOP_SIZE(result);
6187 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6188 emitcode("rlc","a");
6189 emitcode("mov","ov,c");
6190 /* if it is only one byte then */
6192 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6194 emitcode("sjmp","%05d$",tlbl1->key+100);
6195 emitcode("","%05d$:",tlbl->key+100);
6196 emitcode("mov","c,ov");
6197 emitcode("rrc","a");
6198 emitcode("","%05d$:",tlbl1->key+100);
6199 emitcode("djnz","b,%05d$",tlbl->key+100);
6200 aopPut(AOP(result),"a",0);
6204 reAdjustPreg(AOP(result));
6205 emitcode("sjmp","%05d$",tlbl1->key+100);
6206 emitcode("","%05d$:",tlbl->key+100);
6207 emitcode("mov","c,ov");
6209 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6211 emitcode("rrc","a");
6212 aopPut(AOP(result),"a",offset--);
6214 reAdjustPreg(AOP(result));
6215 emitcode("","%05d$:",tlbl1->key+100);
6216 emitcode("djnz","b,%05d$",tlbl->key+100);
6219 freeAsmop(left,NULL,ic,TRUE);
6220 freeAsmop(result,NULL,ic,TRUE);
6223 /*-----------------------------------------------------------------*/
6224 /* genRightShift - generate code for right shifting */
6225 /*-----------------------------------------------------------------*/
6226 static void genRightShift (iCode *ic)
6228 operand *right, *left, *result;
6232 symbol *tlbl, *tlbl1 ;
6234 D(emitcode(";", "genRightShift "););
6236 /* if signed then we do it the hard way preserve the
6237 sign bit moving it inwards */
6238 retype = getSpec(operandType(IC_RESULT(ic)));
6240 if (!SPEC_USIGN(retype)) {
6241 genSignedRightShift (ic);
6245 /* signed & unsigned types are treated the same : i.e. the
6246 signed is NOT propagated inwards : quoting from the
6247 ANSI - standard : "for E1 >> E2, is equivalent to division
6248 by 2**E2 if unsigned or if it has a non-negative value,
6249 otherwise the result is implementation defined ", MY definition
6250 is that the sign does not get propagated */
6252 right = IC_RIGHT(ic);
6254 result = IC_RESULT(ic);
6256 aopOp(right,ic,FALSE, FALSE);
6259 /* if the shift count is known then do it
6260 as efficiently as possible */
6261 if (AOP_TYPE(right) == AOP_LIT) {
6262 genRightShiftLiteral (left,right,result,ic, 0);
6267 /* shift count is unknown then we have to form
6268 a loop get the loop count in B : Note: we take
6269 only the lower order byte since shifting
6270 more that 32 bits make no sense anyway, ( the
6271 largest size of an object can be only 32 bits ) */
6273 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6274 emitcode("inc","b");
6275 freeAsmop (right,NULL,ic,TRUE);
6276 aopOp(left,ic,FALSE, FALSE);
6277 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6279 /* now move the left to the result if they are not the
6281 if (!sameRegs(AOP(left),AOP(result)) &&
6282 AOP_SIZE(result) > 1) {
6284 size = AOP_SIZE(result);
6287 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6288 if (*l == '@' && IS_AOP_PREG(result)) {
6290 emitcode("mov","a,%s",l);
6291 aopPut(AOP(result),"a",offset);
6293 aopPut(AOP(result),l,offset);
6298 tlbl = newiTempLabel(NULL);
6299 tlbl1= newiTempLabel(NULL);
6300 size = AOP_SIZE(result);
6303 /* if it is only one byte then */
6305 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6307 emitcode("sjmp","%05d$",tlbl1->key+100);
6308 emitcode("","%05d$:",tlbl->key+100);
6310 emitcode("rrc","a");
6311 emitcode("","%05d$:",tlbl1->key+100);
6312 emitcode("djnz","b,%05d$",tlbl->key+100);
6313 aopPut(AOP(result),"a",0);
6317 reAdjustPreg(AOP(result));
6318 emitcode("sjmp","%05d$",tlbl1->key+100);
6319 emitcode("","%05d$:",tlbl->key+100);
6322 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6324 emitcode("rrc","a");
6325 aopPut(AOP(result),"a",offset--);
6327 reAdjustPreg(AOP(result));
6329 emitcode("","%05d$:",tlbl1->key+100);
6330 emitcode("djnz","b,%05d$",tlbl->key+100);
6333 freeAsmop(left,NULL,ic,TRUE);
6334 freeAsmop(result,NULL,ic,TRUE);
6337 /*-----------------------------------------------------------------*/
6338 /* genUnpackBits - generates code for unpacking bits */
6339 /*-----------------------------------------------------------------*/
6340 static void genUnpackBits (operand *result, char *rname, int ptype)
6347 D(emitcode(";", "genUnpackBits "););
6349 etype = getSpec(operandType(result));
6351 /* read the first byte */
6356 emitcode("mov","a,@%s",rname);
6360 emitcode("movx","a,@%s",rname);
6364 emitcode("movx","a,@dptr");
6368 emitcode("clr","a");
6369 emitcode("movc","a","@a+dptr");
6373 emitcode("lcall","__gptrget");
6377 /* if we have bitdisplacement then it fits */
6378 /* into this byte completely or if length is */
6379 /* less than a byte */
6380 if ((shCnt = SPEC_BSTR(etype)) ||
6381 (SPEC_BLEN(etype) <= 8)) {
6383 /* shift right acc */
6386 emitcode("anl","a,#0x%02x",
6387 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6388 aopPut(AOP(result),"a",offset);
6392 /* bit field did not fit in a byte */
6393 rlen = SPEC_BLEN(etype) - 8;
6394 aopPut(AOP(result),"a",offset++);
6401 emitcode("inc","%s",rname);
6402 emitcode("mov","a,@%s",rname);
6406 emitcode("inc","%s",rname);
6407 emitcode("movx","a,@%s",rname);
6411 emitcode("inc","dptr");
6412 emitcode("movx","a,@dptr");
6416 emitcode("clr","a");
6417 emitcode("inc","dptr");
6418 emitcode("movc","a","@a+dptr");
6422 emitcode("inc","dptr");
6423 emitcode("lcall","__gptrget");
6428 /* if we are done */
6432 aopPut(AOP(result),"a",offset++);
6437 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6438 aopPut(AOP(result),"a",offset);
6445 /*-----------------------------------------------------------------*/
6446 /* genDataPointerGet - generates code when ptr offset is known */
6447 /*-----------------------------------------------------------------*/
6448 static void genDataPointerGet (operand *left,
6454 int size , offset = 0;
6455 aopOp(result,ic,TRUE, FALSE);
6457 /* get the string representation of the name */
6458 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6459 size = AOP_SIZE(result);
6462 sprintf(buffer,"(%s + %d)",l+1,offset);
6464 sprintf(buffer,"%s",l+1);
6465 aopPut(AOP(result),buffer,offset++);
6468 freeAsmop(left,NULL,ic,TRUE);
6469 freeAsmop(result,NULL,ic,TRUE);
6472 /*-----------------------------------------------------------------*/
6473 /* genNearPointerGet - emitcode for near pointer fetch */
6474 /*-----------------------------------------------------------------*/
6475 static void genNearPointerGet (operand *left,
6482 link *rtype, *retype;
6483 link *ltype = operandType(left);
6486 rtype = operandType(result);
6487 retype= getSpec(rtype);
6489 aopOp(left,ic,FALSE, FALSE);
6491 /* if left is rematerialisable and
6492 result is not bit variable type and
6493 the left is pointer to data space i.e
6494 lower 128 bytes of space */
6495 if (AOP_TYPE(left) == AOP_IMMD &&
6496 !IS_BITVAR(retype) &&
6497 DCL_TYPE(ltype) == POINTER) {
6498 genDataPointerGet (left,result,ic);
6502 /* if the value is already in a pointer register
6503 then don't need anything more */
6504 if (!AOP_INPREG(AOP(left))) {
6505 /* otherwise get a free pointer register */
6507 preg = getFreePtr(ic,&aop,FALSE);
6508 emitcode("mov","%s,%s",
6510 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6511 rname = preg->name ;
6513 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6515 freeAsmop(left,NULL,ic,TRUE);
6516 aopOp (result,ic,FALSE, FALSE);
6518 /* if bitfield then unpack the bits */
6519 if (IS_BITVAR(retype))
6520 genUnpackBits (result,rname,POINTER);
6522 /* we have can just get the values */
6523 int size = AOP_SIZE(result);
6527 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6529 emitcode("mov","a,@%s",rname);
6530 aopPut(AOP(result),"a",offset);
6532 sprintf(buffer,"@%s",rname);
6533 aopPut(AOP(result),buffer,offset);
6537 emitcode("inc","%s",rname);
6541 /* now some housekeeping stuff */
6543 /* we had to allocate for this iCode */
6544 freeAsmop(NULL,aop,ic,TRUE);
6546 /* we did not allocate which means left
6547 already in a pointer register, then
6548 if size > 0 && this could be used again
6549 we have to point it back to where it
6551 if (AOP_SIZE(result) > 1 &&
6552 !OP_SYMBOL(left)->remat &&
6553 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6555 int size = AOP_SIZE(result) - 1;
6557 emitcode("dec","%s",rname);
6562 freeAsmop(result,NULL,ic,TRUE);
6566 /*-----------------------------------------------------------------*/
6567 /* genPagedPointerGet - emitcode for paged pointer fetch */
6568 /*-----------------------------------------------------------------*/
6569 static void genPagedPointerGet (operand *left,
6576 link *rtype, *retype;
6578 rtype = operandType(result);
6579 retype= getSpec(rtype);
6581 aopOp(left,ic,FALSE, FALSE);
6583 /* if the value is already in a pointer register
6584 then don't need anything more */
6585 if (!AOP_INPREG(AOP(left))) {
6586 /* otherwise get a free pointer register */
6588 preg = getFreePtr(ic,&aop,FALSE);
6589 emitcode("mov","%s,%s",
6591 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6592 rname = preg->name ;
6594 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6596 freeAsmop(left,NULL,ic,TRUE);
6597 aopOp (result,ic,FALSE, FALSE);
6599 /* if bitfield then unpack the bits */
6600 if (IS_BITVAR(retype))
6601 genUnpackBits (result,rname,PPOINTER);
6603 /* we have can just get the values */
6604 int size = AOP_SIZE(result);
6609 emitcode("movx","a,@%s",rname);
6610 aopPut(AOP(result),"a",offset);
6615 emitcode("inc","%s",rname);
6619 /* now some housekeeping stuff */
6621 /* we had to allocate for this iCode */
6622 freeAsmop(NULL,aop,ic,TRUE);
6624 /* we did not allocate which means left
6625 already in a pointer register, then
6626 if size > 0 && this could be used again
6627 we have to point it back to where it
6629 if (AOP_SIZE(result) > 1 &&
6630 !OP_SYMBOL(left)->remat &&
6631 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6633 int size = AOP_SIZE(result) - 1;
6635 emitcode("dec","%s",rname);
6640 freeAsmop(result,NULL,ic,TRUE);
6645 /*-----------------------------------------------------------------*/
6646 /* genFarPointerGet - gget value from far space */
6647 /*-----------------------------------------------------------------*/
6648 static void genFarPointerGet (operand *left,
6649 operand *result, iCode *ic)
6652 link *retype = getSpec(operandType(result));
6654 D(emitcode(";", "genFarPointerGet"););
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)
6664 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6668 /* we need to get it byte by byte */
6669 if (AOP_TYPE(left) != AOP_DPTR)
6671 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6672 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6673 if (options.model == MODEL_FLAT24)
6675 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6680 /* We need to generate a load to DPTR indirect through DPTR. */
6681 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6682 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6683 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6684 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6685 emitcode("pop", "dph");
6686 emitcode("pop", "dpl");
6690 /* so dptr know contains the address */
6691 freeAsmop(left,NULL,ic,TRUE);
6692 aopOp(result,ic,FALSE, TRUE);
6694 /* if bit then unpack */
6695 if (IS_BITVAR(retype))
6696 genUnpackBits(result,"dptr",FPOINTER);
6698 size = AOP_SIZE(result);
6702 emitcode("movx","a,@dptr");
6703 aopPut(AOP(result),"a",offset++);
6705 emitcode("inc","dptr");
6709 freeAsmop(result,NULL,ic,TRUE);
6712 /*-----------------------------------------------------------------*/
6713 /* emitcodePointerGet - gget value from code space */
6714 /*-----------------------------------------------------------------*/
6715 static void emitcodePointerGet (operand *left,
6716 operand *result, iCode *ic)
6719 link *retype = getSpec(operandType(result));
6721 aopOp(left,ic,FALSE, FALSE);
6723 /* if the operand is already in dptr
6724 then we do nothing else we move the value to dptr */
6725 if (AOP_TYPE(left) != AOP_STR) {
6726 /* if this is remateriazable */
6727 if (AOP_TYPE(left) == AOP_IMMD)
6728 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6729 else { /* we need to get it byte by byte */
6730 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6731 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6732 if (options.model == MODEL_FLAT24)
6734 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6738 /* so dptr know contains the address */
6739 freeAsmop(left,NULL,ic,TRUE);
6740 aopOp(result,ic,FALSE, FALSE);
6742 /* if bit then unpack */
6743 if (IS_BITVAR(retype))
6744 genUnpackBits(result,"dptr",CPOINTER);
6746 size = AOP_SIZE(result);
6750 emitcode("clr","a");
6751 emitcode("movc","a,@a+dptr");
6752 aopPut(AOP(result),"a",offset++);
6754 emitcode("inc","dptr");
6758 freeAsmop(result,NULL,ic,TRUE);
6761 /*-----------------------------------------------------------------*/
6762 /* genGenPointerGet - gget value from generic pointer space */
6763 /*-----------------------------------------------------------------*/
6764 static void genGenPointerGet (operand *left,
6765 operand *result, iCode *ic)
6768 link *retype = getSpec(operandType(result));
6770 aopOp(left,ic,FALSE, TRUE);
6772 /* if the operand is already in dptr
6773 then we do nothing else we move the value to dptr */
6774 if (AOP_TYPE(left) != AOP_STR) {
6775 /* if this is remateriazable */
6776 if (AOP_TYPE(left) == AOP_IMMD) {
6777 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6778 emitcode("mov","b,#%d",pointerCode(retype));
6780 else { /* we need to get it byte by byte */
6781 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6782 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6783 if (options.model == MODEL_FLAT24)
6785 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6786 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
6790 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6794 /* so dptr know contains the address */
6795 freeAsmop(left,NULL,ic,TRUE);
6796 aopOp(result,ic,FALSE, TRUE);
6798 /* if bit then unpack */
6799 if (IS_BITVAR(retype))
6800 genUnpackBits(result,"dptr",GPOINTER);
6802 size = AOP_SIZE(result);
6806 emitcode("lcall","__gptrget");
6807 aopPut(AOP(result),"a",offset++);
6809 emitcode("inc","dptr");
6813 freeAsmop(result,NULL,ic,TRUE);
6816 /*-----------------------------------------------------------------*/
6817 /* genPointerGet - generate code for pointer get */
6818 /*-----------------------------------------------------------------*/
6819 static void genPointerGet (iCode *ic)
6821 operand *left, *result ;
6825 D(emitcode(";", "genPointerGet "););
6828 result = IC_RESULT(ic) ;
6830 /* depending on the type of pointer we need to
6831 move it to the correct pointer register */
6832 type = operandType(left);
6833 etype = getSpec(type);
6834 /* if left is of type of pointer then it is simple */
6835 if (IS_PTR(type) && !IS_FUNC(type->next))
6836 p_type = DCL_TYPE(type);
6838 /* we have to go by the storage class */
6839 p_type = PTR_TYPE(SPEC_OCLS(etype));
6841 /* if (SPEC_OCLS(etype)->codesp ) { */
6842 /* p_type = CPOINTER ; */
6845 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6846 /* p_type = FPOINTER ; */
6848 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6849 /* p_type = PPOINTER; */
6851 /* if (SPEC_OCLS(etype) == idata ) */
6852 /* p_type = IPOINTER; */
6854 /* p_type = POINTER ; */
6857 /* now that we have the pointer type we assign
6858 the pointer values */
6863 genNearPointerGet (left,result,ic);
6867 genPagedPointerGet(left,result,ic);
6871 genFarPointerGet (left,result,ic);
6875 emitcodePointerGet (left,result,ic);
6879 genGenPointerGet (left,result,ic);
6885 /*-----------------------------------------------------------------*/
6886 /* genPackBits - generates code for packed bit storage */
6887 /*-----------------------------------------------------------------*/
6888 static void genPackBits (link *etype ,
6890 char *rname, int p_type)
6898 blen = SPEC_BLEN(etype);
6899 bstr = SPEC_BSTR(etype);
6901 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
6904 /* if the bit lenth is less than or */
6905 /* it exactly fits a byte then */
6906 if (SPEC_BLEN(etype) <= 8 ) {
6907 shCount = SPEC_BSTR(etype) ;
6909 /* shift left acc */
6912 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6917 emitcode ("mov","b,a");
6918 emitcode("mov","a,@%s",rname);
6922 emitcode ("mov","b,a");
6923 emitcode("movx","a,@dptr");
6927 emitcode ("push","b");
6928 emitcode ("push","acc");
6929 emitcode ("lcall","__gptrget");
6930 emitcode ("pop","b");
6934 emitcode ("anl","a,#0x%02x",(unsigned char)
6935 ((unsigned char)(0xFF << (blen+bstr)) |
6936 (unsigned char)(0xFF >> (8-bstr)) ) );
6937 emitcode ("orl","a,b");
6938 if (p_type == GPOINTER)
6939 emitcode("pop","b");
6945 emitcode("mov","@%s,a",rname);
6949 emitcode("movx","@dptr,a");
6953 emitcode("lcall","__gptrput");
6958 if ( SPEC_BLEN(etype) <= 8 )
6961 emitcode("inc","%s",rname);
6962 rLen = SPEC_BLEN(etype) ;
6964 /* now generate for lengths greater than one byte */
6967 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
6977 emitcode("mov","@%s,a",rname);
6979 emitcode("mov","@%s,%s",rname,l);
6984 emitcode("movx","@dptr,a");
6989 emitcode("lcall","__gptrput");
6992 emitcode ("inc","%s",rname);
6997 /* last last was not complete */
6999 /* save the byte & read byte */
7002 emitcode ("mov","b,a");
7003 emitcode("mov","a,@%s",rname);
7007 emitcode ("mov","b,a");
7008 emitcode("movx","a,@dptr");
7012 emitcode ("push","b");
7013 emitcode ("push","acc");
7014 emitcode ("lcall","__gptrget");
7015 emitcode ("pop","b");
7019 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7020 emitcode ("orl","a,b");
7023 if (p_type == GPOINTER)
7024 emitcode("pop","b");
7029 emitcode("mov","@%s,a",rname);
7033 emitcode("movx","@dptr,a");
7037 emitcode("lcall","__gptrput");
7041 /*-----------------------------------------------------------------*/
7042 /* genDataPointerSet - remat pointer to data space */
7043 /*-----------------------------------------------------------------*/
7044 static void genDataPointerSet(operand *right,
7048 int size, offset = 0 ;
7049 char *l, buffer[256];
7051 aopOp(right,ic,FALSE, FALSE);
7053 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7054 size = AOP_SIZE(right);
7057 sprintf(buffer,"(%s + %d)",l+1,offset);
7059 sprintf(buffer,"%s",l+1);
7060 emitcode("mov","%s,%s",buffer,
7061 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7064 freeAsmop(right,NULL,ic,TRUE);
7065 freeAsmop(result,NULL,ic,TRUE);
7068 /*-----------------------------------------------------------------*/
7069 /* genNearPointerSet - emitcode for near pointer put */
7070 /*-----------------------------------------------------------------*/
7071 static void genNearPointerSet (operand *right,
7079 link *ptype = operandType(result);
7081 retype= getSpec(operandType(right));
7083 aopOp(result,ic,FALSE, FALSE);
7085 /* if the result is rematerializable &
7086 in data space & not a bit variable */
7087 if (AOP_TYPE(result) == AOP_IMMD &&
7088 DCL_TYPE(ptype) == POINTER &&
7089 !IS_BITVAR(retype)) {
7090 genDataPointerSet (right,result,ic);
7094 /* if the value is already in a pointer register
7095 then don't need anything more */
7096 if (!AOP_INPREG(AOP(result))) {
7097 /* otherwise get a free pointer register */
7099 preg = getFreePtr(ic,&aop,FALSE);
7100 emitcode("mov","%s,%s",
7102 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7103 rname = preg->name ;
7105 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7107 freeAsmop(result,NULL,ic,TRUE);
7108 aopOp (right,ic,FALSE, FALSE);
7110 /* if bitfield then unpack the bits */
7111 if (IS_BITVAR(retype))
7112 genPackBits (retype,right,rname,POINTER);
7114 /* we have can just get the values */
7115 int size = AOP_SIZE(right);
7119 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7122 emitcode("mov","@%s,a",rname);
7124 emitcode("mov","@%s,%s",rname,l);
7126 emitcode("inc","%s",rname);
7131 /* now some housekeeping stuff */
7133 /* we had to allocate for this iCode */
7134 freeAsmop(NULL,aop,ic,TRUE);
7136 /* we did not allocate which means left
7137 already in a pointer register, then
7138 if size > 0 && this could be used again
7139 we have to point it back to where it
7141 if (AOP_SIZE(right) > 1 &&
7142 !OP_SYMBOL(result)->remat &&
7143 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7145 int size = AOP_SIZE(right) - 1;
7147 emitcode("dec","%s",rname);
7152 freeAsmop(right,NULL,ic,TRUE);
7157 /*-----------------------------------------------------------------*/
7158 /* genPagedPointerSet - emitcode for Paged pointer put */
7159 /*-----------------------------------------------------------------*/
7160 static void genPagedPointerSet (operand *right,
7169 retype= getSpec(operandType(right));
7171 aopOp(result,ic,FALSE, FALSE);
7173 /* if the value is already in a pointer register
7174 then don't need anything more */
7175 if (!AOP_INPREG(AOP(result))) {
7176 /* otherwise get a free pointer register */
7178 preg = getFreePtr(ic,&aop,FALSE);
7179 emitcode("mov","%s,%s",
7181 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7182 rname = preg->name ;
7184 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7186 freeAsmop(result,NULL,ic,TRUE);
7187 aopOp (right,ic,FALSE, FALSE);
7189 /* if bitfield then unpack the bits */
7190 if (IS_BITVAR(retype))
7191 genPackBits (retype,right,rname,PPOINTER);
7193 /* we have can just get the values */
7194 int size = AOP_SIZE(right);
7198 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7201 emitcode("movx","@%s,a",rname);
7204 emitcode("inc","%s",rname);
7210 /* now some housekeeping stuff */
7212 /* we had to allocate for this iCode */
7213 freeAsmop(NULL,aop,ic,TRUE);
7215 /* we did not allocate which means left
7216 already in a pointer register, then
7217 if size > 0 && this could be used again
7218 we have to point it back to where it
7220 if (AOP_SIZE(right) > 1 &&
7221 !OP_SYMBOL(result)->remat &&
7222 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7224 int size = AOP_SIZE(right) - 1;
7226 emitcode("dec","%s",rname);
7231 freeAsmop(right,NULL,ic,TRUE);
7236 /*-----------------------------------------------------------------*/
7237 /* genFarPointerSet - set value from far space */
7238 /*-----------------------------------------------------------------*/
7239 static void genFarPointerSet (operand *right,
7240 operand *result, iCode *ic)
7243 link *retype = getSpec(operandType(right));
7245 aopOp(result,ic,FALSE, FALSE);
7247 /* if the operand is already in dptr
7248 then we do nothing else we move the value to dptr */
7249 if (AOP_TYPE(result) != AOP_STR) {
7250 /* if this is remateriazable */
7251 if (AOP_TYPE(result) == AOP_IMMD)
7252 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7255 /* we need to get it byte by byte */
7256 if (AOP_TYPE(result) != AOP_DPTR)
7258 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7259 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7260 if (options.model == MODEL_FLAT24)
7262 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7267 /* We need to generate a load to DPTR indirect through DPTR. */
7268 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7269 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7270 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7271 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7272 emitcode("pop", "dph");
7273 emitcode("pop", "dpl");
7277 /* so dptr know contains the address */
7278 freeAsmop(result,NULL,ic,TRUE);
7279 aopOp(right,ic,FALSE, TRUE);
7281 /* if bit then unpack */
7282 if (IS_BITVAR(retype))
7283 genPackBits(retype,right,"dptr",FPOINTER);
7285 size = AOP_SIZE(right);
7289 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7291 emitcode("movx","@dptr,a");
7293 emitcode("inc","dptr");
7297 freeAsmop(right,NULL,ic,TRUE);
7300 /*-----------------------------------------------------------------*/
7301 /* genGenPointerSet - set value from generic pointer space */
7302 /*-----------------------------------------------------------------*/
7303 static void genGenPointerSet (operand *right,
7304 operand *result, iCode *ic)
7307 link *retype = getSpec(operandType(right));
7309 aopOp(result,ic,FALSE, TRUE);
7311 /* if the operand is already in dptr
7312 then we do nothing else we move the value to dptr */
7313 if (AOP_TYPE(result) != AOP_STR) {
7314 /* if this is remateriazable */
7315 if (AOP_TYPE(result) == AOP_IMMD) {
7316 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7317 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7319 else { /* we need to get it byte by byte */
7320 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7321 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7322 if (options.model == MODEL_FLAT24)
7324 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7325 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7329 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7333 /* so dptr know contains the address */
7334 freeAsmop(result,NULL,ic,TRUE);
7335 aopOp(right,ic,FALSE, TRUE);
7337 /* if bit then unpack */
7338 if (IS_BITVAR(retype))
7339 genPackBits(retype,right,"dptr",GPOINTER);
7341 size = AOP_SIZE(right);
7345 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7347 emitcode("lcall","__gptrput");
7349 emitcode("inc","dptr");
7353 freeAsmop(right,NULL,ic,TRUE);
7356 /*-----------------------------------------------------------------*/
7357 /* genPointerSet - stores the value into a pointer location */
7358 /*-----------------------------------------------------------------*/
7359 static void genPointerSet (iCode *ic)
7361 operand *right, *result ;
7365 D(emitcode(";", "genPointerSet "););
7367 right = IC_RIGHT(ic);
7368 result = IC_RESULT(ic) ;
7370 /* depending on the type of pointer we need to
7371 move it to the correct pointer register */
7372 type = operandType(result);
7373 etype = getSpec(type);
7374 /* if left is of type of pointer then it is simple */
7375 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7376 p_type = DCL_TYPE(type);
7379 /* we have to go by the storage class */
7380 p_type = PTR_TYPE(SPEC_OCLS(etype));
7382 /* if (SPEC_OCLS(etype)->codesp ) { */
7383 /* p_type = CPOINTER ; */
7386 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7387 /* p_type = FPOINTER ; */
7389 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7390 /* p_type = PPOINTER ; */
7392 /* if (SPEC_OCLS(etype) == idata ) */
7393 /* p_type = IPOINTER ; */
7395 /* p_type = POINTER ; */
7398 /* now that we have the pointer type we assign
7399 the pointer values */
7404 genNearPointerSet (right,result,ic);
7408 genPagedPointerSet (right,result,ic);
7412 genFarPointerSet (right,result,ic);
7416 genGenPointerSet (right,result,ic);
7422 /*-----------------------------------------------------------------*/
7423 /* genIfx - generate code for Ifx statement */
7424 /*-----------------------------------------------------------------*/
7425 static void genIfx (iCode *ic, iCode *popIc)
7427 operand *cond = IC_COND(ic);
7430 D(emitcode(";", "genIfx "););
7432 aopOp(cond,ic,FALSE, FALSE);
7434 /* get the value into acc */
7435 if (AOP_TYPE(cond) != AOP_CRY)
7439 /* the result is now in the accumulator */
7440 freeAsmop(cond,NULL,ic,TRUE);
7442 /* if there was something to be popped then do it */
7446 /* if the condition is a bit variable */
7447 if (isbit && IS_ITEMP(cond) &&
7449 genIfxJump(ic,SPIL_LOC(cond)->rname);
7451 if (isbit && !IS_ITEMP(cond))
7452 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7459 /*-----------------------------------------------------------------*/
7460 /* genAddrOf - generates code for address of */
7461 /*-----------------------------------------------------------------*/
7462 static void genAddrOf (iCode *ic)
7464 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7467 D(emitcode(";", "genAddrOf "););
7469 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7471 /* if the operand is on the stack then we
7472 need to get the stack offset of this
7475 /* if it has an offset then we need to compute
7478 emitcode("mov","a,_bp");
7479 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7480 aopPut(AOP(IC_RESULT(ic)),"a",0);
7482 /* we can just move _bp */
7483 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7485 /* fill the result with zero */
7486 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7489 if (options.stack10bit && size < (FPTRSIZE - 1))
7492 "*** warning: pointer to stack var truncated.\n");
7499 if (options.stack10bit && offset == 2)
7501 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7505 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7512 /* object not on stack then we need the name */
7513 size = AOP_SIZE(IC_RESULT(ic));
7517 char s[SDCC_NAME_MAX];
7519 sprintf(s,"#(%s >> %d)",
7523 sprintf(s,"#%s",sym->rname);
7524 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7528 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7532 /*-----------------------------------------------------------------*/
7533 /* genFarFarAssign - assignment when both are in far space */
7534 /*-----------------------------------------------------------------*/
7535 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7537 int size = AOP_SIZE(right);
7540 /* first push the right side on to the stack */
7542 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7544 emitcode ("push","acc");
7547 D(emitcode(";", "genFarFarAssign "););
7549 freeAsmop(right,NULL,ic,FALSE);
7550 /* now assign DPTR to result */
7551 aopOp(result,ic,FALSE, FALSE);
7552 size = AOP_SIZE(result);
7554 emitcode ("pop","acc");
7555 aopPut(AOP(result),"a",--offset);
7557 freeAsmop(result,NULL,ic,FALSE);
7561 /*-----------------------------------------------------------------*/
7562 /* genAssign - generate code for assignment */
7563 /*-----------------------------------------------------------------*/
7564 static void genAssign (iCode *ic)
7566 operand *result, *right;
7568 unsigned long lit = 0L;
7570 D(emitcode(";", "genAssign "););
7572 result = IC_RESULT(ic);
7573 right = IC_RIGHT(ic) ;
7575 /* if they are the same */
7576 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7579 aopOp(right,ic,FALSE, FALSE);
7581 emitcode(";", "genAssign: resultIsFar = %s",
7582 isOperandInFarSpace(result) ?
7585 /* special case both in far space */
7586 if ((AOP_TYPE(right) == AOP_DPTR ||
7587 AOP_TYPE(right) == AOP_DPTR2) &&
7588 /* IS_TRUE_SYMOP(result) && */
7589 isOperandInFarSpace(result)) {
7591 genFarFarAssign (result,right,ic);
7595 aopOp(result,ic,TRUE, FALSE);
7597 /* if they are the same registers */
7598 if (sameRegs(AOP(right),AOP(result)))
7601 /* if the result is a bit */
7602 if (AOP_TYPE(result) == AOP_CRY) {
7604 /* if the right size is a literal then
7605 we know what the value is */
7606 if (AOP_TYPE(right) == AOP_LIT) {
7607 if (((int) operandLitValue(right)))
7608 aopPut(AOP(result),one,0);
7610 aopPut(AOP(result),zero,0);
7614 /* the right is also a bit variable */
7615 if (AOP_TYPE(right) == AOP_CRY) {
7616 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7617 aopPut(AOP(result),"c",0);
7623 aopPut(AOP(result),"a",0);
7627 /* bit variables done */
7629 size = AOP_SIZE(result);
7631 if(AOP_TYPE(right) == AOP_LIT)
7632 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7634 (AOP_TYPE(result) != AOP_REG) &&
7635 (AOP_TYPE(right) == AOP_LIT) &&
7636 !IS_FLOAT(operandType(right)) &&
7638 emitcode("clr","a");
7640 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7641 aopPut(AOP(result),"a",size);
7644 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
7650 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7657 freeAsmop (right,NULL,ic,FALSE);
7658 freeAsmop (result,NULL,ic,TRUE);
7661 /*-----------------------------------------------------------------*/
7662 /* genJumpTab - genrates code for jump table */
7663 /*-----------------------------------------------------------------*/
7664 static void genJumpTab (iCode *ic)
7669 D(emitcode(";", "genJumpTab "););
7671 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7672 /* get the condition into accumulator */
7673 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
7675 /* multiply by four! */
7676 emitcode("add","a,acc");
7677 emitcode("add","a,acc");
7678 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7680 jtab = newiTempLabel(NULL);
7681 emitcode("mov","dptr,#%05d$",jtab->key+100);
7682 emitcode("jmp","@a+dptr");
7683 emitcode("","%05d$:",jtab->key+100);
7684 /* now generate the jump labels */
7685 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7686 jtab = setNextItem(IC_JTLABELS(ic)))
7687 emitcode("ljmp","%05d$",jtab->key+100);
7691 /*-----------------------------------------------------------------*/
7692 /* genCast - gen code for casting */
7693 /*-----------------------------------------------------------------*/
7694 static void genCast (iCode *ic)
7696 operand *result = IC_RESULT(ic);
7697 link *ctype = operandType(IC_LEFT(ic));
7698 link *rtype = operandType(IC_RIGHT(ic));
7699 operand *right = IC_RIGHT(ic);
7702 D(emitcode(";", "genCast "););
7704 /* if they are equivalent then do nothing */
7705 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7708 aopOp(right,ic,FALSE, FALSE) ;
7709 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7711 /* if the result is a bit */
7712 if (AOP_TYPE(result) == AOP_CRY) {
7713 /* if the right size is a literal then
7714 we know what the value is */
7715 if (AOP_TYPE(right) == AOP_LIT) {
7716 if (((int) operandLitValue(right)))
7717 aopPut(AOP(result),one,0);
7719 aopPut(AOP(result),zero,0);
7724 /* the right is also a bit variable */
7725 if (AOP_TYPE(right) == AOP_CRY) {
7726 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7727 aopPut(AOP(result),"c",0);
7733 aopPut(AOP(result),"a",0);
7737 /* if they are the same size : or less */
7738 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7740 /* if they are in the same place */
7741 if (sameRegs(AOP(right),AOP(result)))
7744 /* if they in different places then copy */
7745 size = AOP_SIZE(result);
7749 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7757 /* if the result is of type pointer */
7758 if (IS_PTR(ctype)) {
7761 link *type = operandType(right);
7763 /* pointer to generic pointer */
7764 if (IS_GENPTR(ctype)) {
7769 p_type = DCL_TYPE(type);
7773 #if OLD_CAST_BEHAVIOR
7774 /* KV: we are converting a non-pointer type to
7775 * a generic pointer. This (ifdef'd out) code
7776 * says that the resulting generic pointer
7777 * should have the same class as the storage
7778 * location of the non-pointer variable.
7780 * For example, converting an int (which happens
7781 * to be stored in DATA space) to a pointer results
7782 * in a DATA generic pointer; if the original int
7783 * in XDATA space, so will be the resulting pointer.
7785 * I don't like that behavior, and thus this change:
7786 * all such conversions will be forced to XDATA and
7787 * throw a warning. If you want some non-XDATA
7788 * type, or you want to suppress the warning, you
7789 * must go through an intermediate cast, like so:
7791 * char _generic *gp = (char _xdata *)(intVar);
7793 link *etype = getSpec(type);
7795 /* we have to go by the storage class */
7796 if (SPEC_OCLS(etype) != generic)
7798 p_type = PTR_TYPE(SPEC_OCLS(etype));
7803 /* Converting unknown class (i.e. register variable)
7804 * to generic pointer. This is not good, but
7805 * we'll make a guess (and throw a warning).
7808 werror(W_INT_TO_GEN_PTR_CAST);
7812 /* the first two bytes are known */
7813 size = GPTRSIZE - 1;
7817 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7822 /* the last byte depending on type */
7839 /* this should never happen */
7840 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7841 "got unknown pointer type");
7844 aopPut(AOP(result),l, GPTRSIZE - 1);
7848 /* just copy the pointers */
7849 size = AOP_SIZE(result);
7853 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7860 /* so we now know that the size of destination is greater
7861 than the size of the source */
7862 /* we move to result for the size of source */
7863 size = AOP_SIZE(right);
7867 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7872 /* now depending on the sign of the source && destination */
7873 size = AOP_SIZE(result) - AOP_SIZE(right);
7874 /* if unsigned or not an integral type */
7875 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7877 aopPut(AOP(result),zero,offset++);
7879 /* we need to extend the sign :{ */
7880 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7883 emitcode("rlc","a");
7884 emitcode("subb","a,acc");
7886 aopPut(AOP(result),"a",offset++);
7889 /* we are done hurray !!!! */
7892 freeAsmop(right,NULL,ic,TRUE);
7893 freeAsmop(result,NULL,ic,TRUE);
7897 /*-----------------------------------------------------------------*/
7898 /* genDjnz - generate decrement & jump if not zero instrucion */
7899 /*-----------------------------------------------------------------*/
7900 static int genDjnz (iCode *ic, iCode *ifx)
7906 /* if the if condition has a false label
7907 then we cannot save */
7911 /* if the minus is not of the form
7913 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7914 !IS_OP_LITERAL(IC_RIGHT(ic)))
7917 if (operandLitValue(IC_RIGHT(ic)) != 1)
7920 /* if the size of this greater than one then no
7922 if (getSize(operandType(IC_RESULT(ic))) > 1)
7925 /* otherwise we can save BIG */
7926 lbl = newiTempLabel(NULL);
7927 lbl1= newiTempLabel(NULL);
7929 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7931 if (IS_AOP_PREG(IC_RESULT(ic))) {
7932 emitcode("dec","%s",
7933 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
7934 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
7935 emitcode("jnz","%05d$",lbl->key+100);
7937 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
7940 emitcode ("sjmp","%05d$",lbl1->key+100);
7941 emitcode ("","%05d$:",lbl->key+100);
7942 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7943 emitcode ("","%05d$:",lbl1->key+100);
7945 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7950 /*-----------------------------------------------------------------*/
7951 /* genReceive - generate code for a receive iCode */
7952 /*-----------------------------------------------------------------*/
7953 static void genReceive (iCode *ic)
7956 D(emitcode(";", "genReceive "););
7958 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7959 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7960 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7961 int size = getSize(operandType(IC_RESULT(ic)));
7962 int offset = fReturnSize_390 - size;
7964 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
7965 fReturn[fReturnSize_390 - offset - 1] : "acc"));
7968 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7969 size = AOP_SIZE(IC_RESULT(ic));
7972 emitcode ("pop","acc");
7973 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7978 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7980 assignResultValue(IC_RESULT(ic));
7983 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7986 /*-----------------------------------------------------------------*/
7987 /* gen390Code - generate code for 8051 based controllers */
7988 /*-----------------------------------------------------------------*/
7989 void gen390Code (iCode *lic)
7994 lineHead = lineCurr = NULL;
7996 /* print the allocation information */
7998 printAllocInfo( currFunc, codeOutFile);
7999 /* if debug information required */
8000 /* if (options.debug && currFunc) { */
8002 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8004 if (IS_STATIC(currFunc->etype))
8005 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8007 emitcode("","G$%s$0$0 ==.",currFunc->name);
8010 /* stack pointer name */
8011 if (options.useXstack)
8017 for (ic = lic ; ic ; ic = ic->next ) {
8019 if ( cln != ic->lineno ) {
8020 if ( options.debug ) {
8022 emitcode("","C$%s$%d$%d$%d ==.",
8023 ic->filename,ic->lineno,
8024 ic->level,ic->block);
8027 emitcode(";","%s %d",ic->filename,ic->lineno);
8030 /* if the result is marked as
8031 spilt and rematerializable or code for
8032 this has already been generated then
8034 if (resultRemat(ic) || ic->generated )
8037 /* depending on the operation */
8056 /* IPOP happens only when trying to restore a
8057 spilt live range, if there is an ifx statement
8058 following this pop then the if statement might
8059 be using some of the registers being popped which
8060 would destory the contents of the register so
8061 we need to check for this condition and handle it */
8063 ic->next->op == IFX &&
8064 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8065 genIfx (ic->next,ic);
8083 genEndFunction (ic);
8103 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8120 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8124 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8131 /* note these two are xlated by algebraic equivalence
8132 during parsing SDCC.y */
8133 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8134 "got '>=' or '<=' shouldn't have come here");
8138 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8150 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8154 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8158 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8185 case GET_VALUE_AT_ADDRESS:
8190 if (POINTER_SET(ic))
8217 addSet(&_G.sendSet,ic);
8222 /* piCode(ic,stdout); */
8228 /* now we are ready to call the
8229 peep hole optimizer */
8230 if (!options.nopeep)
8231 peepHole (&lineHead);
8233 /* now do the actual printing */
8234 printLine (lineHead,codeOutFile);