1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
37 #ifdef HAVE_SYS_ISA_DEFS_H
38 #include <sys/isa_defs.h>
44 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
45 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #include "SDCCpeeph.h"
55 char *aopLiteral (value *val, int offset);
58 /* this is the down and dirty file with all kinds of
59 kludgy & hacky stuff. This is what it is all about
60 CODE GENERATION for a specific MCU . some of the
61 routines may be reusable, will have to see */
63 static char *zero = "#0x00";
64 static char *one = "#0x01";
69 unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
70 static char *fReturn[] = {"dpl","dph","dpx", "b","a" };
71 static char *accUse[] = {"a","b"};
73 static short rbank = -1;
85 extern int ds390_ptrRegReq ;
86 extern int ds390_nRegs;
87 extern FILE *codeOutFile;
88 static void saverbank (int, iCode *,bool);
89 #define RESULTONSTACK(x) \
90 (IC_RESULT(x) && IC_RESULT(x)->aop && \
91 IC_RESULT(x)->aop->type == AOP_STK )
93 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
94 #define MOVA(x) { char *_mova_tmp = strdup(x); \
95 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
97 emitcode("mov","a,%s",_mova_tmp); \
101 #define CLRC emitcode("clr","c")
102 #define SETC emitcode("setb","c")
104 static lineNode *lineHead = NULL;
105 static lineNode *lineCurr = NULL;
107 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
108 0xE0, 0xC0, 0x80, 0x00};
109 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
110 0x07, 0x03, 0x01, 0x00};
117 /*-----------------------------------------------------------------*/
118 /* emitcode - writes the code into a file : for now it is simple */
119 /*-----------------------------------------------------------------*/
120 static void emitcode (char *inst,char *fmt, ...)
123 char lb[MAX_INLINEASM];
130 sprintf(lb,"%s\t",inst);
132 sprintf(lb,"%s",inst);
133 vsprintf(lb+(strlen(lb)),fmt,ap);
137 while (isspace(*lbp)) lbp++;
140 lineCurr = (lineCurr ?
141 connectLine(lineCurr,newLineNode(lb)) :
142 (lineHead = newLineNode(lb)));
143 lineCurr->isInline = _G.inLine;
144 lineCurr->isDebug = _G.debugLine;
148 /*-----------------------------------------------------------------*/
149 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
150 /*-----------------------------------------------------------------*/
151 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
153 bool r0iu = FALSE , r1iu = FALSE;
154 bool r0ou = FALSE , r1ou = FALSE;
156 /* the logic: if r0 & r1 used in the instruction
157 then we are in trouble otherwise */
159 /* first check if r0 & r1 are used by this
160 instruction, in which case we are in trouble */
161 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
162 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
167 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
168 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
170 /* if no usage of r0 then return it */
171 if (!r0iu && !r0ou) {
172 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
173 (*aopp)->type = AOP_R0;
175 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
178 /* if no usage of r1 then return it */
179 if (!r1iu && !r1ou) {
180 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
181 (*aopp)->type = AOP_R1;
183 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R1_IDX);
186 /* now we know they both have usage */
187 /* if r0 not used in this instruction */
189 /* push it if not already pushed */
191 emitcode ("push","%s",
192 ds390_regWithIdx(R0_IDX)->dname);
196 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
197 (*aopp)->type = AOP_R0;
199 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
202 /* if r1 not used then */
205 /* push it if not already pushed */
207 emitcode ("push","%s",
208 ds390_regWithIdx(R1_IDX)->dname);
212 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
213 (*aopp)->type = AOP_R1;
214 return ds390_regWithIdx(R1_IDX);
218 /* I said end of world but not quite end of world yet */
219 /* if this is a result then we can push it on the stack*/
221 (*aopp)->type = AOP_STK;
226 /* other wise this is true end of the world */
227 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
228 "getFreePtr should never reach here");
232 /*-----------------------------------------------------------------*/
233 /* newAsmop - creates a new asmOp */
234 /*-----------------------------------------------------------------*/
235 static asmop *newAsmop (short type)
239 ALLOC(aop,sizeof(asmop));
244 static void genSetDPTR(int n)
248 emitcode("mov", "dps, #0x00");
252 emitcode("mov", "dps, #0x01");
256 /*-----------------------------------------------------------------*/
257 /* pointerCode - returns the code for a pointer type */
258 /*-----------------------------------------------------------------*/
259 static int pointerCode (link *etype)
262 return PTR_TYPE(SPEC_OCLS(etype));
266 /*-----------------------------------------------------------------*/
267 /* aopForSym - for a true symbol */
268 /*-----------------------------------------------------------------*/
269 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
272 memmap *space= SPEC_OCLS(sym->etype);
274 /* if already has one */
278 /* assign depending on the storage class */
279 /* if it is on the stack or indirectly addressable */
280 /* space we need to assign either r0 or r1 to it */
281 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
282 sym->aop = aop = newAsmop(0);
283 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
284 aop->size = getSize(sym->type);
286 /* now assign the address of the variable to
287 the pointer register */
288 if (aop->type != AOP_STK) {
292 emitcode("push","acc");
294 emitcode("mov","a,_bp");
295 emitcode("add","a,#0x%02x",
297 ((char)(sym->stack - _G.nRegsSaved )) :
298 ((char)sym->stack)) & 0xff);
299 emitcode("mov","%s,a",
300 aop->aopu.aop_ptr->name);
303 emitcode("pop","acc");
305 emitcode("mov","%s,#%s",
306 aop->aopu.aop_ptr->name,
308 aop->paged = space->paged;
310 aop->aopu.aop_stk = sym->stack;
314 if (sym->onStack && options.stack10bit)
316 /* It's on the 10 bit stack, which is located in
321 emitcode("push","acc");
323 emitcode("mov","a,_bp");
324 emitcode("add","a,#0x%02x",
326 ((char)(sym->stack - _G.nRegsSaved )) :
327 ((char)sym->stack)) & 0xff);
332 emitcode ("mov","dpx1,#0x40");
333 emitcode ("mov","dph1,#0x00");
334 emitcode ("mov","dpl1, a");
339 emitcode ("mov","dpx,#0x40");
340 emitcode ("mov","dph,#0x00");
341 emitcode ("mov","dpl, a");
345 emitcode("pop","acc");
347 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
348 aop->size = getSize(sym->type);
352 /* if in bit space */
353 if (IN_BITSPACE(space)) {
354 sym->aop = aop = newAsmop (AOP_CRY);
355 aop->aopu.aop_dir = sym->rname ;
356 aop->size = getSize(sym->type);
359 /* if it is in direct space */
360 if (IN_DIRSPACE(space)) {
361 sym->aop = aop = newAsmop (AOP_DIR);
362 aop->aopu.aop_dir = sym->rname ;
363 aop->size = getSize(sym->type);
367 /* special case for a function */
368 if (IS_FUNC(sym->type)) {
369 sym->aop = aop = newAsmop(AOP_IMMD);
370 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
371 strcpy(aop->aopu.aop_immd,sym->rname);
372 aop->size = FPTRSIZE;
376 /* only remaining is far space */
377 /* in which case DPTR gets the address */
378 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
382 emitcode ("mov","dptr,#%s", sym->rname);
387 emitcode ("mov","dptr,#%s", sym->rname);
389 aop->size = getSize(sym->type);
391 /* if it is in code space */
392 if (IN_CODESPACE(space))
398 /*-----------------------------------------------------------------*/
399 /* aopForRemat - rematerialzes an object */
400 /*-----------------------------------------------------------------*/
401 static asmop *aopForRemat (symbol *sym)
403 iCode *ic = sym->rematiCode;
404 asmop *aop = newAsmop(AOP_IMMD);
410 val += operandLitValue(IC_RIGHT(ic));
411 else if (ic->op == '-')
412 val -= operandLitValue(IC_RIGHT(ic));
416 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
420 sprintf(buffer,"(%s %c 0x%04x)",
421 OP_SYMBOL(IC_LEFT(ic))->rname,
422 val >= 0 ? '+' : '-',
425 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
427 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
428 strcpy(aop->aopu.aop_immd,buffer);
432 /*-----------------------------------------------------------------*/
433 /* regsInCommon - two operands have some registers in common */
434 /*-----------------------------------------------------------------*/
435 static bool regsInCommon (operand *op1, operand *op2)
440 /* if they have registers in common */
441 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
444 sym1 = OP_SYMBOL(op1);
445 sym2 = OP_SYMBOL(op2);
447 if (sym1->nRegs == 0 || sym2->nRegs == 0)
450 for (i = 0 ; i < sym1->nRegs ; i++) {
455 for (j = 0 ; j < sym2->nRegs ;j++ ) {
459 if (sym2->regs[j] == sym1->regs[i])
467 /*-----------------------------------------------------------------*/
468 /* operandsEqu - equivalent */
469 /*-----------------------------------------------------------------*/
470 static bool operandsEqu ( operand *op1, operand *op2)
474 /* if they not symbols */
475 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
478 sym1 = OP_SYMBOL(op1);
479 sym2 = OP_SYMBOL(op2);
481 /* if both are itemps & one is spilt
482 and the other is not then false */
483 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
484 sym1->isspilt != sym2->isspilt )
487 /* if they are the same */
491 if (strcmp(sym1->rname,sym2->rname) == 0)
495 /* if left is a tmp & right is not */
499 (sym1->usl.spillLoc == sym2))
506 (sym2->usl.spillLoc == sym1))
512 /*-----------------------------------------------------------------*/
513 /* sameRegs - two asmops have the same registers */
514 /*-----------------------------------------------------------------*/
515 static bool sameRegs (asmop *aop1, asmop *aop2 )
521 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
528 if (aop1->type != AOP_REG ||
529 aop2->type != AOP_REG )
532 if (aop1->size != aop2->size )
535 for (i = 0 ; i < aop1->size ; i++ )
536 if (aop1->aopu.aop_reg[i] !=
537 aop2->aopu.aop_reg[i] )
543 /*-----------------------------------------------------------------*/
544 /* aopOp - allocates an asmop for an operand : */
545 /*-----------------------------------------------------------------*/
546 static void aopOp (operand *op, iCode *ic, bool result, bool useDP2)
555 /* if this a literal */
556 if (IS_OP_LITERAL(op)) {
557 op->aop = aop = newAsmop(AOP_LIT);
558 aop->aopu.aop_lit = op->operand.valOperand;
559 aop->size = getSize(operandType(op));
563 /* if already has a asmop then continue */
567 /* if the underlying symbol has a aop */
568 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
569 op->aop = OP_SYMBOL(op)->aop;
573 /* if this is a true symbol */
574 if (IS_TRUE_SYMOP(op)) {
575 op->aop = aopForSym(ic,OP_SYMBOL(op),result, useDP2);
579 /* this is a temporary : this has
585 e) can be a return use only */
590 /* if the type is a conditional */
591 if (sym->regType == REG_CND) {
592 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
597 /* if it is spilt then two situations
599 b) has a spill location */
600 if (sym->isspilt || sym->nRegs == 0) {
602 /* rematerialize it NOW */
604 sym->aop = op->aop = aop =
606 aop->size = getSize(sym->type);
612 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
613 aop->size = getSize(sym->type);
614 for ( i = 0 ; i < 2 ; i++ )
615 aop->aopu.aop_str[i] = accUse[i];
621 aop = op->aop = sym->aop = newAsmop(AOP_STR);
622 aop->size = getSize(sym->type);
623 for ( i = 0 ; i < fReturnSize_390 ; i++ )
624 aop->aopu.aop_str[i] = fReturn[i];
628 /* else spill location */
629 sym->aop = op->aop = aop =
630 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
631 aop->size = getSize(sym->type);
635 /* must be in a register */
636 sym->aop = op->aop = aop = newAsmop(AOP_REG);
637 aop->size = sym->nRegs;
638 for ( i = 0 ; i < sym->nRegs ;i++)
639 aop->aopu.aop_reg[i] = sym->regs[i];
642 /*-----------------------------------------------------------------*/
643 /* freeAsmop - free up the asmop given to an operand */
644 /*----------------------------------------------------------------*/
645 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
662 /* depending on the asmop type only three cases need work AOP_RO
663 , AOP_R1 && AOP_STK */
668 emitcode ("pop","ar0");
672 bitVectUnSetBit(ic->rUsed,R0_IDX);
678 emitcode ("pop","ar1");
682 bitVectUnSetBit(ic->rUsed,R1_IDX);
688 int stk = aop->aopu.aop_stk + aop->size;
689 bitVectUnSetBit(ic->rUsed,R0_IDX);
690 bitVectUnSetBit(ic->rUsed,R1_IDX);
692 getFreePtr(ic,&aop,FALSE);
694 if (options.stack10bit)
696 /* I'm not sure what to do here yet... */
699 "*** Warning: probably generating bad code for "
700 "10 bit stack mode.\n");
704 emitcode ("mov","a,_bp");
705 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
706 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
708 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
712 emitcode("pop","acc");
713 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
715 emitcode("dec","%s",aop->aopu.aop_ptr->name);
718 freeAsmop(op,NULL,ic,TRUE);
720 emitcode("pop","ar0");
725 emitcode("pop","ar1");
732 /* all other cases just dealloc */
736 OP_SYMBOL(op)->aop = NULL;
737 /* if the symbol has a spill */
739 SPIL_LOC(op)->aop = NULL;
744 /*------------------------------------------------------------------*/
745 /* aopGet - for fetching value of the aop */
747 /* Set canClobberACC if you are aure it is OK to clobber the value */
748 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe,*/
749 /* just less efficient. */
750 /*------------------------------------------------------------------*/
752 static char *aopGet (asmop *aop,
761 /* offset is greater than
763 if (offset > (aop->size - 1) &&
764 aop->type != AOP_LIT)
767 /* depending on type */
772 /* if we need to increment it */
773 while (offset > aop->coff) {
774 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
778 while (offset < aop->coff) {
779 emitcode("dec","%s",aop->aopu.aop_ptr->name);
785 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
786 return (dname ? "acc" : "a");
788 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
789 ALLOC_ATOMIC(rs,strlen(s)+1);
796 if (aop->type == AOP_DPTR2)
800 #ifndef KEVIN_BROKE_IT
804 emitcode("xch", "a, ap");
808 while (offset > aop->coff) {
809 emitcode ("inc","dptr");
813 while (offset < aop->coff) {
814 emitcode("lcall","__decdptr");
821 emitcode("movc","a,@a+dptr");
824 emitcode("movx","a,@dptr");
827 if (aop->type == AOP_DPTR2)
831 #ifndef KEVIN_BROKE_IT
835 emitcode("xch", "a, ap");
840 return (dname ? "acc" : "a");
845 sprintf (s,"#%s",aop->aopu.aop_immd);
848 sprintf(s,"#(%s >> %d)",
854 ALLOC_ATOMIC(rs,strlen(s)+1);
860 sprintf(s,"(%s + %d)",
864 sprintf(s,"%s",aop->aopu.aop_dir);
865 ALLOC_ATOMIC(rs,strlen(s)+1);
871 return aop->aopu.aop_reg[offset]->dname;
873 return aop->aopu.aop_reg[offset]->name;
877 emitcode("mov","c,%s",aop->aopu.aop_dir);
878 emitcode("rlc","a") ;
879 return (dname ? "acc" : "a");
882 if (!offset && dname)
884 return aop->aopu.aop_str[offset];
887 return aopLiteral (aop->aopu.aop_lit,offset);
891 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
895 return aop->aopu.aop_str[offset];
899 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
900 "aopget got unsupported aop->type");
903 /*-----------------------------------------------------------------*/
904 /* aopPut - puts a string for a aop */
905 /*-----------------------------------------------------------------*/
906 static void aopPut (asmop *aop, char *s, int offset)
911 if (aop->size && offset > ( aop->size - 1)) {
912 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
913 "aopPut got offset > aop->size");
917 /* will assign value to value */
918 /* depending on where it is ofcourse */
922 sprintf(d,"(%s + %d)",
923 aop->aopu.aop_dir,offset);
925 sprintf(d,"%s",aop->aopu.aop_dir);
928 emitcode("mov","%s,%s",d,s);
933 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
934 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
936 strcmp(s,"r0") == 0 ||
937 strcmp(s,"r1") == 0 ||
938 strcmp(s,"r2") == 0 ||
939 strcmp(s,"r3") == 0 ||
940 strcmp(s,"r4") == 0 ||
941 strcmp(s,"r5") == 0 ||
942 strcmp(s,"r6") == 0 ||
943 strcmp(s,"r7") == 0 )
944 emitcode("mov","%s,%s",
945 aop->aopu.aop_reg[offset]->dname,s);
947 emitcode("mov","%s,%s",
948 aop->aopu.aop_reg[offset]->name,s);
955 if (aop->type == AOP_DPTR2)
961 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
962 "aopPut writting to code space");
966 while (offset > aop->coff) {
968 emitcode ("inc","dptr");
971 while (offset < aop->coff) {
973 emitcode("lcall","__decdptr");
978 /* if not in accumulater */
981 emitcode ("movx","@dptr,a");
983 if (aop->type == AOP_DPTR2)
991 while (offset > aop->coff) {
993 emitcode("inc","%s",aop->aopu.aop_ptr->name);
995 while (offset < aop->coff) {
997 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1003 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1008 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1010 if (strcmp(s,"r0") == 0 ||
1011 strcmp(s,"r1") == 0 ||
1012 strcmp(s,"r2") == 0 ||
1013 strcmp(s,"r3") == 0 ||
1014 strcmp(s,"r4") == 0 ||
1015 strcmp(s,"r5") == 0 ||
1016 strcmp(s,"r6") == 0 ||
1017 strcmp(s,"r7") == 0 ) {
1019 sprintf(buffer,"a%s",s);
1020 emitcode("mov","@%s,%s",
1021 aop->aopu.aop_ptr->name,buffer);
1023 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1028 if (strcmp(s,"a") == 0)
1029 emitcode("push","acc");
1031 emitcode("push","%s",s);
1036 /* if bit variable */
1037 if (!aop->aopu.aop_dir) {
1038 emitcode("clr","a");
1039 emitcode("rlc","a");
1042 emitcode("clr","%s",aop->aopu.aop_dir);
1045 emitcode("setb","%s",aop->aopu.aop_dir);
1048 emitcode("mov","%s,c",aop->aopu.aop_dir);
1050 lbl = newiTempLabel(NULL);
1052 if (strcmp(s,"a")) {
1055 emitcode("clr","c");
1056 emitcode("jz","%05d$",lbl->key+100);
1057 emitcode("cpl","c");
1058 emitcode("","%05d$:",lbl->key+100);
1059 emitcode("mov","%s,c",aop->aopu.aop_dir);
1066 if (strcmp(aop->aopu.aop_str[offset],s))
1067 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1072 if (!offset && (strcmp(s,"acc") == 0))
1075 if (strcmp(aop->aopu.aop_str[offset],s))
1076 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1080 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1081 "aopPut got unsupported aop->type");
1089 /*-----------------------------------------------------------------*/
1090 /* pointToEnd :- points to the last byte of the operand */
1091 /*-----------------------------------------------------------------*/
1092 static void pointToEnd (asmop *aop)
1098 aop->coff = count = (aop->size - 1);
1099 switch (aop->type) {
1103 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1107 emitcode("inc","dptr");
1114 /*-----------------------------------------------------------------*/
1115 /* reAdjustPreg - points a register back to where it should */
1116 /*-----------------------------------------------------------------*/
1117 static void reAdjustPreg (asmop *aop)
1122 if ((size = aop->size) <= 1)
1125 switch (aop->type) {
1129 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1133 if (aop->type == AOP_DPTR2)
1139 emitcode("lcall","__decdptr");
1142 if (aop->type == AOP_DPTR2)
1152 #define AOP(op) op->aop
1153 #define AOP_TYPE(op) AOP(op)->type
1154 #define AOP_SIZE(op) AOP(op)->size
1155 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1156 AOP_TYPE(x) == AOP_R0))
1158 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1159 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1162 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1163 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1164 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1166 /* Workaround for DS80C390 bug: div ab may return bogus results
1167 * if A is accessed in instruction immediately before the div.
1169 * Will be fixed in B4 rev of processor, Dallas claims.
1172 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1173 if (!AOP_NEEDSACC(RIGHT)) \
1175 /* We can load A first, then B, since \
1176 * B (the RIGHT operand) won't clobber A, \
1177 * thus avoiding touching A right before the div. \
1179 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1180 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1182 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1186 /* Just stuff in a nop after loading A. */ \
1187 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1188 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1190 emitcode("nop", "; workaround for DS80C390 div bug."); \
1193 /*-----------------------------------------------------------------*/
1194 /* genNotFloat - generates not for float operations */
1195 /*-----------------------------------------------------------------*/
1196 static void genNotFloat (operand *op, operand *res)
1202 D(emitcode(";", "genNotFloat "););
1204 /* we will put 127 in the first byte of
1206 aopPut(AOP(res),"#127",0);
1207 size = AOP_SIZE(op) - 1;
1210 l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
1214 emitcode("orl","a,%s",
1216 offset++,FALSE,FALSE,FALSE));
1218 tlbl = newiTempLabel(NULL);
1220 tlbl = newiTempLabel(NULL);
1221 aopPut(res->aop,one,1);
1222 emitcode("jz","%05d$",(tlbl->key+100));
1223 aopPut(res->aop,zero,1);
1224 emitcode("","%05d$:",(tlbl->key+100));
1226 size = res->aop->size - 2;
1228 /* put zeros in the rest */
1230 aopPut(res->aop,zero,offset++);
1233 /*-----------------------------------------------------------------*/
1234 /* opIsGptr: returns non-zero if the passed operand is */
1235 /* a generic pointer type. */
1236 /*-----------------------------------------------------------------*/
1237 static int opIsGptr(operand *op)
1239 link *type = operandType(op);
1241 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1248 /*-----------------------------------------------------------------*/
1249 /* getDataSize - get the operand data size */
1250 /*-----------------------------------------------------------------*/
1251 static int getDataSize(operand *op)
1254 size = AOP_SIZE(op);
1255 if (size == GPTRSIZE)
1257 link *type = operandType(op);
1258 if (IS_GENPTR(type))
1260 /* generic pointer; arithmetic operations
1261 * should ignore the high byte (pointer type).
1269 /*-----------------------------------------------------------------*/
1270 /* outAcc - output Acc */
1271 /*-----------------------------------------------------------------*/
1272 static void outAcc(operand *result)
1275 size = getDataSize(result);
1277 aopPut(AOP(result),"a",0);
1280 /* unsigned or positive */
1282 aopPut(AOP(result),zero,offset++);
1287 /*-----------------------------------------------------------------*/
1288 /* outBitC - output a bit C */
1289 /*-----------------------------------------------------------------*/
1290 static void outBitC(operand *result)
1292 /* if the result is bit */
1293 if (AOP_TYPE(result) == AOP_CRY)
1294 aopPut(AOP(result),"c",0);
1296 emitcode("clr","a");
1297 emitcode("rlc","a");
1302 /*-----------------------------------------------------------------*/
1303 /* toBoolean - emit code for orl a,operator(sizeop) */
1304 /*-----------------------------------------------------------------*/
1305 static void toBoolean(operand *oper)
1307 int size = AOP_SIZE(oper) - 1;
1310 if (AOP_NEEDSACC(oper))
1312 emitcode("push", "b");
1313 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1317 MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1321 if (AOP_NEEDSACC(oper))
1323 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1327 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1331 if (AOP_NEEDSACC(oper))
1333 emitcode("mov", "a,b");
1334 emitcode("pop", "b");
1339 /*-----------------------------------------------------------------*/
1340 /* genNot - generate code for ! operation */
1341 /*-----------------------------------------------------------------*/
1342 static void genNot (iCode *ic)
1345 link *optype = operandType(IC_LEFT(ic));
1347 D(emitcode(";", "genNot "););
1349 /* assign asmOps to operand & result */
1350 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1351 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1353 /* if in bit space then a special case */
1354 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1355 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1356 emitcode("cpl","c");
1357 outBitC(IC_RESULT(ic));
1361 /* if type float then do float */
1362 if (IS_FLOAT(optype)) {
1363 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1367 toBoolean(IC_LEFT(ic));
1369 tlbl = newiTempLabel(NULL);
1370 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1371 emitcode("","%05d$:",tlbl->key+100);
1372 outBitC(IC_RESULT(ic));
1375 /* release the aops */
1376 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1377 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1381 /*-----------------------------------------------------------------*/
1382 /* genCpl - generate code for complement */
1383 /*-----------------------------------------------------------------*/
1384 static void genCpl (iCode *ic)
1389 D(emitcode(";", "genCpl "););
1392 /* assign asmOps to operand & result */
1393 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1394 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1396 /* if both are in bit space then
1398 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1399 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1401 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1402 emitcode("cpl","c");
1403 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1407 size = AOP_SIZE(IC_RESULT(ic));
1409 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1411 emitcode("cpl","a");
1412 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1417 /* release the aops */
1418 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1419 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1422 /*-----------------------------------------------------------------*/
1423 /* genUminusFloat - unary minus for floating points */
1424 /*-----------------------------------------------------------------*/
1425 static void genUminusFloat(operand *op,operand *result)
1427 int size ,offset =0 ;
1429 /* for this we just need to flip the
1430 first it then copy the rest in place */
1431 D(emitcode(";", "genUminusFloat"););
1433 size = AOP_SIZE(op) - 1;
1434 l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1437 emitcode("cpl","acc.7");
1438 aopPut(AOP(result),"a",3);
1442 aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1448 /*-----------------------------------------------------------------*/
1449 /* genUminus - unary minus code generation */
1450 /*-----------------------------------------------------------------*/
1451 static void genUminus (iCode *ic)
1454 link *optype, *rtype;
1456 D(emitcode(";", "genUminus "););
1460 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1461 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1463 /* if both in bit space then special
1465 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1466 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1468 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1469 emitcode("cpl","c");
1470 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1474 optype = operandType(IC_LEFT(ic));
1475 rtype = operandType(IC_RESULT(ic));
1477 /* if float then do float stuff */
1478 if (IS_FLOAT(optype)) {
1479 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1483 /* otherwise subtract from zero */
1484 size = AOP_SIZE(IC_LEFT(ic));
1488 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1489 if (!strcmp(l,"a")) {
1492 emitcode("cpl","a");
1493 emitcode("addc", "a,#0");
1497 emitcode("clr","a");
1498 emitcode("subb","a,%s",l);
1500 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1503 /* if any remaining bytes in the result */
1504 /* we just need to propagate the sign */
1505 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1506 emitcode("rlc","a");
1507 emitcode("subb","a,acc");
1509 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1513 /* release the aops */
1514 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1515 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1518 /*-----------------------------------------------------------------*/
1519 /* saveRegisters - will look for a call and save the registers */
1520 /*-----------------------------------------------------------------*/
1521 static void saveRegisters(iCode *lic)
1529 for (ic = lic ; ic ; ic = ic->next)
1530 if (ic->op == CALL || ic->op == PCALL)
1534 fprintf(stderr,"found parameter push with no function call\n");
1538 /* if the registers have been saved already then
1540 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1543 /* find the registers in use at this time
1544 and push them away to safety */
1545 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1549 if (options.useXstack) {
1550 if (bitVectBitValue(rsave,R0_IDX))
1551 emitcode("mov","b,r0");
1552 emitcode("mov","r0,%s",spname);
1553 for (i = 0 ; i < ds390_nRegs ; i++) {
1554 if (bitVectBitValue(rsave,i)) {
1556 emitcode("mov","a,b");
1558 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1559 emitcode("movx","@r0,a");
1560 emitcode("inc","r0");
1563 emitcode("mov","%s,r0",spname);
1564 if (bitVectBitValue(rsave,R0_IDX))
1565 emitcode("mov","r0,b");
1567 for (i = 0 ; i < ds390_nRegs ; i++) {
1568 if (bitVectBitValue(rsave,i))
1569 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1572 detype = getSpec(operandType(IC_LEFT(ic)));
1574 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1575 IS_ISR(currFunc->etype) &&
1578 saverbank(SPEC_BANK(detype),ic,TRUE);
1581 /*-----------------------------------------------------------------*/
1582 /* unsaveRegisters - pop the pushed registers */
1583 /*-----------------------------------------------------------------*/
1584 static void unsaveRegisters (iCode *ic)
1588 /* find the registers in use at this time
1589 and push them away to safety */
1590 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1593 if (options.useXstack) {
1594 emitcode("mov","r0,%s",spname);
1595 for (i = ds390_nRegs ; i >= 0 ; i--) {
1596 if (bitVectBitValue(rsave,i)) {
1597 emitcode("dec","r0");
1598 emitcode("movx","a,@r0");
1600 emitcode("mov","b,a");
1602 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1606 emitcode("mov","%s,r0",spname);
1607 if (bitVectBitValue(rsave,R0_IDX))
1608 emitcode("mov","r0,b");
1610 for (i = ds390_nRegs ; i >= 0 ; i--) {
1611 if (bitVectBitValue(rsave,i))
1612 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1618 /*-----------------------------------------------------------------*/
1620 /*-----------------------------------------------------------------*/
1621 static void pushSide(operand * oper, int size)
1625 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1626 if (AOP_TYPE(oper) != AOP_REG &&
1627 AOP_TYPE(oper) != AOP_DIR &&
1629 emitcode("mov","a,%s",l);
1630 emitcode("push","acc");
1632 emitcode("push","%s",l);
1636 /*-----------------------------------------------------------------*/
1637 /* assignResultValue - */
1638 /*-----------------------------------------------------------------*/
1639 static void assignResultValue(operand * oper)
1642 int size = AOP_SIZE(oper);
1644 aopPut(AOP(oper),fReturn[offset],offset);
1650 /*-----------------------------------------------------------------*/
1651 /* genXpush - pushes onto the external stack */
1652 /*-----------------------------------------------------------------*/
1653 static void genXpush (iCode *ic)
1655 asmop *aop = newAsmop(0);
1657 int size,offset = 0;
1659 D(emitcode(";", "genXpush "););
1661 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1662 r = getFreePtr(ic,&aop,FALSE);
1665 emitcode("mov","%s,_spx",r->name);
1667 size = AOP_SIZE(IC_LEFT(ic));
1670 char *l = aopGet(AOP(IC_LEFT(ic)),
1671 offset++,FALSE,FALSE,TRUE);
1673 emitcode("movx","@%s,a",r->name);
1674 emitcode("inc","%s",r->name);
1679 emitcode("mov","_spx,%s",r->name);
1681 freeAsmop(NULL,aop,ic,TRUE);
1682 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1685 /*-----------------------------------------------------------------*/
1686 /* genIpush - genrate code for pushing this gets a little complex */
1687 /*-----------------------------------------------------------------*/
1688 static void genIpush (iCode *ic)
1690 int size, offset = 0 ;
1693 D(emitcode(";", "genIpush "););
1696 /* if this is not a parm push : ie. it is spill push
1697 and spill push is always done on the local stack */
1698 if (!ic->parmPush) {
1700 /* and the item is spilt then do nothing */
1701 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1704 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1705 size = AOP_SIZE(IC_LEFT(ic));
1706 /* push it on the stack */
1708 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1713 emitcode("push","%s",l);
1718 /* this is a paramter push: in this case we call
1719 the routine to find the call and save those
1720 registers that need to be saved */
1723 /* if use external stack then call the external
1724 stack pushing routine */
1725 if (options.useXstack) {
1730 /* then do the push */
1731 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1734 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1735 size = AOP_SIZE(IC_LEFT(ic));
1738 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1739 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1740 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1742 emitcode("mov","a,%s",l);
1743 emitcode("push","acc");
1745 emitcode("push","%s",l);
1748 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1751 /*-----------------------------------------------------------------*/
1752 /* genIpop - recover the registers: can happen only for spilling */
1753 /*-----------------------------------------------------------------*/
1754 static void genIpop (iCode *ic)
1758 D(emitcode(";", "genIpop "););
1761 /* if the temp was not pushed then */
1762 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1765 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1766 size = AOP_SIZE(IC_LEFT(ic));
1769 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1772 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1775 /*-----------------------------------------------------------------*/
1776 /* unsaverbank - restores the resgister bank from stack */
1777 /*-----------------------------------------------------------------*/
1778 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1785 if (options.useXstack) {
1787 r = getFreePtr(ic,&aop,FALSE);
1790 emitcode("mov","%s,_spx",r->name);
1791 emitcode("movx","a,@%s",r->name);
1792 emitcode("mov","psw,a");
1793 emitcode("dec","%s",r->name);
1796 emitcode ("pop","psw");
1799 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1800 if (options.useXstack) {
1801 emitcode("movx","a,@%s",r->name);
1802 emitcode("mov","(%s+%d),a",
1803 regs390[i].base,8*bank+regs390[i].offset);
1804 emitcode("dec","%s",r->name);
1807 emitcode("pop","(%s+%d)",
1808 regs390[i].base,8*bank+regs390[i].offset);
1811 if (options.useXstack) {
1813 emitcode("mov","_spx,%s",r->name);
1814 freeAsmop(NULL,aop,ic,TRUE);
1819 /*-----------------------------------------------------------------*/
1820 /* saverbank - saves an entire register bank on the stack */
1821 /*-----------------------------------------------------------------*/
1822 static void saverbank (int bank, iCode *ic, bool pushPsw)
1828 if (options.useXstack) {
1831 r = getFreePtr(ic,&aop,FALSE);
1832 emitcode("mov","%s,_spx",r->name);
1836 for (i = 0 ; i < ds390_nRegs ;i++) {
1837 if (options.useXstack) {
1838 emitcode("inc","%s",r->name);
1839 emitcode("mov","a,(%s+%d)",
1840 regs390[i].base,8*bank+regs390[i].offset);
1841 emitcode("movx","@%s,a",r->name);
1843 emitcode("push","(%s+%d)",
1844 regs390[i].base,8*bank+regs390[i].offset);
1848 if (options.useXstack) {
1849 emitcode("mov","a,psw");
1850 emitcode("movx","@%s,a",r->name);
1851 emitcode("inc","%s",r->name);
1852 emitcode("mov","_spx,%s",r->name);
1853 freeAsmop (NULL,aop,ic,TRUE);
1856 emitcode("push","psw");
1858 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1864 /*-----------------------------------------------------------------*/
1865 /* genCall - generates a call statement */
1866 /*-----------------------------------------------------------------*/
1867 static void genCall (iCode *ic)
1871 D(emitcode(";", "genCall "););
1873 /* if caller saves & we have not saved then */
1877 /* if we are calling a function that is not using
1878 the same register bank then we need to save the
1879 destination registers on the stack */
1880 detype = getSpec(operandType(IC_LEFT(ic)));
1882 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1883 IS_ISR(currFunc->etype) &&
1886 saverbank(SPEC_BANK(detype),ic,TRUE);
1888 /* if send set is not empty the assign */
1892 for (sic = setFirstItem(_G.sendSet) ; sic ;
1893 sic = setNextItem(_G.sendSet)) {
1894 int size, offset = 0;
1895 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
1896 size = AOP_SIZE(IC_LEFT(sic));
1898 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1899 FALSE, FALSE, FALSE);
1900 if (strcmp(l,fReturn[offset]))
1901 emitcode("mov","%s,%s",
1906 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1911 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1912 OP_SYMBOL(IC_LEFT(ic))->rname :
1913 OP_SYMBOL(IC_LEFT(ic))->name));
1915 /* if we need assign a result value */
1916 if ((IS_ITEMP(IC_RESULT(ic)) &&
1917 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1918 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1919 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1921 if (!isOperandInFarSpace(IC_RESULT(ic)))
1924 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1927 assignResultValue(IC_RESULT(ic));
1929 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1933 /* Result is in far space, and requires DPTR to access
1934 * it. Push the result onto the stack and restore from
1937 int size = getSize(operandType(IC_RESULT(ic)));
1938 int offset = size - 1;
1941 emitcode(";", "Kevin function call abuse #1");
1943 /* first push the right side on to the stack */
1944 /* NB: this relies on the fact that "a" is the last
1945 * register in fReturn. If it were not, the MOVA
1946 * would potentially clobber a returned byte in A.
1949 l = fReturn[offset--];
1951 emitcode ("push","acc");
1954 /* now assign DPTR to result */
1955 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1956 size = AOP_SIZE(IC_RESULT(ic));
1957 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
1959 emitcode ("pop","acc");
1960 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
1962 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1966 /* adjust the stack for parameters if
1968 if (IC_LEFT(ic)->parmBytes) {
1970 if (IC_LEFT(ic)->parmBytes > 3) {
1971 emitcode("mov","a,%s",spname);
1972 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1973 emitcode("mov","%s,a",spname);
1975 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1976 emitcode("dec","%s",spname);
1980 /* if register bank was saved then pop them */
1982 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1984 /* if we hade saved some registers then unsave them */
1985 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1986 unsaveRegisters (ic);
1991 /*-----------------------------------------------------------------*/
1992 /* genPcall - generates a call by pointer statement */
1993 /*-----------------------------------------------------------------*/
1994 static void genPcall (iCode *ic)
1997 symbol *rlbl = newiTempLabel(NULL);
1999 D(emitcode(";", "genPcall "););
2002 /* if caller saves & we have not saved then */
2006 /* if we are calling a function that is not using
2007 the same register bank then we need to save the
2008 destination registers on the stack */
2009 detype = getSpec(operandType(IC_LEFT(ic)));
2011 IS_ISR(currFunc->etype) &&
2012 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2013 saverbank(SPEC_BANK(detype),ic,TRUE);
2016 /* push the return address on to the stack */
2017 emitcode("mov","a,#%05d$",(rlbl->key+100));
2018 emitcode("push","acc");
2019 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2020 emitcode("push","acc");
2022 if (options.model == MODEL_FLAT24)
2024 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2025 emitcode("push","acc");
2028 /* now push the calling address */
2029 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2031 pushSide(IC_LEFT(ic), FPTRSIZE);
2033 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2035 /* if send set is not empty the assign */
2039 for (sic = setFirstItem(_G.sendSet) ; sic ;
2040 sic = setNextItem(_G.sendSet)) {
2041 int size, offset = 0;
2042 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2043 size = AOP_SIZE(IC_LEFT(sic));
2045 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2047 if (strcmp(l,fReturn[offset]))
2048 emitcode("mov","%s,%s",
2053 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2059 emitcode("","%05d$:",(rlbl->key+100));
2062 /* if we need assign a result value */
2063 if ((IS_ITEMP(IC_RESULT(ic)) &&
2064 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2065 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2066 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2069 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2072 assignResultValue(IC_RESULT(ic));
2074 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2077 /* adjust the stack for parameters if
2079 if (IC_LEFT(ic)->parmBytes) {
2081 if (IC_LEFT(ic)->parmBytes > 3) {
2082 emitcode("mov","a,%s",spname);
2083 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2084 emitcode("mov","%s,a",spname);
2086 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2087 emitcode("dec","%s",spname);
2091 /* if register bank was saved then unsave them */
2093 (SPEC_BANK(currFunc->etype) !=
2095 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2097 /* if we hade saved some registers then
2100 unsaveRegisters (ic);
2104 /*-----------------------------------------------------------------*/
2105 /* resultRemat - result is rematerializable */
2106 /*-----------------------------------------------------------------*/
2107 static int resultRemat (iCode *ic)
2109 if (SKIP_IC(ic) || ic->op == IFX)
2112 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2113 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2114 if (sym->remat && !POINTER_SET(ic))
2122 #define STRCASECMP stricmp
2124 #define STRCASECMP strcasecmp
2127 /*-----------------------------------------------------------------*/
2128 /* inExcludeList - return 1 if the string is in exclude Reg list */
2129 /*-----------------------------------------------------------------*/
2130 static bool inExcludeList(char *s)
2134 if (options.excludeRegs[i] &&
2135 STRCASECMP(options.excludeRegs[i],"none") == 0)
2138 for ( i = 0 ; options.excludeRegs[i]; i++) {
2139 if (options.excludeRegs[i] &&
2140 STRCASECMP(s,options.excludeRegs[i]) == 0)
2146 /*-----------------------------------------------------------------*/
2147 /* genFunction - generated code for function entry */
2148 /*-----------------------------------------------------------------*/
2149 static void genFunction (iCode *ic)
2154 D(emitcode(";", "genFunction "););
2157 /* create the function header */
2158 emitcode(";","-----------------------------------------");
2159 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2160 emitcode(";","-----------------------------------------");
2162 emitcode("","%s:",sym->rname);
2163 fetype = getSpec(operandType(IC_LEFT(ic)));
2165 /* if critical function then turn interrupts off */
2166 if (SPEC_CRTCL(fetype))
2167 emitcode("clr","ea");
2169 /* here we need to generate the equates for the
2170 register bank if required */
2171 if (SPEC_BANK(fetype) != rbank) {
2174 rbank = SPEC_BANK(fetype);
2175 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2176 if (strcmp(regs390[i].base,"0") == 0)
2177 emitcode("","%s = 0x%02x",
2179 8*rbank+regs390[i].offset);
2181 emitcode ("","%s = %s + 0x%02x",
2184 8*rbank+regs390[i].offset);
2188 /* if this is an interrupt service routine then
2189 save acc, b, dpl, dph */
2190 if (IS_ISR(sym->etype)) {
2192 if (!inExcludeList("acc"))
2193 emitcode ("push","acc");
2194 if (!inExcludeList("b"))
2195 emitcode ("push","b");
2196 if (!inExcludeList("dpl"))
2197 emitcode ("push","dpl");
2198 if (!inExcludeList("dph"))
2199 emitcode ("push","dph");
2200 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2202 emitcode ("push", "dpx");
2203 /* Make sure we're using standard DPTR */
2204 emitcode ("push", "dps");
2205 emitcode ("mov", "dps, #0x00");
2206 if (options.stack10bit)
2208 /* This ISR could conceivably use DPTR2. Better save it. */
2209 emitcode ("push", "dpl1");
2210 emitcode ("push", "dph1");
2211 emitcode ("push", "dpx1");
2212 emitcode ("push", "ap");
2215 /* if this isr has no bank i.e. is going to
2216 run with bank 0 , then we need to save more
2218 if (!SPEC_BANK(sym->etype)) {
2220 /* if this function does not call any other
2221 function then we can be economical and
2222 save only those registers that are used */
2223 if (! sym->hasFcall) {
2226 /* if any registers used */
2227 if (sym->regsUsed) {
2228 /* save the registers used */
2229 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2230 if (bitVectBitValue(sym->regsUsed,i) ||
2231 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2232 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2237 /* this function has a function call cannot
2238 determines register usage so we will have the
2240 saverbank(0,ic,FALSE);
2244 /* if callee-save to be used for this function
2245 then save the registers being used in this function */
2246 if (sym->calleeSave) {
2249 /* if any registers used */
2250 if (sym->regsUsed) {
2251 /* save the registers used */
2252 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2253 if (bitVectBitValue(sym->regsUsed,i) ||
2254 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2255 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2263 /* set the register bank to the desired value */
2264 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2265 emitcode("push","psw");
2266 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2269 if (IS_RENT(sym->etype) || options.stackAuto) {
2271 if (options.useXstack) {
2272 emitcode("mov","r0,%s",spname);
2273 emitcode("mov","a,_bp");
2274 emitcode("movx","@r0,a");
2275 emitcode("inc","%s",spname);
2279 /* set up the stack */
2280 emitcode ("push","_bp"); /* save the callers stack */
2282 emitcode ("mov","_bp,%s",spname);
2285 /* adjust the stack for the function */
2290 werror(W_STACK_OVERFLOW,sym->name);
2292 if (i > 3 && sym->recvSize < 4) {
2294 emitcode ("mov","a,sp");
2295 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2296 emitcode ("mov","sp,a");
2301 emitcode("inc","sp");
2306 emitcode ("mov","a,_spx");
2307 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2308 emitcode ("mov","_spx,a");
2313 /*-----------------------------------------------------------------*/
2314 /* genEndFunction - generates epilogue for functions */
2315 /*-----------------------------------------------------------------*/
2316 static void genEndFunction (iCode *ic)
2318 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2320 D(emitcode(";", "genEndFunction "););
2322 if (IS_RENT(sym->etype) || options.stackAuto)
2324 emitcode ("mov","%s,_bp",spname);
2327 /* if use external stack but some variables were
2328 added to the local stack then decrement the
2330 if (options.useXstack && sym->stack) {
2331 emitcode("mov","a,sp");
2332 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2333 emitcode("mov","sp,a");
2337 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2338 if (options.useXstack) {
2339 emitcode("mov","r0,%s",spname);
2340 emitcode("movx","a,@r0");
2341 emitcode("mov","_bp,a");
2342 emitcode("dec","%s",spname);
2346 emitcode ("pop","_bp");
2350 /* restore the register bank */
2351 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2352 emitcode ("pop","psw");
2354 if (IS_ISR(sym->etype)) {
2356 /* now we need to restore the registers */
2357 /* if this isr has no bank i.e. is going to
2358 run with bank 0 , then we need to save more
2360 if (!SPEC_BANK(sym->etype)) {
2362 /* if this function does not call any other
2363 function then we can be economical and
2364 save only those registers that are used */
2365 if (! sym->hasFcall) {
2368 /* if any registers used */
2369 if (sym->regsUsed) {
2370 /* save the registers used */
2371 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2372 if (bitVectBitValue(sym->regsUsed,i) ||
2373 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2374 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2379 /* this function has a function call cannot
2380 determines register usage so we will have the
2382 unsaverbank(0,ic,FALSE);
2386 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2388 if (options.stack10bit)
2390 emitcode ("pop", "ap");
2391 emitcode ("pop", "dpx1");
2392 emitcode ("pop", "dph1");
2393 emitcode ("pop", "dpl1");
2395 emitcode ("pop", "dps");
2396 emitcode ("pop", "dpx");
2398 if (!inExcludeList("dph"))
2399 emitcode ("pop","dph");
2400 if (!inExcludeList("dpl"))
2401 emitcode ("pop","dpl");
2402 if (!inExcludeList("b"))
2403 emitcode ("pop","b");
2404 if (!inExcludeList("acc"))
2405 emitcode ("pop","acc");
2407 if (SPEC_CRTCL(sym->etype))
2408 emitcode("setb","ea");
2410 /* if debug then send end of function */
2411 /* if (options.debug && currFunc) { */
2414 emitcode("","C$%s$%d$%d$%d ==.",
2415 ic->filename,currFunc->lastLine,
2416 ic->level,ic->block);
2417 if (IS_STATIC(currFunc->etype))
2418 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2420 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2424 emitcode ("reti","");
2427 if (SPEC_CRTCL(sym->etype))
2428 emitcode("setb","ea");
2430 if (sym->calleeSave) {
2433 /* if any registers used */
2434 if (sym->regsUsed) {
2435 /* save the registers used */
2436 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2437 if (bitVectBitValue(sym->regsUsed,i) ||
2438 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2439 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2445 /* if debug then send end of function */
2448 emitcode("","C$%s$%d$%d$%d ==.",
2449 ic->filename,currFunc->lastLine,
2450 ic->level,ic->block);
2451 if (IS_STATIC(currFunc->etype))
2452 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2454 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2458 emitcode ("ret","");
2463 /*-----------------------------------------------------------------*/
2464 /* genRet - generate code for return statement */
2465 /*-----------------------------------------------------------------*/
2466 static void genRet (iCode *ic)
2468 int size,offset = 0 , pushed = 0;
2470 D(emitcode(";", "genRet "););
2472 /* if we have no return value then
2473 just generate the "ret" */
2477 /* we have something to return then
2478 move the return value into place */
2479 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2480 size = AOP_SIZE(IC_LEFT(ic));
2484 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2485 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2487 emitcode("push","%s",l);
2490 l = aopGet(AOP(IC_LEFT(ic)),offset,
2492 if (strcmp(fReturn[offset],l))
2493 emitcode("mov","%s,%s",fReturn[offset++],l);
2500 if (strcmp(fReturn[pushed],"a"))
2501 emitcode("pop",fReturn[pushed]);
2503 emitcode("pop","acc");
2506 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2509 /* generate a jump to the return label
2510 if the next is not the return statement */
2511 if (!(ic->next && ic->next->op == LABEL &&
2512 IC_LABEL(ic->next) == returnLabel))
2514 emitcode("ljmp","%05d$",(returnLabel->key+100));
2518 /*-----------------------------------------------------------------*/
2519 /* genLabel - generates a label */
2520 /*-----------------------------------------------------------------*/
2521 static void genLabel (iCode *ic)
2523 /* special case never generate */
2524 if (IC_LABEL(ic) == entryLabel)
2527 D(emitcode(";", "genLabel "););
2529 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2532 /*-----------------------------------------------------------------*/
2533 /* genGoto - generates a ljmp */
2534 /*-----------------------------------------------------------------*/
2535 static void genGoto (iCode *ic)
2537 D(emitcode(";", "genGoto "););
2538 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2541 /*-----------------------------------------------------------------*/
2542 /* findLabelBackwards: walks back through the iCode chain looking */
2543 /* for the given label. Returns number of iCode instructions */
2544 /* between that label and given ic. */
2545 /* Returns zero if label not found. */
2546 /*-----------------------------------------------------------------*/
2547 static int findLabelBackwards(iCode *ic, int key)
2556 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2558 /* printf("findLabelBackwards = %d\n", count); */
2566 /*-----------------------------------------------------------------*/
2567 /* genPlusIncr :- does addition with increment if possible */
2568 /*-----------------------------------------------------------------*/
2569 static bool genPlusIncr (iCode *ic)
2571 unsigned int icount ;
2572 unsigned int size = getDataSize(IC_RESULT(ic));
2574 /* will try to generate an increment */
2575 /* if the right side is not a literal
2577 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2580 /* if the literal value of the right hand side
2581 is greater than 4 then it is not worth it */
2582 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2585 /* if increment 16 bits in register */
2587 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2588 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2589 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2596 /* If the next instruction is a goto and the goto target
2597 * is <= 5 instructions previous to this, we can generate
2598 * jumps straight to that target.
2600 if (ic->next && ic->next->op == GOTO
2601 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2602 && labelRange <= 5 )
2604 emitcode(";", "tail increment optimized (range %d)", labelRange);
2605 tlbl = IC_LABEL(ic->next);
2610 tlbl = newiTempLabel(NULL);
2613 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2614 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2615 IS_AOP_PREG(IC_RESULT(ic)))
2616 emitcode("cjne","%s,#0x00,%05d$"
2617 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2620 emitcode("clr","a");
2621 emitcode("cjne","a,%s,%05d$"
2622 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2626 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2629 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2630 IS_AOP_PREG(IC_RESULT(ic)))
2631 emitcode("cjne","%s,#0x00,%05d$"
2632 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2635 emitcode("cjne","a,%s,%05d$"
2636 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2639 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2643 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2644 IS_AOP_PREG(IC_RESULT(ic)))
2645 emitcode("cjne","%s,#0x00,%05d$"
2646 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2649 emitcode("cjne","a,%s,%05d$"
2650 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2653 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2658 emitcode("","%05d$:",tlbl->key+100);
2663 /* if the sizes are greater than 1 then we cannot */
2664 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2665 AOP_SIZE(IC_LEFT(ic)) > 1 )
2668 /* we can if the aops of the left & result match or
2669 if they are in registers and the registers are the
2672 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2673 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2674 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2677 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2678 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2679 aopPut(AOP(IC_RESULT(ic)),"a",0);
2683 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2692 /*-----------------------------------------------------------------*/
2693 /* outBitAcc - output a bit in acc */
2694 /*-----------------------------------------------------------------*/
2695 static void outBitAcc(operand *result)
2697 symbol *tlbl = newiTempLabel(NULL);
2698 /* if the result is a bit */
2699 if (AOP_TYPE(result) == AOP_CRY){
2700 aopPut(AOP(result),"a",0);
2703 emitcode("jz","%05d$",tlbl->key+100);
2704 emitcode("mov","a,%s",one);
2705 emitcode("","%05d$:",tlbl->key+100);
2710 /*-----------------------------------------------------------------*/
2711 /* genPlusBits - generates code for addition of two bits */
2712 /*-----------------------------------------------------------------*/
2713 static void genPlusBits (iCode *ic)
2715 D(emitcode(";", "genPlusBits "););
2716 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2717 symbol *lbl = newiTempLabel(NULL);
2718 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2719 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2720 emitcode("cpl","c");
2721 emitcode("","%05d$:",(lbl->key+100));
2722 outBitC(IC_RESULT(ic));
2725 emitcode("clr","a");
2726 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2727 emitcode("rlc","a");
2728 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2729 emitcode("addc","a,#0x00");
2730 outAcc(IC_RESULT(ic));
2734 static void adjustArithmeticResult(iCode *ic)
2736 if (opIsGptr(IC_RESULT(ic)) &&
2737 opIsGptr(IC_LEFT(ic)) &&
2738 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2740 aopPut(AOP(IC_RESULT(ic)),
2741 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2745 if (opIsGptr(IC_RESULT(ic)) &&
2746 opIsGptr(IC_RIGHT(ic)) &&
2747 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2749 aopPut(AOP(IC_RESULT(ic)),
2750 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2754 if (opIsGptr(IC_RESULT(ic)) &&
2755 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2756 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2757 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2758 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2760 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2761 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2765 #define AOP_OP_3(ic) \
2766 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2767 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2768 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2769 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2770 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2772 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2774 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2777 #define AOP_SET_LOCALS(ic) \
2778 left = IC_LEFT(ic); \
2779 right = IC_RIGHT(ic); \
2780 result = IC_RESULT(ic);
2782 /*-----------------------------------------------------------------*/
2783 /* genPlus - generates code for addition */
2784 /*-----------------------------------------------------------------*/
2785 static void genPlus (iCode *ic)
2787 int size, offset = 0;
2788 bool pushResult = FALSE;
2790 D(emitcode(";", "genPlus "););
2792 /* special cases :- */
2794 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2795 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2796 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2797 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2803 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR);
2805 /* if literal, literal on the right or
2806 if left requires ACC or right is already
2808 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2809 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2810 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2811 operand *t = IC_RIGHT(ic);
2812 IC_RIGHT(ic) = IC_LEFT(ic);
2816 /* if both left & right are in bit
2818 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2819 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2824 /* if left in bit space & right literal */
2825 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2826 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2827 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2828 /* if result in bit space */
2829 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2830 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2831 emitcode("cpl","c");
2832 outBitC(IC_RESULT(ic));
2834 size = getDataSize(IC_RESULT(ic));
2836 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
2837 emitcode("addc","a,#00");
2838 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2844 /* if I can do an increment instead
2845 of add then GOOD for ME */
2846 if (genPlusIncr (ic) == TRUE)
2850 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
2853 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2854 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
2856 emitcode("add","a,%s",
2857 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
2859 emitcode("addc","a,%s",
2860 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
2862 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
2864 emitcode("add","a,%s",
2865 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
2867 emitcode("addc","a,%s",
2868 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
2872 aopPut(AOP(IC_RESULT(ic)),"a",offset);
2876 emitcode("push", "acc");
2883 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2885 size = getDataSize(IC_LEFT(ic));
2887 /* If the pushed data is bigger than the result,
2888 * simply discard unused bytes. Icky, but works.
2890 * Should we throw a warning here? We're losing data...
2892 while (size > getDataSize(IC_RESULT(ic)))
2894 emitcode(";", "discarding unused result byte.");
2895 emitcode("pop", "acc");
2902 emitcode("pop", "acc");
2903 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
2907 adjustArithmeticResult(ic);
2910 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2911 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2912 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2915 /*-----------------------------------------------------------------*/
2916 /* genMinusDec :- does subtraction with deccrement if possible */
2917 /*-----------------------------------------------------------------*/
2918 static bool genMinusDec (iCode *ic)
2920 unsigned int icount ;
2921 unsigned int size = getDataSize(IC_RESULT(ic));
2923 /* will try to generate an increment */
2924 /* if the right side is not a literal
2926 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2929 /* if the literal value of the right hand side
2930 is greater than 4 then it is not worth it */
2931 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2934 /* if decrement 16 bits in register */
2935 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2936 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2937 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2944 /* If the next instruction is a goto and the goto target
2945 * is <= 5 instructions previous to this, we can generate
2946 * jumps straight to that target.
2948 if (ic->next && ic->next->op == GOTO
2949 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2950 && labelRange <= 5 )
2952 emitcode(";", "tail decrement optimized (range %d)", labelRange);
2953 tlbl = IC_LABEL(ic->next);
2958 tlbl = newiTempLabel(NULL);
2962 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2963 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2964 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2965 IS_AOP_PREG(IC_RESULT(ic)))
2966 emitcode("cjne","%s,#0xff,%05d$"
2967 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2970 emitcode("mov","a,#0xff");
2971 emitcode("cjne","a,%s,%05d$"
2972 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2975 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2978 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2979 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2980 IS_AOP_PREG(IC_RESULT(ic)))
2981 emitcode("cjne","%s,#0xff,%05d$"
2982 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2985 emitcode("cjne","a,%s,%05d$"
2986 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2989 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2993 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2994 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
2995 IS_AOP_PREG(IC_RESULT(ic)))
2996 emitcode("cjne","%s,#0xff,%05d$"
2997 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3000 emitcode("cjne","a,%s,%05d$"
3001 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3004 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3008 emitcode("","%05d$:",tlbl->key+100);
3013 /* if the sizes are greater than 1 then we cannot */
3014 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3015 AOP_SIZE(IC_LEFT(ic)) > 1 )
3018 /* we can if the aops of the left & result match or
3019 if they are in registers and the registers are the
3022 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3023 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3024 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3027 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3035 /*-----------------------------------------------------------------*/
3036 /* addSign - complete with sign */
3037 /*-----------------------------------------------------------------*/
3038 static void addSign(operand *result, int offset, int sign)
3040 int size = (getDataSize(result) - offset);
3043 emitcode("rlc","a");
3044 emitcode("subb","a,acc");
3046 aopPut(AOP(result),"a",offset++);
3049 aopPut(AOP(result),zero,offset++);
3053 /*-----------------------------------------------------------------*/
3054 /* genMinusBits - generates code for subtraction of two bits */
3055 /*-----------------------------------------------------------------*/
3056 static void genMinusBits (iCode *ic)
3058 symbol *lbl = newiTempLabel(NULL);
3060 D(emitcode(";", "genMinusBits "););
3062 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3063 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3064 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3065 emitcode("cpl","c");
3066 emitcode("","%05d$:",(lbl->key+100));
3067 outBitC(IC_RESULT(ic));
3070 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3071 emitcode("subb","a,acc");
3072 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3073 emitcode("inc","a");
3074 emitcode("","%05d$:",(lbl->key+100));
3075 aopPut(AOP(IC_RESULT(ic)),"a",0);
3076 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3080 /*-----------------------------------------------------------------*/
3081 /* genMinus - generates code for subtraction */
3082 /*-----------------------------------------------------------------*/
3083 static void genMinus (iCode *ic)
3085 int size, offset = 0;
3086 unsigned long lit = 0L;
3087 bool pushResult = FALSE;
3089 D(emitcode(";", "genMinus "););
3091 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3092 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3093 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3094 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3100 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3102 /* special cases :- */
3103 /* if both left & right are in bit space */
3104 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3105 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3110 /* if I can do an decrement instead
3111 of subtract then GOOD for ME */
3112 if (genMinusDec (ic) == TRUE)
3117 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3119 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3123 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3128 /* if literal, add a,#-lit, else normal subb */
3130 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3131 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3132 emitcode("subb","a,%s",
3133 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3135 /* first add without previous c */
3137 emitcode("add","a,#0x%02x",
3138 (unsigned int)(lit & 0x0FFL));
3140 emitcode("addc","a,#0x%02x",
3141 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3146 emitcode("push", "acc");
3150 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3157 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3159 size = getDataSize(IC_LEFT(ic));
3161 /* If the pushed data is bigger than the result,
3162 * simply discard unused bytes. Icky, but works.
3164 * Should we throw a warning here? We're losing data...
3166 while (size > getDataSize(IC_RESULT(ic)))
3168 emitcode(";", "discarding unused result byte.");
3169 emitcode("pop", "acc");
3176 emitcode("pop", "acc");
3177 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3181 adjustArithmeticResult(ic);
3184 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3185 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3186 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3190 /*-----------------------------------------------------------------*/
3191 /* genMultbits :- multiplication of bits */
3192 /*-----------------------------------------------------------------*/
3193 static void genMultbits (operand *left,
3197 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3198 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3203 /*-----------------------------------------------------------------*/
3204 /* genMultOneByte : 8 bit multiplication & division */
3205 /*-----------------------------------------------------------------*/
3206 static void genMultOneByte (operand *left,
3210 link *opetype = operandType(result);
3215 /* (if two literals, the value is computed before) */
3216 /* if one literal, literal on the right */
3217 if (AOP_TYPE(left) == AOP_LIT){
3223 size = AOP_SIZE(result);
3224 /* signed or unsigned */
3225 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3226 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3228 emitcode("mul","ab");
3229 /* if result size = 1, mul signed = mul unsigned */
3230 aopPut(AOP(result),"a",0);
3232 if (SPEC_USIGN(opetype)){
3233 aopPut(AOP(result),"b",1);
3235 /* for filling the MSBs */
3236 emitcode("clr","a");
3239 emitcode("mov","a,b");
3241 /* adjust the MSB if left or right neg */
3243 /* if one literal */
3244 if (AOP_TYPE(right) == AOP_LIT){
3245 /* AND literal negative */
3246 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3247 /* adjust MSB (c==0 after mul) */
3248 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3252 lbl = newiTempLabel(NULL);
3253 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3254 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3255 emitcode("","%05d$:",(lbl->key+100));
3256 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3257 lbl = newiTempLabel(NULL);
3258 emitcode("jc","%05d$",(lbl->key+100));
3259 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3260 emitcode("","%05d$:",(lbl->key+100));
3263 lbl = newiTempLabel(NULL);
3264 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3265 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3266 emitcode("","%05d$:",(lbl->key+100));
3267 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3268 lbl = newiTempLabel(NULL);
3269 emitcode("jc","%05d$",(lbl->key+100));
3270 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3271 emitcode("","%05d$:",(lbl->key+100));
3273 aopPut(AOP(result),"a",1);
3276 emitcode("rlc","a");
3277 emitcode("subb","a,acc");
3284 aopPut(AOP(result),"a",offset++);
3288 /*-----------------------------------------------------------------*/
3289 /* genMult - generates code for multiplication */
3290 /*-----------------------------------------------------------------*/
3291 static void genMult (iCode *ic)
3293 operand *left = IC_LEFT(ic);
3294 operand *right = IC_RIGHT(ic);
3295 operand *result= IC_RESULT(ic);
3297 D(emitcode(";", "genMult "););
3299 /* assign the amsops */
3302 aopOp (left,ic,FALSE, FALSE);
3303 aopOp (right,ic,FALSE, TRUE);
3304 aopOp (result,ic,TRUE, FALSE);
3307 /* special cases first */
3309 if (AOP_TYPE(left) == AOP_CRY &&
3310 AOP_TYPE(right)== AOP_CRY) {
3311 genMultbits(left,right,result);
3315 /* if both are of size == 1 */
3316 if (AOP_SIZE(left) == 1 &&
3317 AOP_SIZE(right) == 1 ) {
3318 genMultOneByte(left,right,result);
3322 /* should have been converted to function call */
3326 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3327 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3328 freeAsmop(result,NULL,ic,TRUE);
3331 /*-----------------------------------------------------------------*/
3332 /* genDivbits :- division of bits */
3333 /*-----------------------------------------------------------------*/
3334 static void genDivbits (operand *left,
3341 /* the result must be bit */
3342 LOAD_AB_FOR_DIV(left, right, l);
3343 emitcode("div","ab");
3344 emitcode("rrc","a");
3345 aopPut(AOP(result),"c",0);
3348 /*-----------------------------------------------------------------*/
3349 /* genDivOneByte : 8 bit division */
3350 /*-----------------------------------------------------------------*/
3351 static void genDivOneByte (operand *left,
3355 link *opetype = operandType(result);
3360 size = AOP_SIZE(result) - 1;
3362 /* signed or unsigned */
3363 if (SPEC_USIGN(opetype)) {
3364 /* unsigned is easy */
3365 LOAD_AB_FOR_DIV(left, right, l);
3366 emitcode("div","ab");
3367 aopPut(AOP(result),"a",0);
3369 aopPut(AOP(result),zero,offset++);
3373 /* signed is a little bit more difficult */
3375 /* save the signs of the operands */
3376 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3378 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3379 emitcode("push","acc"); /* save it on the stack */
3381 /* now sign adjust for both left & right */
3382 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3384 lbl = newiTempLabel(NULL);
3385 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3386 emitcode("cpl","a");
3387 emitcode("inc","a");
3388 emitcode("","%05d$:",(lbl->key+100));
3389 emitcode("mov","b,a");
3391 /* sign adjust left side */
3392 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3395 lbl = newiTempLabel(NULL);
3396 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3397 emitcode("cpl","a");
3398 emitcode("inc","a");
3399 emitcode("","%05d$:",(lbl->key+100));
3401 /* now the division */
3402 emitcode("nop", "; workaround for DS80C390 div bug.");
3403 emitcode("div","ab");
3404 /* we are interested in the lower order
3406 emitcode("mov","b,a");
3407 lbl = newiTempLabel(NULL);
3408 emitcode("pop","acc");
3409 /* if there was an over flow we don't
3410 adjust the sign of the result */
3411 emitcode("jb","ov,%05d$",(lbl->key+100));
3412 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3414 emitcode("clr","a");
3415 emitcode("subb","a,b");
3416 emitcode("mov","b,a");
3417 emitcode("","%05d$:",(lbl->key+100));
3419 /* now we are done */
3420 aopPut(AOP(result),"b",0);
3422 emitcode("mov","c,b.7");
3423 emitcode("subb","a,acc");
3426 aopPut(AOP(result),"a",offset++);
3430 /*-----------------------------------------------------------------*/
3431 /* genDiv - generates code for division */
3432 /*-----------------------------------------------------------------*/
3433 static void genDiv (iCode *ic)
3435 operand *left = IC_LEFT(ic);
3436 operand *right = IC_RIGHT(ic);
3437 operand *result= IC_RESULT(ic);
3439 D(emitcode(";", "genDiv "););
3441 /* assign the amsops */
3444 aopOp (left,ic,FALSE, FALSE);
3445 aopOp (right,ic,FALSE, TRUE);
3446 aopOp (result,ic,TRUE, FALSE);
3449 /* special cases first */
3451 if (AOP_TYPE(left) == AOP_CRY &&
3452 AOP_TYPE(right)== AOP_CRY) {
3453 genDivbits(left,right,result);
3457 /* if both are of size == 1 */
3458 if (AOP_SIZE(left) == 1 &&
3459 AOP_SIZE(right) == 1 ) {
3460 genDivOneByte(left,right,result);
3464 /* should have been converted to function call */
3467 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3468 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3469 freeAsmop(result,NULL,ic,TRUE);
3472 /*-----------------------------------------------------------------*/
3473 /* genModbits :- modulus of bits */
3474 /*-----------------------------------------------------------------*/
3475 static void genModbits (operand *left,
3482 /* the result must be bit */
3483 LOAD_AB_FOR_DIV(left, right, l);
3484 emitcode("div","ab");
3485 emitcode("mov","a,b");
3486 emitcode("rrc","a");
3487 aopPut(AOP(result),"c",0);
3490 /*-----------------------------------------------------------------*/
3491 /* genModOneByte : 8 bit modulus */
3492 /*-----------------------------------------------------------------*/
3493 static void genModOneByte (operand *left,
3497 link *opetype = operandType(result);
3501 /* signed or unsigned */
3502 if (SPEC_USIGN(opetype)) {
3503 /* unsigned is easy */
3504 LOAD_AB_FOR_DIV(left, right, l);
3505 emitcode("div","ab");
3506 aopPut(AOP(result),"b",0);
3510 /* signed is a little bit more difficult */
3512 /* save the signs of the operands */
3513 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3516 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3517 emitcode("push","acc"); /* save it on the stack */
3519 /* now sign adjust for both left & right */
3520 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3523 lbl = newiTempLabel(NULL);
3524 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3525 emitcode("cpl","a");
3526 emitcode("inc","a");
3527 emitcode("","%05d$:",(lbl->key+100));
3528 emitcode("mov","b,a");
3530 /* sign adjust left side */
3531 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3534 lbl = newiTempLabel(NULL);
3535 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3536 emitcode("cpl","a");
3537 emitcode("inc","a");
3538 emitcode("","%05d$:",(lbl->key+100));
3540 /* now the multiplication */
3541 emitcode("nop", "; workaround for DS80C390 div bug.");
3542 emitcode("div","ab");
3543 /* we are interested in the lower order
3545 lbl = newiTempLabel(NULL);
3546 emitcode("pop","acc");
3547 /* if there was an over flow we don't
3548 adjust the sign of the result */
3549 emitcode("jb","ov,%05d$",(lbl->key+100));
3550 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3552 emitcode("clr","a");
3553 emitcode("subb","a,b");
3554 emitcode("mov","b,a");
3555 emitcode("","%05d$:",(lbl->key+100));
3557 /* now we are done */
3558 aopPut(AOP(result),"b",0);
3562 /*-----------------------------------------------------------------*/
3563 /* genMod - generates code for division */
3564 /*-----------------------------------------------------------------*/
3565 static void genMod (iCode *ic)
3567 operand *left = IC_LEFT(ic);
3568 operand *right = IC_RIGHT(ic);
3569 operand *result= IC_RESULT(ic);
3571 D(emitcode(";", "genMod "););
3573 /* assign the amsops */
3576 aopOp (left,ic,FALSE, FALSE);
3577 aopOp (right,ic,FALSE, TRUE);
3578 aopOp (result,ic,TRUE, FALSE);
3581 /* special cases first */
3583 if (AOP_TYPE(left) == AOP_CRY &&
3584 AOP_TYPE(right)== AOP_CRY) {
3585 genModbits(left,right,result);
3589 /* if both are of size == 1 */
3590 if (AOP_SIZE(left) == 1 &&
3591 AOP_SIZE(right) == 1 ) {
3592 genModOneByte(left,right,result);
3596 /* should have been converted to function call */
3600 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3601 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3602 freeAsmop(result,NULL,ic,TRUE);
3605 /*-----------------------------------------------------------------*/
3606 /* genIfxJump :- will create a jump depending on the ifx */
3607 /*-----------------------------------------------------------------*/
3608 static void genIfxJump (iCode *ic, char *jval)
3611 symbol *tlbl = newiTempLabel(NULL);
3614 D(emitcode(";", "genIfxJump "););
3616 /* if true label then we jump if condition
3618 if ( IC_TRUE(ic) ) {
3620 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3621 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3624 /* false label is present */
3625 jlbl = IC_FALSE(ic) ;
3626 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3627 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3629 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3630 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3632 emitcode(inst,"%05d$",tlbl->key+100);
3633 emitcode("ljmp","%05d$",jlbl->key+100);
3634 emitcode("","%05d$:",tlbl->key+100);
3636 /* mark the icode as generated */
3640 /*-----------------------------------------------------------------*/
3641 /* genCmp :- greater or less than comparison */
3642 /*-----------------------------------------------------------------*/
3643 static void genCmp (operand *left,operand *right,
3644 operand *result, iCode *ifx, int sign)
3646 int size, offset = 0 ;
3647 unsigned long lit = 0L;
3648 bool swappedOps = FALSE;
3650 D(emitcode(";", "genCmp"););
3653 /* If left if lit and right isn't, swap 'em. */
3654 if (AOP_TYPE(left) == AOP_LIT &&
3655 AOP_TYPE(right) != AOP_LIT)
3657 operand *tmp = left;
3660 D(emitcode(";", "kevin literal hack"););
3661 swappedOps = !swappedOps;
3664 if (AOP_NEEDSACC(right))
3666 if (AOP_NEEDSACC(left))
3668 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3669 "both CMP operands need ACC!");
3674 operand *tmp = left;
3677 D(emitcode(";", "kevin ACC hack"););
3678 swappedOps = !swappedOps;
3683 /* if left & right are bit variables */
3684 if (AOP_TYPE(left) == AOP_CRY &&
3685 AOP_TYPE(right) == AOP_CRY ) {
3686 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3687 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3689 /* subtract right from left if at the
3690 end the carry flag is set then we know that
3691 left is greater than right */
3692 size = max(AOP_SIZE(left),AOP_SIZE(right));
3694 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3695 if((size == 1) && !sign &&
3696 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3697 symbol *lbl = newiTempLabel(NULL);
3698 emitcode("cjne","%s,%s,%05d$",
3699 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3700 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3702 emitcode("","%05d$:",lbl->key+100);
3704 if(AOP_TYPE(right) == AOP_LIT){
3705 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3706 /* optimize if(x < 0) or if(x >= 0) */
3712 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3713 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3714 genIfxJump (ifx,"acc.7");
3718 emitcode("rlc","a");
3726 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3727 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3728 emitcode(";", "genCmp #2");
3729 if (sign && (size == 0))
3731 emitcode(";", "genCmp #3");
3732 emitcode("xrl","a,#0x80");
3733 if (AOP_TYPE(right) == AOP_LIT)
3735 unsigned long lit = (unsigned long)
3736 floatFromVal(AOP(right)->aopu.aop_lit);
3737 emitcode(";", "genCmp #3.1");
3738 emitcode("subb","a,#0x%02x",
3739 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3743 emitcode(";", "genCmp #3.2");
3744 if (AOP_NEEDSACC(right))
3746 emitcode("push", "acc");
3748 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3749 FALSE,FALSE,FALSE));
3750 emitcode("xrl","b,#0x80");
3751 if (AOP_NEEDSACC(right))
3753 emitcode("pop", "acc");
3755 emitcode("subb","a,b");
3762 emitcode(";", "genCmp #4");
3763 if (AOP_NEEDSACC(right))
3766 emitcode(";", "genCmp #4.1");
3767 emitcode("xch", "a, b");
3768 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3769 emitcode("xch", "a, b");
3774 emitcode(";", "genCmp #4.2");
3775 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
3778 emitcode("subb","a,%s",s);
3787 D(emitcode(";","kevHack: flip carry."););
3788 emitcode("cpl", "c");
3791 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3794 /* if the result is used in the next
3795 ifx conditional branch then generate
3796 code a little differently */
3798 genIfxJump (ifx,"c");
3801 /* leave the result in acc */
3805 /*-----------------------------------------------------------------*/
3806 /* genCmpGt :- greater than comparison */
3807 /*-----------------------------------------------------------------*/
3808 static void genCmpGt (iCode *ic, iCode *ifx)
3810 operand *left, *right, *result;
3811 link *letype , *retype;
3814 D(emitcode(";", "genCmpGt "););
3817 right= IC_RIGHT(ic);
3818 result = IC_RESULT(ic);
3820 letype = getSpec(operandType(left));
3821 retype =getSpec(operandType(right));
3822 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3823 /* assign the amsops */
3826 aopOp (left,ic,FALSE, TRUE);
3827 aopOp (right,ic,FALSE, FALSE);
3828 aopOp (result,ic,TRUE, FALSE);
3831 genCmp(right, left, result, ifx, sign);
3833 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3834 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3835 freeAsmop(result,NULL,ic,TRUE);
3838 /*-----------------------------------------------------------------*/
3839 /* genCmpLt - less than comparisons */
3840 /*-----------------------------------------------------------------*/
3841 static void genCmpLt (iCode *ic, iCode *ifx)
3843 operand *left, *right, *result;
3844 link *letype , *retype;
3847 D(emitcode(";", "genCmpLt "););
3850 right= IC_RIGHT(ic);
3851 result = IC_RESULT(ic);
3853 letype = getSpec(operandType(left));
3854 retype =getSpec(operandType(right));
3855 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3857 /* assign the amsops */
3860 aopOp (left,ic,FALSE, FALSE);
3861 aopOp (right,ic,FALSE, TRUE);
3862 aopOp (result,ic,TRUE, FALSE);
3865 genCmp(left, right, result, ifx, sign);
3867 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3868 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3869 freeAsmop(result,NULL,ic,TRUE);
3872 /*-----------------------------------------------------------------*/
3873 /* gencjneshort - compare and jump if not equal */
3874 /*-----------------------------------------------------------------*/
3875 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3877 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3879 unsigned long lit = 0L;
3881 D(emitcode(";", "gencjneshort"););
3883 /* if the left side is a literal or
3884 if the right is in a pointer register and left
3886 if ((AOP_TYPE(left) == AOP_LIT) ||
3887 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3892 if(AOP_TYPE(right) == AOP_LIT)
3893 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3895 /* if the right side is a literal then anything goes */
3896 if (AOP_TYPE(right) == AOP_LIT &&
3897 AOP_TYPE(left) != AOP_DIR ) {
3899 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
3901 emitcode("cjne","a,%s,%05d$",
3902 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3908 /* if the right side is in a register or in direct space or
3909 if the left is a pointer register & right is not */
3910 else if (AOP_TYPE(right) == AOP_REG ||
3911 AOP_TYPE(right) == AOP_DIR ||
3912 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3913 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3915 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3916 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3917 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3918 emitcode("jnz","%05d$",lbl->key+100);
3920 emitcode("cjne","a,%s,%05d$",
3921 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
3926 /* right is a pointer reg need both a & b */
3928 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
3930 emitcode("mov","b,%s",l);
3931 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
3932 emitcode("cjne","a,b,%05d$",lbl->key+100);
3938 /*-----------------------------------------------------------------*/
3939 /* gencjne - compare and jump if not equal */
3940 /*-----------------------------------------------------------------*/
3941 static void gencjne(operand *left, operand *right, symbol *lbl)
3943 symbol *tlbl = newiTempLabel(NULL);
3945 D(emitcode(";", "gencjne"););
3947 gencjneshort(left, right, lbl);
3949 emitcode("mov","a,%s",one);
3950 emitcode("sjmp","%05d$",tlbl->key+100);
3951 emitcode("","%05d$:",lbl->key+100);
3952 emitcode("clr","a");
3953 emitcode("","%05d$:",tlbl->key+100);
3956 /*-----------------------------------------------------------------*/
3957 /* genCmpEq - generates code for equal to */
3958 /*-----------------------------------------------------------------*/
3959 static void genCmpEq (iCode *ic, iCode *ifx)
3961 operand *left, *right, *result;
3963 D(emitcode(";", "genCmpEq "););
3968 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
3969 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3970 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3973 /* if literal, literal on the right or
3974 if the right is in a pointer register and left
3976 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3977 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3978 operand *t = IC_RIGHT(ic);
3979 IC_RIGHT(ic) = IC_LEFT(ic);
3983 if(ifx && !AOP_SIZE(result)){
3985 /* if they are both bit variables */
3986 if (AOP_TYPE(left) == AOP_CRY &&
3987 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3988 if(AOP_TYPE(right) == AOP_LIT){
3989 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3991 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3992 emitcode("cpl","c");
3993 } else if(lit == 1L) {
3994 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3996 emitcode("clr","c");
3998 /* AOP_TYPE(right) == AOP_CRY */
4000 symbol *lbl = newiTempLabel(NULL);
4001 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4002 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4003 emitcode("cpl","c");
4004 emitcode("","%05d$:",(lbl->key+100));
4006 /* if true label then we jump if condition
4008 tlbl = newiTempLabel(NULL);
4009 if ( IC_TRUE(ifx) ) {
4010 emitcode("jnc","%05d$",tlbl->key+100);
4011 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4013 emitcode("jc","%05d$",tlbl->key+100);
4014 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4016 emitcode("","%05d$:",tlbl->key+100);
4018 tlbl = newiTempLabel(NULL);
4019 gencjneshort(left, right, tlbl);
4020 if ( IC_TRUE(ifx) ) {
4021 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4022 emitcode("","%05d$:",tlbl->key+100);
4024 symbol *lbl = newiTempLabel(NULL);
4025 emitcode("sjmp","%05d$",lbl->key+100);
4026 emitcode("","%05d$:",tlbl->key+100);
4027 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4028 emitcode("","%05d$:",lbl->key+100);
4031 /* mark the icode as generated */
4036 /* if they are both bit variables */
4037 if (AOP_TYPE(left) == AOP_CRY &&
4038 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4039 if(AOP_TYPE(right) == AOP_LIT){
4040 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4042 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4043 emitcode("cpl","c");
4044 } else if(lit == 1L) {
4045 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4047 emitcode("clr","c");
4049 /* AOP_TYPE(right) == AOP_CRY */
4051 symbol *lbl = newiTempLabel(NULL);
4052 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4053 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4054 emitcode("cpl","c");
4055 emitcode("","%05d$:",(lbl->key+100));
4058 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4063 genIfxJump (ifx,"c");
4066 /* if the result is used in an arithmetic operation
4067 then put the result in place */
4070 gencjne(left,right,newiTempLabel(NULL));
4071 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4072 aopPut(AOP(result),"a",0);
4076 genIfxJump (ifx,"a");
4079 /* if the result is used in an arithmetic operation
4080 then put the result in place */
4081 if (AOP_TYPE(result) != AOP_CRY)
4083 /* leave the result in acc */
4087 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4088 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4089 freeAsmop(result,NULL,ic,TRUE);
4092 /*-----------------------------------------------------------------*/
4093 /* ifxForOp - returns the icode containing the ifx for operand */
4094 /*-----------------------------------------------------------------*/
4095 static iCode *ifxForOp ( operand *op, iCode *ic )
4097 /* if true symbol then needs to be assigned */
4098 if (IS_TRUE_SYMOP(op))
4101 /* if this has register type condition and
4102 the next instruction is ifx with the same operand
4103 and live to of the operand is upto the ifx only then */
4105 ic->next->op == IFX &&
4106 IC_COND(ic->next)->key == op->key &&
4107 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4112 /*-----------------------------------------------------------------*/
4113 /* genAndOp - for && operation */
4114 /*-----------------------------------------------------------------*/
4115 static void genAndOp (iCode *ic)
4117 operand *left,*right, *result;
4120 D(emitcode(";", "genAndOp "););
4122 /* note here that && operations that are in an
4123 if statement are taken away by backPatchLabels
4124 only those used in arthmetic operations remain */
4128 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4129 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4130 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4133 /* if both are bit variables */
4134 if (AOP_TYPE(left) == AOP_CRY &&
4135 AOP_TYPE(right) == AOP_CRY ) {
4136 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4137 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4140 tlbl = newiTempLabel(NULL);
4142 emitcode("jz","%05d$",tlbl->key+100);
4144 emitcode("","%05d$:",tlbl->key+100);
4148 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4149 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4150 freeAsmop(result,NULL,ic,TRUE);
4154 /*-----------------------------------------------------------------*/
4155 /* genOrOp - for || operation */
4156 /*-----------------------------------------------------------------*/
4157 static void genOrOp (iCode *ic)
4159 operand *left,*right, *result;
4162 D(emitcode(";", "genOrOp "););
4164 /* note here that || operations that are in an
4165 if statement are taken away by backPatchLabels
4166 only those used in arthmetic operations remain */
4170 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4171 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4172 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4175 /* if both are bit variables */
4176 if (AOP_TYPE(left) == AOP_CRY &&
4177 AOP_TYPE(right) == AOP_CRY ) {
4178 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4179 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4182 tlbl = newiTempLabel(NULL);
4184 emitcode("jnz","%05d$",tlbl->key+100);
4186 emitcode("","%05d$:",tlbl->key+100);
4190 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4191 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4192 freeAsmop(result,NULL,ic,TRUE);
4195 /*-----------------------------------------------------------------*/
4196 /* isLiteralBit - test if lit == 2^n */
4197 /*-----------------------------------------------------------------*/
4198 static int isLiteralBit(unsigned long lit)
4200 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4201 0x100L,0x200L,0x400L,0x800L,
4202 0x1000L,0x2000L,0x4000L,0x8000L,
4203 0x10000L,0x20000L,0x40000L,0x80000L,
4204 0x100000L,0x200000L,0x400000L,0x800000L,
4205 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4206 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4209 for(idx = 0; idx < 32; idx++)
4215 /*-----------------------------------------------------------------*/
4216 /* continueIfTrue - */
4217 /*-----------------------------------------------------------------*/
4218 static void continueIfTrue (iCode *ic)
4221 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4225 /*-----------------------------------------------------------------*/
4227 /*-----------------------------------------------------------------*/
4228 static void jumpIfTrue (iCode *ic)
4231 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4235 /*-----------------------------------------------------------------*/
4236 /* jmpTrueOrFalse - */
4237 /*-----------------------------------------------------------------*/
4238 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4240 // ugly but optimized by peephole
4242 symbol *nlbl = newiTempLabel(NULL);
4243 emitcode("sjmp","%05d$",nlbl->key+100);
4244 emitcode("","%05d$:",tlbl->key+100);
4245 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4246 emitcode("","%05d$:",nlbl->key+100);
4249 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4250 emitcode("","%05d$:",tlbl->key+100);
4255 /*-----------------------------------------------------------------*/
4256 /* genAnd - code for and */
4257 /*-----------------------------------------------------------------*/
4258 static void genAnd (iCode *ic, iCode *ifx)
4260 operand *left, *right, *result;
4262 unsigned long lit = 0L;
4266 D(emitcode(";", "genAnd "););
4271 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4272 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4273 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4277 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4279 AOP_TYPE(left), AOP_TYPE(right));
4280 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4282 AOP_SIZE(left), AOP_SIZE(right));
4285 /* if left is a literal & right is not then exchange them */
4286 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4287 AOP_NEEDSACC(left)) {
4288 operand *tmp = right ;
4293 /* if result = right then exchange them */
4294 if(sameRegs(AOP(result),AOP(right))){
4295 operand *tmp = right ;
4300 /* if right is bit then exchange them */
4301 if (AOP_TYPE(right) == AOP_CRY &&
4302 AOP_TYPE(left) != AOP_CRY){
4303 operand *tmp = right ;
4307 if(AOP_TYPE(right) == AOP_LIT)
4308 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4310 size = AOP_SIZE(result);
4313 // result = bit & yy;
4314 if (AOP_TYPE(left) == AOP_CRY){
4315 // c = bit & literal;
4316 if(AOP_TYPE(right) == AOP_LIT){
4318 if(size && sameRegs(AOP(result),AOP(left)))
4321 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4324 if(size && (AOP_TYPE(result) == AOP_CRY)){
4325 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4328 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4332 emitcode("clr","c");
4335 if (AOP_TYPE(right) == AOP_CRY){
4337 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4338 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4341 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4343 emitcode("rrc","a");
4344 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4352 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4353 genIfxJump(ifx, "c");
4357 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4358 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4359 if((AOP_TYPE(right) == AOP_LIT) &&
4360 (AOP_TYPE(result) == AOP_CRY) &&
4361 (AOP_TYPE(left) != AOP_CRY)){
4362 int posbit = isLiteralBit(lit);
4366 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4369 emitcode("mov","c,acc.%d",posbit&0x07);
4373 sprintf(buffer,"acc.%d",posbit&0x07);
4374 genIfxJump(ifx, buffer);
4379 symbol *tlbl = newiTempLabel(NULL);
4380 int sizel = AOP_SIZE(left);
4382 emitcode("setb","c");
4384 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4385 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4387 if((posbit = isLiteralBit(bytelit)) != 0)
4388 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4390 if(bytelit != 0x0FFL)
4391 emitcode("anl","a,%s",
4392 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4393 emitcode("jnz","%05d$",tlbl->key+100);
4398 // bit = left & literal
4400 emitcode("clr","c");
4401 emitcode("","%05d$:",tlbl->key+100);
4403 // if(left & literal)
4406 jmpTrueOrFalse(ifx, tlbl);
4414 /* if left is same as result */
4415 if(sameRegs(AOP(result),AOP(left))){
4416 for(;size--; offset++) {
4417 if(AOP_TYPE(right) == AOP_LIT){
4418 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4422 aopPut(AOP(result),zero,offset);
4424 if (IS_AOP_PREG(result)) {
4425 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4426 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4427 aopPut(AOP(result),"a",offset);
4429 emitcode("anl","%s,%s",
4430 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4431 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4433 if (AOP_TYPE(left) == AOP_ACC)
4434 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4436 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4437 if (IS_AOP_PREG(result)) {
4438 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4439 aopPut(AOP(result),"a",offset);
4442 emitcode("anl","%s,a",
4443 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4448 // left & result in different registers
4449 if(AOP_TYPE(result) == AOP_CRY){
4451 // if(size), result in bit
4452 // if(!size && ifx), conditional oper: if(left & right)
4453 symbol *tlbl = newiTempLabel(NULL);
4454 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4456 emitcode("setb","c");
4458 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4459 emitcode("anl","a,%s",
4460 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4461 emitcode("jnz","%05d$",tlbl->key+100);
4466 emitcode("","%05d$:",tlbl->key+100);
4469 jmpTrueOrFalse(ifx, tlbl);
4471 for(;(size--);offset++) {
4473 // result = left & right
4474 if(AOP_TYPE(right) == AOP_LIT){
4475 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4477 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4480 } else if(bytelit == 0){
4481 aopPut(AOP(result),zero,offset);
4485 // faster than result <- left, anl result,right
4486 // and better if result is SFR
4487 if (AOP_TYPE(left) == AOP_ACC)
4488 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4490 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4491 emitcode("anl","a,%s",
4492 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4494 aopPut(AOP(result),"a",offset);
4500 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4501 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4502 freeAsmop(result,NULL,ic,TRUE);
4505 /*-----------------------------------------------------------------*/
4506 /* genOr - code for or */
4507 /*-----------------------------------------------------------------*/
4508 static void genOr (iCode *ic, iCode *ifx)
4510 operand *left, *right, *result;
4512 unsigned long lit = 0L;
4514 D(emitcode(";", "genOr "););
4519 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4520 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4521 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4525 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4527 AOP_TYPE(left), AOP_TYPE(right));
4528 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4530 AOP_SIZE(left), AOP_SIZE(right));
4533 /* if left is a literal & right is not then exchange them */
4534 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4535 AOP_NEEDSACC(left)) {
4536 operand *tmp = right ;
4541 /* if result = right then exchange them */
4542 if(sameRegs(AOP(result),AOP(right))){
4543 operand *tmp = right ;
4548 /* if right is bit then exchange them */
4549 if (AOP_TYPE(right) == AOP_CRY &&
4550 AOP_TYPE(left) != AOP_CRY){
4551 operand *tmp = right ;
4555 if(AOP_TYPE(right) == AOP_LIT)
4556 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4558 size = AOP_SIZE(result);
4562 if (AOP_TYPE(left) == AOP_CRY){
4563 if(AOP_TYPE(right) == AOP_LIT){
4564 // c = bit & literal;
4566 // lit != 0 => result = 1
4567 if(AOP_TYPE(result) == AOP_CRY){
4569 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4571 continueIfTrue(ifx);
4574 emitcode("setb","c");
4576 // lit == 0 => result = left
4577 if(size && sameRegs(AOP(result),AOP(left)))
4579 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4582 if (AOP_TYPE(right) == AOP_CRY){
4584 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4585 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4589 symbol *tlbl = newiTempLabel(NULL);
4590 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4591 emitcode("setb","c");
4592 emitcode("jb","%s,%05d$",
4593 AOP(left)->aopu.aop_dir,tlbl->key+100);
4595 emitcode("jnz","%05d$",tlbl->key+100);
4596 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4597 jmpTrueOrFalse(ifx, tlbl);
4601 emitcode("","%05d$:",tlbl->key+100);
4610 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4611 genIfxJump(ifx, "c");
4615 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4616 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4617 if((AOP_TYPE(right) == AOP_LIT) &&
4618 (AOP_TYPE(result) == AOP_CRY) &&
4619 (AOP_TYPE(left) != AOP_CRY)){
4623 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4625 continueIfTrue(ifx);
4628 // lit = 0, result = boolean(left)
4630 emitcode("setb","c");
4633 symbol *tlbl = newiTempLabel(NULL);
4634 emitcode("jnz","%05d$",tlbl->key+100);
4636 emitcode("","%05d$:",tlbl->key+100);
4638 genIfxJump (ifx,"a");
4646 /* if left is same as result */
4647 if(sameRegs(AOP(result),AOP(left))){
4648 for(;size--; offset++) {
4649 if(AOP_TYPE(right) == AOP_LIT){
4650 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4653 if (IS_AOP_PREG(left)) {
4654 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4655 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4656 aopPut(AOP(result),"a",offset);
4658 emitcode("orl","%s,%s",
4659 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4660 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4662 if (AOP_TYPE(left) == AOP_ACC)
4663 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4665 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4666 if (IS_AOP_PREG(left)) {
4667 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4668 aopPut(AOP(result),"a",offset);
4670 emitcode("orl","%s,a",
4671 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4676 // left & result in different registers
4677 if(AOP_TYPE(result) == AOP_CRY){
4679 // if(size), result in bit
4680 // if(!size && ifx), conditional oper: if(left | right)
4681 symbol *tlbl = newiTempLabel(NULL);
4682 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4684 emitcode("setb","c");
4686 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4687 emitcode("orl","a,%s",
4688 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4689 emitcode("jnz","%05d$",tlbl->key+100);
4694 emitcode("","%05d$:",tlbl->key+100);
4697 jmpTrueOrFalse(ifx, tlbl);
4698 } else for(;(size--);offset++){
4700 // result = left & right
4701 if(AOP_TYPE(right) == AOP_LIT){
4702 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4704 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4709 // faster than result <- left, anl result,right
4710 // and better if result is SFR
4711 if (AOP_TYPE(left) == AOP_ACC)
4712 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4714 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4715 emitcode("orl","a,%s",
4716 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4718 aopPut(AOP(result),"a",offset);
4723 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4724 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4725 freeAsmop(result,NULL,ic,TRUE);
4728 /*-----------------------------------------------------------------*/
4729 /* genXor - code for xclusive or */
4730 /*-----------------------------------------------------------------*/
4731 static void genXor (iCode *ic, iCode *ifx)
4733 operand *left, *right, *result;
4735 unsigned long lit = 0L;
4737 D(emitcode(";", "genXor "););
4742 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4743 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4744 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4748 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4750 AOP_TYPE(left), AOP_TYPE(right));
4751 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4753 AOP_SIZE(left), AOP_SIZE(right));
4756 /* if left is a literal & right is not ||
4757 if left needs acc & right does not */
4758 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4759 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4760 operand *tmp = right ;
4765 /* if result = right then exchange them */
4766 if(sameRegs(AOP(result),AOP(right))){
4767 operand *tmp = right ;
4772 /* if right is bit then exchange them */
4773 if (AOP_TYPE(right) == AOP_CRY &&
4774 AOP_TYPE(left) != AOP_CRY){
4775 operand *tmp = right ;
4779 if(AOP_TYPE(right) == AOP_LIT)
4780 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4782 size = AOP_SIZE(result);
4786 if (AOP_TYPE(left) == AOP_CRY){
4787 if(AOP_TYPE(right) == AOP_LIT){
4788 // c = bit & literal;
4790 // lit>>1 != 0 => result = 1
4791 if(AOP_TYPE(result) == AOP_CRY){
4793 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4795 continueIfTrue(ifx);
4798 emitcode("setb","c");
4802 // lit == 0, result = left
4803 if(size && sameRegs(AOP(result),AOP(left)))
4805 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4807 // lit == 1, result = not(left)
4808 if(size && sameRegs(AOP(result),AOP(left))){
4809 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4812 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4813 emitcode("cpl","c");
4820 symbol *tlbl = newiTempLabel(NULL);
4821 if (AOP_TYPE(right) == AOP_CRY){
4823 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4826 int sizer = AOP_SIZE(right);
4828 // if val>>1 != 0, result = 1
4829 emitcode("setb","c");
4831 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
4833 // test the msb of the lsb
4834 emitcode("anl","a,#0xfe");
4835 emitcode("jnz","%05d$",tlbl->key+100);
4839 emitcode("rrc","a");
4841 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4842 emitcode("cpl","c");
4843 emitcode("","%05d$:",(tlbl->key+100));
4850 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4851 genIfxJump(ifx, "c");
4855 if(sameRegs(AOP(result),AOP(left))){
4856 /* if left is same as result */
4857 for(;size--; offset++) {
4858 if(AOP_TYPE(right) == AOP_LIT){
4859 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4862 if (IS_AOP_PREG(left)) {
4863 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4864 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4865 aopPut(AOP(result),"a",offset);
4867 emitcode("xrl","%s,%s",
4868 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4869 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4871 if (AOP_TYPE(left) == AOP_ACC)
4872 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4874 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4875 if (IS_AOP_PREG(left)) {
4876 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4877 aopPut(AOP(result),"a",offset);
4879 emitcode("xrl","%s,a",
4880 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4885 // left & result in different registers
4886 if(AOP_TYPE(result) == AOP_CRY){
4888 // if(size), result in bit
4889 // if(!size && ifx), conditional oper: if(left ^ right)
4890 symbol *tlbl = newiTempLabel(NULL);
4891 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4893 emitcode("setb","c");
4895 if((AOP_TYPE(right) == AOP_LIT) &&
4896 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4897 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4899 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4900 emitcode("xrl","a,%s",
4901 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4903 emitcode("jnz","%05d$",tlbl->key+100);
4908 emitcode("","%05d$:",tlbl->key+100);
4911 jmpTrueOrFalse(ifx, tlbl);
4912 } else for(;(size--);offset++){
4914 // result = left & right
4915 if(AOP_TYPE(right) == AOP_LIT){
4916 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4918 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4923 // faster than result <- left, anl result,right
4924 // and better if result is SFR
4925 if (AOP_TYPE(left) == AOP_ACC)
4926 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4928 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4929 emitcode("xrl","a,%s",
4930 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4932 aopPut(AOP(result),"a",offset);
4937 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4938 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4939 freeAsmop(result,NULL,ic,TRUE);
4942 /*-----------------------------------------------------------------*/
4943 /* genInline - write the inline code out */
4944 /*-----------------------------------------------------------------*/
4945 static void genInline (iCode *ic)
4947 char buffer[MAX_INLINEASM];
4951 D(emitcode(";", "genInline "););
4953 _G.inLine += (!options.asmpeep);
4954 strcpy(buffer,IC_INLINE(ic));
4956 /* emit each line as a code */
4975 /* emitcode("",buffer); */
4976 _G.inLine -= (!options.asmpeep);
4979 /*-----------------------------------------------------------------*/
4980 /* genRRC - rotate right with carry */
4981 /*-----------------------------------------------------------------*/
4982 static void genRRC (iCode *ic)
4984 operand *left , *result ;
4985 int size, offset = 0;
4988 D(emitcode(";", "genRRC "););
4990 /* rotate right with carry */
4992 result=IC_RESULT(ic);
4993 aopOp (left,ic,FALSE, FALSE);
4994 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
4996 /* move it to the result */
4997 size = AOP_SIZE(result);
5001 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5003 emitcode("rrc","a");
5004 if (AOP_SIZE(result) > 1)
5005 aopPut(AOP(result),"a",offset--);
5007 /* now we need to put the carry into the
5008 highest order byte of the result */
5009 if (AOP_SIZE(result) > 1) {
5010 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5013 emitcode("mov","acc.7,c");
5014 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5015 freeAsmop(left,NULL,ic,TRUE);
5016 freeAsmop(result,NULL,ic,TRUE);
5019 /*-----------------------------------------------------------------*/
5020 /* genRLC - generate code for rotate left with carry */
5021 /*-----------------------------------------------------------------*/
5022 static void genRLC (iCode *ic)
5024 operand *left , *result ;
5025 int size, offset = 0;
5028 D(emitcode(";", "genRLC "););
5030 /* rotate right with carry */
5032 result=IC_RESULT(ic);
5033 aopOp (left,ic,FALSE, FALSE);
5034 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5036 /* move it to the result */
5037 size = AOP_SIZE(result);
5040 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5042 emitcode("add","a,acc");
5043 if (AOP_SIZE(result) > 1)
5044 aopPut(AOP(result),"a",offset++);
5046 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5048 emitcode("rlc","a");
5049 if (AOP_SIZE(result) > 1)
5050 aopPut(AOP(result),"a",offset++);
5053 /* now we need to put the carry into the
5054 highest order byte of the result */
5055 if (AOP_SIZE(result) > 1) {
5056 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5059 emitcode("mov","acc.0,c");
5060 aopPut(AOP(result),"a",0);
5061 freeAsmop(left,NULL,ic,TRUE);
5062 freeAsmop(result,NULL,ic,TRUE);
5065 /*-----------------------------------------------------------------*/
5066 /* genGetHbit - generates code get highest order bit */
5067 /*-----------------------------------------------------------------*/
5068 static void genGetHbit (iCode *ic)
5070 operand *left, *result;
5072 result=IC_RESULT(ic);
5073 aopOp (left,ic,FALSE, FALSE);
5074 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5076 D(emitcode(";", "genGetHbit "););
5078 /* get the highest order byte into a */
5079 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5080 if(AOP_TYPE(result) == AOP_CRY){
5081 emitcode("rlc","a");
5086 emitcode("anl","a,#0x01");
5091 freeAsmop(left,NULL,ic,TRUE);
5092 freeAsmop(result,NULL,ic,TRUE);
5095 /*-----------------------------------------------------------------*/
5096 /* AccRol - rotate left accumulator by known count */
5097 /*-----------------------------------------------------------------*/
5098 static void AccRol (int shCount)
5100 shCount &= 0x0007; // shCount : 0..7
5112 emitcode("swap","a");
5116 emitcode("swap","a");
5119 emitcode("swap","a");
5132 /*-----------------------------------------------------------------*/
5133 /* AccLsh - left shift accumulator by known count */
5134 /*-----------------------------------------------------------------*/
5135 static void AccLsh (int shCount)
5139 emitcode("add","a,acc");
5142 emitcode("add","a,acc");
5143 emitcode("add","a,acc");
5145 /* rotate left accumulator */
5147 /* and kill the lower order bits */
5148 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5153 /*-----------------------------------------------------------------*/
5154 /* AccRsh - right shift accumulator by known count */
5155 /*-----------------------------------------------------------------*/
5156 static void AccRsh (int shCount)
5161 emitcode("rrc","a");
5163 /* rotate right accumulator */
5164 AccRol(8 - shCount);
5165 /* and kill the higher order bits */
5166 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5171 /*-----------------------------------------------------------------*/
5172 /* AccSRsh - signed right shift accumulator by known count */
5173 /*-----------------------------------------------------------------*/
5174 static void AccSRsh (int shCount)
5179 emitcode("mov","c,acc.7");
5180 emitcode("rrc","a");
5181 } else if(shCount == 2){
5182 emitcode("mov","c,acc.7");
5183 emitcode("rrc","a");
5184 emitcode("mov","c,acc.7");
5185 emitcode("rrc","a");
5187 tlbl = newiTempLabel(NULL);
5188 /* rotate right accumulator */
5189 AccRol(8 - shCount);
5190 /* and kill the higher order bits */
5191 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5192 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5193 emitcode("orl","a,#0x%02x",
5194 (unsigned char)~SRMask[shCount]);
5195 emitcode("","%05d$:",tlbl->key+100);
5200 /*-----------------------------------------------------------------*/
5201 /* shiftR1Left2Result - shift right one byte from left to result */
5202 /*-----------------------------------------------------------------*/
5203 static void shiftR1Left2Result (operand *left, int offl,
5204 operand *result, int offr,
5205 int shCount, int sign)
5207 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5208 /* shift right accumulator */
5213 aopPut(AOP(result),"a",offr);
5216 /*-----------------------------------------------------------------*/
5217 /* shiftL1Left2Result - shift left one byte from left to result */
5218 /*-----------------------------------------------------------------*/
5219 static void shiftL1Left2Result (operand *left, int offl,
5220 operand *result, int offr, int shCount)
5223 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5225 /* shift left accumulator */
5227 aopPut(AOP(result),"a",offr);
5230 /*-----------------------------------------------------------------*/
5231 /* movLeft2Result - move byte from left to result */
5232 /*-----------------------------------------------------------------*/
5233 static void movLeft2Result (operand *left, int offl,
5234 operand *result, int offr, int sign)
5237 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5238 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5240 if (*l == '@' && (IS_AOP_PREG(result))) {
5241 emitcode("mov","a,%s",l);
5242 aopPut(AOP(result),"a",offr);
5245 aopPut(AOP(result),l,offr);
5247 /* MSB sign in acc.7 ! */
5248 if(getDataSize(left) == offl+1){
5249 emitcode("mov","a,%s",l);
5250 aopPut(AOP(result),"a",offr);
5257 /*-----------------------------------------------------------------*/
5258 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5259 /*-----------------------------------------------------------------*/
5260 static void AccAXRrl1 (char *x)
5262 emitcode("rrc","a");
5263 emitcode("xch","a,%s", x);
5264 emitcode("rrc","a");
5265 emitcode("xch","a,%s", x);
5268 /*-----------------------------------------------------------------*/
5269 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5270 /*-----------------------------------------------------------------*/
5271 static void AccAXLrl1 (char *x)
5273 emitcode("xch","a,%s",x);
5274 emitcode("rlc","a");
5275 emitcode("xch","a,%s",x);
5276 emitcode("rlc","a");
5279 /*-----------------------------------------------------------------*/
5280 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5281 /*-----------------------------------------------------------------*/
5282 static void AccAXLsh1 (char *x)
5284 emitcode("xch","a,%s",x);
5285 emitcode("add","a,acc");
5286 emitcode("xch","a,%s",x);
5287 emitcode("rlc","a");
5290 /*-----------------------------------------------------------------*/
5291 /* AccAXLsh - left shift a:x by known count (0..7) */
5292 /*-----------------------------------------------------------------*/
5293 static void AccAXLsh (char *x, int shCount)
5307 case 5 : // AAAAABBB:CCCCCDDD
5308 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5309 emitcode("anl","a,#0x%02x",
5310 SLMask[shCount]); // BBB00000:CCCCCDDD
5311 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5312 AccRol(shCount); // DDDCCCCC:BBB00000
5313 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5314 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5315 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5316 emitcode("anl","a,#0x%02x",
5317 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5318 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5319 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5321 case 6 : // AAAAAABB:CCCCCCDD
5322 emitcode("anl","a,#0x%02x",
5323 SRMask[shCount]); // 000000BB:CCCCCCDD
5324 emitcode("mov","c,acc.0"); // c = B
5325 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5326 AccAXRrl1(x); // BCCCCCCD:D000000B
5327 AccAXRrl1(x); // BBCCCCCC:DD000000
5329 case 7 : // a:x <<= 7
5330 emitcode("anl","a,#0x%02x",
5331 SRMask[shCount]); // 0000000B:CCCCCCCD
5332 emitcode("mov","c,acc.0"); // c = B
5333 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5334 AccAXRrl1(x); // BCCCCCCC:D0000000
5341 /*-----------------------------------------------------------------*/
5342 /* AccAXRsh - right shift a:x known count (0..7) */
5343 /*-----------------------------------------------------------------*/
5344 static void AccAXRsh (char *x, int shCount)
5351 AccAXRrl1(x); // 0->a:x
5355 AccAXRrl1(x); // 0->a:x
5357 AccAXRrl1(x); // 0->a:x
5361 case 5 : // AAAAABBB:CCCCCDDD = a:x
5362 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5363 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5364 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5365 emitcode("anl","a,#0x%02x",
5366 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5367 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5368 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5369 emitcode("anl","a,#0x%02x",
5370 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5371 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5372 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5373 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5375 case 6 : // AABBBBBB:CCDDDDDD
5376 emitcode("mov","c,acc.7");
5377 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5378 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5379 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5380 emitcode("anl","a,#0x%02x",
5381 SRMask[shCount]); // 000000AA:BBBBBBCC
5383 case 7 : // ABBBBBBB:CDDDDDDD
5384 emitcode("mov","c,acc.7"); // c = A
5385 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5386 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5387 emitcode("anl","a,#0x%02x",
5388 SRMask[shCount]); // 0000000A:BBBBBBBC
5395 /*-----------------------------------------------------------------*/
5396 /* AccAXRshS - right shift signed a:x known count (0..7) */
5397 /*-----------------------------------------------------------------*/
5398 static void AccAXRshS (char *x, int shCount)
5405 emitcode("mov","c,acc.7");
5406 AccAXRrl1(x); // s->a:x
5409 emitcode("mov","c,acc.7");
5410 AccAXRrl1(x); // s->a:x
5411 emitcode("mov","c,acc.7");
5412 AccAXRrl1(x); // s->a:x
5416 case 5 : // AAAAABBB:CCCCCDDD = a:x
5417 tlbl = newiTempLabel(NULL);
5418 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5419 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5420 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5421 emitcode("anl","a,#0x%02x",
5422 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5423 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5424 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5425 emitcode("anl","a,#0x%02x",
5426 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5427 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5428 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5429 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5430 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5431 emitcode("orl","a,#0x%02x",
5432 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5433 emitcode("","%05d$:",tlbl->key+100);
5434 break; // SSSSAAAA:BBBCCCCC
5435 case 6 : // AABBBBBB:CCDDDDDD
5436 tlbl = newiTempLabel(NULL);
5437 emitcode("mov","c,acc.7");
5438 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5439 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5440 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5441 emitcode("anl","a,#0x%02x",
5442 SRMask[shCount]); // 000000AA:BBBBBBCC
5443 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5444 emitcode("orl","a,#0x%02x",
5445 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5446 emitcode("","%05d$:",tlbl->key+100);
5448 case 7 : // ABBBBBBB:CDDDDDDD
5449 tlbl = newiTempLabel(NULL);
5450 emitcode("mov","c,acc.7"); // c = A
5451 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5452 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5453 emitcode("anl","a,#0x%02x",
5454 SRMask[shCount]); // 0000000A:BBBBBBBC
5455 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5456 emitcode("orl","a,#0x%02x",
5457 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5458 emitcode("","%05d$:",tlbl->key+100);
5465 /*-----------------------------------------------------------------*/
5466 /* shiftL2Left2Result - shift left two bytes from left to result */
5467 /*-----------------------------------------------------------------*/
5468 static void shiftL2Left2Result (operand *left, int offl,
5469 operand *result, int offr, int shCount)
5471 if(sameRegs(AOP(result), AOP(left)) &&
5472 ((offl + MSB16) == offr)){
5473 /* don't crash result[offr] */
5474 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5475 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5477 movLeft2Result(left,offl, result, offr, 0);
5478 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5480 /* ax << shCount (x = lsb(result))*/
5481 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5482 aopPut(AOP(result),"a",offr+MSB16);
5486 /*-----------------------------------------------------------------*/
5487 /* shiftR2Left2Result - shift right two bytes from left to result */
5488 /*-----------------------------------------------------------------*/
5489 static void shiftR2Left2Result (operand *left, int offl,
5490 operand *result, int offr,
5491 int shCount, int sign)
5493 if(sameRegs(AOP(result), AOP(left)) &&
5494 ((offl + MSB16) == offr)){
5495 /* don't crash result[offr] */
5496 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5497 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5499 movLeft2Result(left,offl, result, offr, 0);
5500 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5502 /* a:x >> shCount (x = lsb(result))*/
5504 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5506 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5507 if(getDataSize(result) > 1)
5508 aopPut(AOP(result),"a",offr+MSB16);
5511 /*-----------------------------------------------------------------*/
5512 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5513 /*-----------------------------------------------------------------*/
5514 static void shiftLLeftOrResult (operand *left, int offl,
5515 operand *result, int offr, int shCount)
5517 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5518 /* shift left accumulator */
5520 /* or with result */
5521 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5522 /* back to result */
5523 aopPut(AOP(result),"a",offr);
5526 /*-----------------------------------------------------------------*/
5527 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5528 /*-----------------------------------------------------------------*/
5529 static void shiftRLeftOrResult (operand *left, int offl,
5530 operand *result, int offr, int shCount)
5532 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5533 /* shift right accumulator */
5535 /* or with result */
5536 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5537 /* back to result */
5538 aopPut(AOP(result),"a",offr);
5541 /*-----------------------------------------------------------------*/
5542 /* genlshOne - left shift a one byte quantity by known count */
5543 /*-----------------------------------------------------------------*/
5544 static void genlshOne (operand *result, operand *left, int shCount)
5546 D(emitcode(";", "genlshOne "););
5547 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5550 /*-----------------------------------------------------------------*/
5551 /* genlshTwo - left shift two bytes by known amount != 0 */
5552 /*-----------------------------------------------------------------*/
5553 static void genlshTwo (operand *result,operand *left, int shCount)
5557 D(emitcode(";", "genlshTwo "););
5559 size = getDataSize(result);
5561 /* if shCount >= 8 */
5567 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5569 movLeft2Result(left, LSB, result, MSB16, 0);
5571 aopPut(AOP(result),zero,LSB);
5574 /* 1 <= shCount <= 7 */
5577 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5579 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5583 /*-----------------------------------------------------------------*/
5584 /* shiftLLong - shift left one long from left to result */
5585 /* offl = LSB or MSB16 */
5586 /*-----------------------------------------------------------------*/
5587 static void shiftLLong (operand *left, operand *result, int offr )
5590 int size = AOP_SIZE(result);
5592 if(size >= LSB+offr){
5593 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5595 emitcode("add","a,acc");
5596 if (sameRegs(AOP(left),AOP(result)) &&
5597 size >= MSB16+offr && offr != LSB )
5598 emitcode("xch","a,%s",
5599 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5601 aopPut(AOP(result),"a",LSB+offr);
5604 if(size >= MSB16+offr){
5605 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5606 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5609 emitcode("rlc","a");
5610 if (sameRegs(AOP(left),AOP(result)) &&
5611 size >= MSB24+offr && offr != LSB)
5612 emitcode("xch","a,%s",
5613 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5615 aopPut(AOP(result),"a",MSB16+offr);
5618 if(size >= MSB24+offr){
5619 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5620 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5623 emitcode("rlc","a");
5624 if (sameRegs(AOP(left),AOP(result)) &&
5625 size >= MSB32+offr && offr != LSB )
5626 emitcode("xch","a,%s",
5627 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5629 aopPut(AOP(result),"a",MSB24+offr);
5632 if(size > MSB32+offr){
5633 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5634 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5637 emitcode("rlc","a");
5638 aopPut(AOP(result),"a",MSB32+offr);
5641 aopPut(AOP(result),zero,LSB);
5644 /*-----------------------------------------------------------------*/
5645 /* genlshFour - shift four byte by a known amount != 0 */
5646 /*-----------------------------------------------------------------*/
5647 static void genlshFour (operand *result, operand *left, int shCount)
5651 D(emitcode(";", "genlshFour "););
5653 size = AOP_SIZE(result);
5655 /* if shifting more that 3 bytes */
5656 if (shCount >= 24 ) {
5659 /* lowest order of left goes to the highest
5660 order of the destination */
5661 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5663 movLeft2Result(left, LSB, result, MSB32, 0);
5664 aopPut(AOP(result),zero,LSB);
5665 aopPut(AOP(result),zero,MSB16);
5666 aopPut(AOP(result),zero,MSB32);
5670 /* more than two bytes */
5671 else if ( shCount >= 16 ) {
5672 /* lower order two bytes goes to higher order two bytes */
5674 /* if some more remaining */
5676 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5678 movLeft2Result(left, MSB16, result, MSB32, 0);
5679 movLeft2Result(left, LSB, result, MSB24, 0);
5681 aopPut(AOP(result),zero,MSB16);
5682 aopPut(AOP(result),zero,LSB);
5686 /* if more than 1 byte */
5687 else if ( shCount >= 8 ) {
5688 /* lower order three bytes goes to higher order three bytes */
5692 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5694 movLeft2Result(left, LSB, result, MSB16, 0);
5696 else{ /* size = 4 */
5698 movLeft2Result(left, MSB24, result, MSB32, 0);
5699 movLeft2Result(left, MSB16, result, MSB24, 0);
5700 movLeft2Result(left, LSB, result, MSB16, 0);
5701 aopPut(AOP(result),zero,LSB);
5703 else if(shCount == 1)
5704 shiftLLong(left, result, MSB16);
5706 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5707 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5708 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5709 aopPut(AOP(result),zero,LSB);
5714 /* 1 <= shCount <= 7 */
5715 else if(shCount <= 2){
5716 shiftLLong(left, result, LSB);
5718 shiftLLong(result, result, LSB);
5720 /* 3 <= shCount <= 7, optimize */
5722 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5723 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5724 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5728 /*-----------------------------------------------------------------*/
5729 /* genLeftShiftLiteral - left shifting by known count */
5730 /*-----------------------------------------------------------------*/
5731 static void genLeftShiftLiteral (operand *left,
5736 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5739 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5741 freeAsmop(right,NULL,ic,TRUE);
5743 aopOp(left,ic,FALSE, FALSE);
5744 aopOp(result,ic,FALSE, TRUE);
5746 size = getSize(operandType(result));
5749 emitcode("; shift left ","result %d, left %d",size,
5753 /* I suppose that the left size >= result size */
5756 movLeft2Result(left, size, result, size, 0);
5760 else if(shCount >= (size * 8))
5762 aopPut(AOP(result),zero,size);
5766 genlshOne (result,left,shCount);
5770 case 3: /* bug: this is for generic pointers, I bet. */
5771 genlshTwo (result,left,shCount);
5775 genlshFour (result,left,shCount);
5779 freeAsmop(left,NULL,ic,TRUE);
5780 freeAsmop(result,NULL,ic,TRUE);
5783 /*-----------------------------------------------------------------*/
5784 /* genLeftShift - generates code for left shifting */
5785 /*-----------------------------------------------------------------*/
5786 static void genLeftShift (iCode *ic)
5788 operand *left,*right, *result;
5791 symbol *tlbl , *tlbl1;
5793 D(emitcode(";", "genLeftShift "););
5795 right = IC_RIGHT(ic);
5797 result = IC_RESULT(ic);
5799 aopOp(right,ic,FALSE, FALSE);
5802 /* if the shift count is known then do it
5803 as efficiently as possible */
5804 if (AOP_TYPE(right) == AOP_LIT) {
5805 genLeftShiftLiteral (left,right,result,ic);
5810 /* shift count is unknown then we have to form
5811 a loop get the loop count in B : Note: we take
5812 only the lower order byte since shifting
5813 more that 32 bits make no sense anyway, ( the
5814 largest size of an object can be only 32 bits ) */
5816 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
5817 emitcode("inc","b");
5818 freeAsmop (right,NULL,ic,TRUE);
5819 aopOp(left,ic,FALSE, FALSE);
5820 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5822 /* now move the left to the result if they are not the
5824 if (!sameRegs(AOP(left),AOP(result)) &&
5825 AOP_SIZE(result) > 1) {
5827 size = AOP_SIZE(result);
5830 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
5831 if (*l == '@' && (IS_AOP_PREG(result))) {
5833 emitcode("mov","a,%s",l);
5834 aopPut(AOP(result),"a",offset);
5836 aopPut(AOP(result),l,offset);
5841 tlbl = newiTempLabel(NULL);
5842 size = AOP_SIZE(result);
5844 tlbl1 = newiTempLabel(NULL);
5846 /* if it is only one byte then */
5848 symbol *tlbl1 = newiTempLabel(NULL);
5850 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
5852 emitcode("sjmp","%05d$",tlbl1->key+100);
5853 emitcode("","%05d$:",tlbl->key+100);
5854 emitcode("add","a,acc");
5855 emitcode("","%05d$:",tlbl1->key+100);
5856 emitcode("djnz","b,%05d$",tlbl->key+100);
5857 aopPut(AOP(result),"a",0);
5861 reAdjustPreg(AOP(result));
5863 emitcode("sjmp","%05d$",tlbl1->key+100);
5864 emitcode("","%05d$:",tlbl->key+100);
5865 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
5867 emitcode("add","a,acc");
5868 aopPut(AOP(result),"a",offset++);
5870 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
5872 emitcode("rlc","a");
5873 aopPut(AOP(result),"a",offset++);
5875 reAdjustPreg(AOP(result));
5877 emitcode("","%05d$:",tlbl1->key+100);
5878 emitcode("djnz","b,%05d$",tlbl->key+100);
5880 freeAsmop(left,NULL,ic,TRUE);
5881 freeAsmop(result,NULL,ic,TRUE);
5884 /*-----------------------------------------------------------------*/
5885 /* genrshOne - right shift a one byte quantity by known count */
5886 /*-----------------------------------------------------------------*/
5887 static void genrshOne (operand *result, operand *left,
5888 int shCount, int sign)
5890 D(emitcode(";", "genrshOne"););
5891 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5894 /*-----------------------------------------------------------------*/
5895 /* genrshTwo - right shift two bytes by known amount != 0 */
5896 /*-----------------------------------------------------------------*/
5897 static void genrshTwo (operand *result,operand *left,
5898 int shCount, int sign)
5900 D(emitcode(";", "genrshTwo"););
5902 /* if shCount >= 8 */
5906 shiftR1Left2Result(left, MSB16, result, LSB,
5909 movLeft2Result(left, MSB16, result, LSB, sign);
5910 addSign(result, MSB16, sign);
5913 /* 1 <= shCount <= 7 */
5915 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5918 /*-----------------------------------------------------------------*/
5919 /* shiftRLong - shift right one long from left to result */
5920 /* offl = LSB or MSB16 */
5921 /*-----------------------------------------------------------------*/
5922 static void shiftRLong (operand *left, int offl,
5923 operand *result, int sign)
5926 emitcode("clr","c");
5927 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
5929 emitcode("mov","c,acc.7");
5930 emitcode("rrc","a");
5931 aopPut(AOP(result),"a",MSB32-offl);
5933 /* add sign of "a" */
5934 addSign(result, MSB32, sign);
5936 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
5937 emitcode("rrc","a");
5938 aopPut(AOP(result),"a",MSB24-offl);
5940 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
5941 emitcode("rrc","a");
5942 aopPut(AOP(result),"a",MSB16-offl);
5945 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
5946 emitcode("rrc","a");
5947 aopPut(AOP(result),"a",LSB);
5951 /*-----------------------------------------------------------------*/
5952 /* genrshFour - shift four byte by a known amount != 0 */
5953 /*-----------------------------------------------------------------*/
5954 static void genrshFour (operand *result, operand *left,
5955 int shCount, int sign)
5957 D(emitcode(";", "genrshFour"););
5959 /* if shifting more that 3 bytes */
5960 if(shCount >= 24 ) {
5963 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5965 movLeft2Result(left, MSB32, result, LSB, sign);
5966 addSign(result, MSB16, sign);
5968 else if(shCount >= 16){
5971 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5973 movLeft2Result(left, MSB24, result, LSB, 0);
5974 movLeft2Result(left, MSB32, result, MSB16, sign);
5976 addSign(result, MSB24, sign);
5978 else if(shCount >= 8){
5981 shiftRLong(left, MSB16, result, sign);
5982 else if(shCount == 0){
5983 movLeft2Result(left, MSB16, result, LSB, 0);
5984 movLeft2Result(left, MSB24, result, MSB16, 0);
5985 movLeft2Result(left, MSB32, result, MSB24, sign);
5986 addSign(result, MSB32, sign);
5989 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5990 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5991 /* the last shift is signed */
5992 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5993 addSign(result, MSB32, sign);
5996 else{ /* 1 <= shCount <= 7 */
5998 shiftRLong(left, LSB, result, sign);
6000 shiftRLong(result, LSB, result, sign);
6003 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6004 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6005 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6010 /*-----------------------------------------------------------------*/
6011 /* genRightShiftLiteral - right shifting by known count */
6012 /*-----------------------------------------------------------------*/
6013 static void genRightShiftLiteral (operand *left,
6019 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6022 D(emitcode(";", "genRightShiftLiteral"););
6024 freeAsmop(right,NULL,ic,TRUE);
6026 aopOp(left,ic,FALSE, FALSE);
6027 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6030 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6034 size = getDataSize(left);
6035 /* test the LEFT size !!! */
6037 /* I suppose that the left size >= result size */
6039 size = getDataSize(result);
6041 movLeft2Result(left, size, result, size, 0);
6044 else if(shCount >= (size * 8)){
6046 /* get sign in acc.7 */
6047 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6048 addSign(result, LSB, sign);
6052 genrshOne (result,left,shCount,sign);
6056 genrshTwo (result,left,shCount,sign);
6060 genrshFour (result,left,shCount,sign);
6066 freeAsmop(left,NULL,ic,TRUE);
6067 freeAsmop(result,NULL,ic,TRUE);
6071 /*-----------------------------------------------------------------*/
6072 /* genSignedRightShift - right shift of signed number */
6073 /*-----------------------------------------------------------------*/
6074 static void genSignedRightShift (iCode *ic)
6076 operand *right, *left, *result;
6079 symbol *tlbl, *tlbl1 ;
6081 D(emitcode(";", "genSignedRightShift "););
6083 /* we do it the hard way put the shift count in b
6084 and loop thru preserving the sign */
6086 right = IC_RIGHT(ic);
6088 result = IC_RESULT(ic);
6090 aopOp(right,ic,FALSE, FALSE);
6093 if ( AOP_TYPE(right) == AOP_LIT) {
6094 genRightShiftLiteral (left,right,result,ic,1);
6098 /* shift count is unknown then we have to form
6099 a loop get the loop count in B : Note: we take
6100 only the lower order byte since shifting
6101 more that 32 bits make no sense anyway, ( the
6102 largest size of an object can be only 32 bits ) */
6104 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6105 emitcode("inc","b");
6106 freeAsmop (right,NULL,ic,TRUE);
6107 aopOp(left,ic,FALSE, FALSE);
6108 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6110 /* now move the left to the result if they are not the
6112 if (!sameRegs(AOP(left),AOP(result)) &&
6113 AOP_SIZE(result) > 1) {
6115 size = AOP_SIZE(result);
6118 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6119 if (*l == '@' && IS_AOP_PREG(result)) {
6121 emitcode("mov","a,%s",l);
6122 aopPut(AOP(result),"a",offset);
6124 aopPut(AOP(result),l,offset);
6129 /* mov the highest order bit to OVR */
6130 tlbl = newiTempLabel(NULL);
6131 tlbl1= newiTempLabel(NULL);
6133 size = AOP_SIZE(result);
6135 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6136 emitcode("rlc","a");
6137 emitcode("mov","ov,c");
6138 /* if it is only one byte then */
6140 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6142 emitcode("sjmp","%05d$",tlbl1->key+100);
6143 emitcode("","%05d$:",tlbl->key+100);
6144 emitcode("mov","c,ov");
6145 emitcode("rrc","a");
6146 emitcode("","%05d$:",tlbl1->key+100);
6147 emitcode("djnz","b,%05d$",tlbl->key+100);
6148 aopPut(AOP(result),"a",0);
6152 reAdjustPreg(AOP(result));
6153 emitcode("sjmp","%05d$",tlbl1->key+100);
6154 emitcode("","%05d$:",tlbl->key+100);
6155 emitcode("mov","c,ov");
6157 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6159 emitcode("rrc","a");
6160 aopPut(AOP(result),"a",offset--);
6162 reAdjustPreg(AOP(result));
6163 emitcode("","%05d$:",tlbl1->key+100);
6164 emitcode("djnz","b,%05d$",tlbl->key+100);
6167 freeAsmop(left,NULL,ic,TRUE);
6168 freeAsmop(result,NULL,ic,TRUE);
6171 /*-----------------------------------------------------------------*/
6172 /* genRightShift - generate code for right shifting */
6173 /*-----------------------------------------------------------------*/
6174 static void genRightShift (iCode *ic)
6176 operand *right, *left, *result;
6180 symbol *tlbl, *tlbl1 ;
6182 D(emitcode(";", "genRightShift "););
6184 /* if signed then we do it the hard way preserve the
6185 sign bit moving it inwards */
6186 retype = getSpec(operandType(IC_RESULT(ic)));
6188 if (!SPEC_USIGN(retype)) {
6189 genSignedRightShift (ic);
6193 /* signed & unsigned types are treated the same : i.e. the
6194 signed is NOT propagated inwards : quoting from the
6195 ANSI - standard : "for E1 >> E2, is equivalent to division
6196 by 2**E2 if unsigned or if it has a non-negative value,
6197 otherwise the result is implementation defined ", MY definition
6198 is that the sign does not get propagated */
6200 right = IC_RIGHT(ic);
6202 result = IC_RESULT(ic);
6204 aopOp(right,ic,FALSE, FALSE);
6207 /* if the shift count is known then do it
6208 as efficiently as possible */
6209 if (AOP_TYPE(right) == AOP_LIT) {
6210 genRightShiftLiteral (left,right,result,ic, 0);
6215 /* shift count is unknown then we have to form
6216 a loop get the loop count in B : Note: we take
6217 only the lower order byte since shifting
6218 more that 32 bits make no sense anyway, ( the
6219 largest size of an object can be only 32 bits ) */
6221 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6222 emitcode("inc","b");
6223 freeAsmop (right,NULL,ic,TRUE);
6224 aopOp(left,ic,FALSE, FALSE);
6225 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6227 /* now move the left to the result if they are not the
6229 if (!sameRegs(AOP(left),AOP(result)) &&
6230 AOP_SIZE(result) > 1) {
6232 size = AOP_SIZE(result);
6235 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6236 if (*l == '@' && IS_AOP_PREG(result)) {
6238 emitcode("mov","a,%s",l);
6239 aopPut(AOP(result),"a",offset);
6241 aopPut(AOP(result),l,offset);
6246 tlbl = newiTempLabel(NULL);
6247 tlbl1= newiTempLabel(NULL);
6248 size = AOP_SIZE(result);
6251 /* if it is only one byte then */
6253 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6255 emitcode("sjmp","%05d$",tlbl1->key+100);
6256 emitcode("","%05d$:",tlbl->key+100);
6258 emitcode("rrc","a");
6259 emitcode("","%05d$:",tlbl1->key+100);
6260 emitcode("djnz","b,%05d$",tlbl->key+100);
6261 aopPut(AOP(result),"a",0);
6265 reAdjustPreg(AOP(result));
6266 emitcode("sjmp","%05d$",tlbl1->key+100);
6267 emitcode("","%05d$:",tlbl->key+100);
6270 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6272 emitcode("rrc","a");
6273 aopPut(AOP(result),"a",offset--);
6275 reAdjustPreg(AOP(result));
6277 emitcode("","%05d$:",tlbl1->key+100);
6278 emitcode("djnz","b,%05d$",tlbl->key+100);
6281 freeAsmop(left,NULL,ic,TRUE);
6282 freeAsmop(result,NULL,ic,TRUE);
6285 /*-----------------------------------------------------------------*/
6286 /* genUnpackBits - generates code for unpacking bits */
6287 /*-----------------------------------------------------------------*/
6288 static void genUnpackBits (operand *result, char *rname, int ptype)
6295 D(emitcode(";", "genUnpackBits "););
6297 etype = getSpec(operandType(result));
6299 /* read the first byte */
6304 emitcode("mov","a,@%s",rname);
6308 emitcode("movx","a,@%s",rname);
6312 emitcode("movx","a,@dptr");
6316 emitcode("clr","a");
6317 emitcode("movc","a","@a+dptr");
6321 emitcode("lcall","__gptrget");
6325 /* if we have bitdisplacement then it fits */
6326 /* into this byte completely or if length is */
6327 /* less than a byte */
6328 if ((shCnt = SPEC_BSTR(etype)) ||
6329 (SPEC_BLEN(etype) <= 8)) {
6331 /* shift right acc */
6334 emitcode("anl","a,#0x%02x",
6335 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6336 aopPut(AOP(result),"a",offset);
6340 /* bit field did not fit in a byte */
6341 rlen = SPEC_BLEN(etype) - 8;
6342 aopPut(AOP(result),"a",offset++);
6349 emitcode("inc","%s",rname);
6350 emitcode("mov","a,@%s",rname);
6354 emitcode("inc","%s",rname);
6355 emitcode("movx","a,@%s",rname);
6359 emitcode("inc","dptr");
6360 emitcode("movx","a,@dptr");
6364 emitcode("clr","a");
6365 emitcode("inc","dptr");
6366 emitcode("movc","a","@a+dptr");
6370 emitcode("inc","dptr");
6371 emitcode("lcall","__gptrget");
6376 /* if we are done */
6380 aopPut(AOP(result),"a",offset++);
6385 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6386 aopPut(AOP(result),"a",offset);
6393 /*-----------------------------------------------------------------*/
6394 /* genDataPointerGet - generates code when ptr offset is known */
6395 /*-----------------------------------------------------------------*/
6396 static void genDataPointerGet (operand *left,
6402 int size , offset = 0;
6403 aopOp(result,ic,TRUE, FALSE);
6405 /* get the string representation of the name */
6406 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6407 size = AOP_SIZE(result);
6410 sprintf(buffer,"(%s + %d)",l+1,offset);
6412 sprintf(buffer,"%s",l+1);
6413 aopPut(AOP(result),buffer,offset++);
6416 freeAsmop(left,NULL,ic,TRUE);
6417 freeAsmop(result,NULL,ic,TRUE);
6420 /*-----------------------------------------------------------------*/
6421 /* genNearPointerGet - emitcode for near pointer fetch */
6422 /*-----------------------------------------------------------------*/
6423 static void genNearPointerGet (operand *left,
6430 link *rtype, *retype;
6431 link *ltype = operandType(left);
6434 rtype = operandType(result);
6435 retype= getSpec(rtype);
6437 aopOp(left,ic,FALSE, FALSE);
6439 /* if left is rematerialisable and
6440 result is not bit variable type and
6441 the left is pointer to data space i.e
6442 lower 128 bytes of space */
6443 if (AOP_TYPE(left) == AOP_IMMD &&
6444 !IS_BITVAR(retype) &&
6445 DCL_TYPE(ltype) == POINTER) {
6446 genDataPointerGet (left,result,ic);
6450 /* if the value is already in a pointer register
6451 then don't need anything more */
6452 if (!AOP_INPREG(AOP(left))) {
6453 /* otherwise get a free pointer register */
6455 preg = getFreePtr(ic,&aop,FALSE);
6456 emitcode("mov","%s,%s",
6458 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6459 rname = preg->name ;
6461 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6463 freeAsmop(left,NULL,ic,TRUE);
6464 aopOp (result,ic,FALSE, FALSE);
6466 /* if bitfield then unpack the bits */
6467 if (IS_BITVAR(retype))
6468 genUnpackBits (result,rname,POINTER);
6470 /* we have can just get the values */
6471 int size = AOP_SIZE(result);
6475 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6477 emitcode("mov","a,@%s",rname);
6478 aopPut(AOP(result),"a",offset);
6480 sprintf(buffer,"@%s",rname);
6481 aopPut(AOP(result),buffer,offset);
6485 emitcode("inc","%s",rname);
6489 /* now some housekeeping stuff */
6491 /* we had to allocate for this iCode */
6492 freeAsmop(NULL,aop,ic,TRUE);
6494 /* we did not allocate which means left
6495 already in a pointer register, then
6496 if size > 0 && this could be used again
6497 we have to point it back to where it
6499 if (AOP_SIZE(result) > 1 &&
6500 !OP_SYMBOL(left)->remat &&
6501 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6503 int size = AOP_SIZE(result) - 1;
6505 emitcode("dec","%s",rname);
6510 freeAsmop(result,NULL,ic,TRUE);
6514 /*-----------------------------------------------------------------*/
6515 /* genPagedPointerGet - emitcode for paged pointer fetch */
6516 /*-----------------------------------------------------------------*/
6517 static void genPagedPointerGet (operand *left,
6524 link *rtype, *retype;
6526 rtype = operandType(result);
6527 retype= getSpec(rtype);
6529 aopOp(left,ic,FALSE, FALSE);
6531 /* if the value is already in a pointer register
6532 then don't need anything more */
6533 if (!AOP_INPREG(AOP(left))) {
6534 /* otherwise get a free pointer register */
6536 preg = getFreePtr(ic,&aop,FALSE);
6537 emitcode("mov","%s,%s",
6539 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6540 rname = preg->name ;
6542 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6544 freeAsmop(left,NULL,ic,TRUE);
6545 aopOp (result,ic,FALSE, FALSE);
6547 /* if bitfield then unpack the bits */
6548 if (IS_BITVAR(retype))
6549 genUnpackBits (result,rname,PPOINTER);
6551 /* we have can just get the values */
6552 int size = AOP_SIZE(result);
6557 emitcode("movx","a,@%s",rname);
6558 aopPut(AOP(result),"a",offset);
6563 emitcode("inc","%s",rname);
6567 /* now some housekeeping stuff */
6569 /* we had to allocate for this iCode */
6570 freeAsmop(NULL,aop,ic,TRUE);
6572 /* we did not allocate which means left
6573 already in a pointer register, then
6574 if size > 0 && this could be used again
6575 we have to point it back to where it
6577 if (AOP_SIZE(result) > 1 &&
6578 !OP_SYMBOL(left)->remat &&
6579 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6581 int size = AOP_SIZE(result) - 1;
6583 emitcode("dec","%s",rname);
6588 freeAsmop(result,NULL,ic,TRUE);
6593 /*-----------------------------------------------------------------*/
6594 /* genFarPointerGet - gget value from far space */
6595 /*-----------------------------------------------------------------*/
6596 static void genFarPointerGet (operand *left,
6597 operand *result, iCode *ic)
6600 link *retype = getSpec(operandType(result));
6602 D(emitcode(";", "genFarPointerGet"););
6604 aopOp(left,ic,FALSE, FALSE);
6606 /* if the operand is already in dptr
6607 then we do nothing else we move the value to dptr */
6608 if (AOP_TYPE(left) != AOP_STR) {
6609 /* if this is remateriazable */
6610 if (AOP_TYPE(left) == AOP_IMMD)
6612 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6616 /* we need to get it byte by byte */
6617 if (AOP_TYPE(left) != AOP_DPTR)
6619 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6620 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6621 if (options.model == MODEL_FLAT24)
6623 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6628 /* We need to generate a load to DPTR indirect through DPTR. */
6629 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6630 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6631 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6632 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6633 emitcode("pop", "dph");
6634 emitcode("pop", "dpl");
6638 /* so dptr know contains the address */
6639 freeAsmop(left,NULL,ic,TRUE);
6640 aopOp(result,ic,FALSE, TRUE);
6642 /* if bit then unpack */
6643 if (IS_BITVAR(retype))
6644 genUnpackBits(result,"dptr",FPOINTER);
6646 size = AOP_SIZE(result);
6650 emitcode("movx","a,@dptr");
6651 aopPut(AOP(result),"a",offset++);
6653 emitcode("inc","dptr");
6657 freeAsmop(result,NULL,ic,TRUE);
6660 /*-----------------------------------------------------------------*/
6661 /* emitcodePointerGet - gget value from code space */
6662 /*-----------------------------------------------------------------*/
6663 static void emitcodePointerGet (operand *left,
6664 operand *result, iCode *ic)
6667 link *retype = getSpec(operandType(result));
6669 aopOp(left,ic,FALSE, FALSE);
6671 /* if the operand is already in dptr
6672 then we do nothing else we move the value to dptr */
6673 if (AOP_TYPE(left) != AOP_STR) {
6674 /* if this is remateriazable */
6675 if (AOP_TYPE(left) == AOP_IMMD)
6676 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6677 else { /* we need to get it byte by byte */
6678 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6679 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6680 if (options.model == MODEL_FLAT24)
6682 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6686 /* so dptr know contains the address */
6687 freeAsmop(left,NULL,ic,TRUE);
6688 aopOp(result,ic,FALSE, FALSE);
6690 /* if bit then unpack */
6691 if (IS_BITVAR(retype))
6692 genUnpackBits(result,"dptr",CPOINTER);
6694 size = AOP_SIZE(result);
6698 emitcode("clr","a");
6699 emitcode("movc","a,@a+dptr");
6700 aopPut(AOP(result),"a",offset++);
6702 emitcode("inc","dptr");
6706 freeAsmop(result,NULL,ic,TRUE);
6709 /*-----------------------------------------------------------------*/
6710 /* genGenPointerGet - gget value from generic pointer space */
6711 /*-----------------------------------------------------------------*/
6712 static void genGenPointerGet (operand *left,
6713 operand *result, iCode *ic)
6716 link *retype = getSpec(operandType(result));
6718 aopOp(left,ic,FALSE, TRUE);
6720 /* if the operand is already in dptr
6721 then we do nothing else we move the value to dptr */
6722 if (AOP_TYPE(left) != AOP_STR) {
6723 /* if this is remateriazable */
6724 if (AOP_TYPE(left) == AOP_IMMD) {
6725 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6726 emitcode("mov","b,#%d",pointerCode(retype));
6728 else { /* we need to get it byte by byte */
6729 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6730 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6731 if (options.model == MODEL_FLAT24)
6733 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6734 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
6738 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6742 /* so dptr know contains the address */
6743 freeAsmop(left,NULL,ic,TRUE);
6744 aopOp(result,ic,FALSE, TRUE);
6746 /* if bit then unpack */
6747 if (IS_BITVAR(retype))
6748 genUnpackBits(result,"dptr",GPOINTER);
6750 size = AOP_SIZE(result);
6754 emitcode("lcall","__gptrget");
6755 aopPut(AOP(result),"a",offset++);
6757 emitcode("inc","dptr");
6761 freeAsmop(result,NULL,ic,TRUE);
6764 /*-----------------------------------------------------------------*/
6765 /* genPointerGet - generate code for pointer get */
6766 /*-----------------------------------------------------------------*/
6767 static void genPointerGet (iCode *ic)
6769 operand *left, *result ;
6773 D(emitcode(";", "genPointerGet "););
6776 result = IC_RESULT(ic) ;
6778 /* depending on the type of pointer we need to
6779 move it to the correct pointer register */
6780 type = operandType(left);
6781 etype = getSpec(type);
6782 /* if left is of type of pointer then it is simple */
6783 if (IS_PTR(type) && !IS_FUNC(type->next))
6784 p_type = DCL_TYPE(type);
6786 /* we have to go by the storage class */
6787 p_type = PTR_TYPE(SPEC_OCLS(etype));
6789 /* if (SPEC_OCLS(etype)->codesp ) { */
6790 /* p_type = CPOINTER ; */
6793 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6794 /* p_type = FPOINTER ; */
6796 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6797 /* p_type = PPOINTER; */
6799 /* if (SPEC_OCLS(etype) == idata ) */
6800 /* p_type = IPOINTER; */
6802 /* p_type = POINTER ; */
6805 /* now that we have the pointer type we assign
6806 the pointer values */
6811 genNearPointerGet (left,result,ic);
6815 genPagedPointerGet(left,result,ic);
6819 genFarPointerGet (left,result,ic);
6823 emitcodePointerGet (left,result,ic);
6827 genGenPointerGet (left,result,ic);
6833 /*-----------------------------------------------------------------*/
6834 /* genPackBits - generates code for packed bit storage */
6835 /*-----------------------------------------------------------------*/
6836 static void genPackBits (link *etype ,
6838 char *rname, int p_type)
6846 blen = SPEC_BLEN(etype);
6847 bstr = SPEC_BSTR(etype);
6849 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
6852 /* if the bit lenth is less than or */
6853 /* it exactly fits a byte then */
6854 if (SPEC_BLEN(etype) <= 8 ) {
6855 shCount = SPEC_BSTR(etype) ;
6857 /* shift left acc */
6860 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6865 emitcode ("mov","b,a");
6866 emitcode("mov","a,@%s",rname);
6870 emitcode ("mov","b,a");
6871 emitcode("movx","a,@dptr");
6875 emitcode ("push","b");
6876 emitcode ("push","acc");
6877 emitcode ("lcall","__gptrget");
6878 emitcode ("pop","b");
6882 emitcode ("anl","a,#0x%02x",(unsigned char)
6883 ((unsigned char)(0xFF << (blen+bstr)) |
6884 (unsigned char)(0xFF >> (8-bstr)) ) );
6885 emitcode ("orl","a,b");
6886 if (p_type == GPOINTER)
6887 emitcode("pop","b");
6893 emitcode("mov","@%s,a",rname);
6897 emitcode("movx","@dptr,a");
6901 emitcode("lcall","__gptrput");
6906 if ( SPEC_BLEN(etype) <= 8 )
6909 emitcode("inc","%s",rname);
6910 rLen = SPEC_BLEN(etype) ;
6912 /* now generate for lengths greater than one byte */
6915 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
6925 emitcode("mov","@%s,a",rname);
6927 emitcode("mov","@%s,%s",rname,l);
6932 emitcode("movx","@dptr,a");
6937 emitcode("lcall","__gptrput");
6940 emitcode ("inc","%s",rname);
6945 /* last last was not complete */
6947 /* save the byte & read byte */
6950 emitcode ("mov","b,a");
6951 emitcode("mov","a,@%s",rname);
6955 emitcode ("mov","b,a");
6956 emitcode("movx","a,@dptr");
6960 emitcode ("push","b");
6961 emitcode ("push","acc");
6962 emitcode ("lcall","__gptrget");
6963 emitcode ("pop","b");
6967 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6968 emitcode ("orl","a,b");
6971 if (p_type == GPOINTER)
6972 emitcode("pop","b");
6977 emitcode("mov","@%s,a",rname);
6981 emitcode("movx","@dptr,a");
6985 emitcode("lcall","__gptrput");
6989 /*-----------------------------------------------------------------*/
6990 /* genDataPointerSet - remat pointer to data space */
6991 /*-----------------------------------------------------------------*/
6992 static void genDataPointerSet(operand *right,
6996 int size, offset = 0 ;
6997 char *l, buffer[256];
6999 aopOp(right,ic,FALSE, FALSE);
7001 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7002 size = AOP_SIZE(right);
7005 sprintf(buffer,"(%s + %d)",l+1,offset);
7007 sprintf(buffer,"%s",l+1);
7008 emitcode("mov","%s,%s",buffer,
7009 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7012 freeAsmop(right,NULL,ic,TRUE);
7013 freeAsmop(result,NULL,ic,TRUE);
7016 /*-----------------------------------------------------------------*/
7017 /* genNearPointerSet - emitcode for near pointer put */
7018 /*-----------------------------------------------------------------*/
7019 static void genNearPointerSet (operand *right,
7027 link *ptype = operandType(result);
7029 retype= getSpec(operandType(right));
7031 aopOp(result,ic,FALSE, FALSE);
7033 /* if the result is rematerializable &
7034 in data space & not a bit variable */
7035 if (AOP_TYPE(result) == AOP_IMMD &&
7036 DCL_TYPE(ptype) == POINTER &&
7037 !IS_BITVAR(retype)) {
7038 genDataPointerSet (right,result,ic);
7042 /* if the value is already in a pointer register
7043 then don't need anything more */
7044 if (!AOP_INPREG(AOP(result))) {
7045 /* otherwise get a free pointer register */
7047 preg = getFreePtr(ic,&aop,FALSE);
7048 emitcode("mov","%s,%s",
7050 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7051 rname = preg->name ;
7053 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7055 freeAsmop(result,NULL,ic,TRUE);
7056 aopOp (right,ic,FALSE, FALSE);
7058 /* if bitfield then unpack the bits */
7059 if (IS_BITVAR(retype))
7060 genPackBits (retype,right,rname,POINTER);
7062 /* we have can just get the values */
7063 int size = AOP_SIZE(right);
7067 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7070 emitcode("mov","@%s,a",rname);
7072 emitcode("mov","@%s,%s",rname,l);
7074 emitcode("inc","%s",rname);
7079 /* now some housekeeping stuff */
7081 /* we had to allocate for this iCode */
7082 freeAsmop(NULL,aop,ic,TRUE);
7084 /* we did not allocate which means left
7085 already in a pointer register, then
7086 if size > 0 && this could be used again
7087 we have to point it back to where it
7089 if (AOP_SIZE(right) > 1 &&
7090 !OP_SYMBOL(result)->remat &&
7091 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7093 int size = AOP_SIZE(right) - 1;
7095 emitcode("dec","%s",rname);
7100 freeAsmop(right,NULL,ic,TRUE);
7105 /*-----------------------------------------------------------------*/
7106 /* genPagedPointerSet - emitcode for Paged pointer put */
7107 /*-----------------------------------------------------------------*/
7108 static void genPagedPointerSet (operand *right,
7117 retype= getSpec(operandType(right));
7119 aopOp(result,ic,FALSE, FALSE);
7121 /* if the value is already in a pointer register
7122 then don't need anything more */
7123 if (!AOP_INPREG(AOP(result))) {
7124 /* otherwise get a free pointer register */
7126 preg = getFreePtr(ic,&aop,FALSE);
7127 emitcode("mov","%s,%s",
7129 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7130 rname = preg->name ;
7132 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7134 freeAsmop(result,NULL,ic,TRUE);
7135 aopOp (right,ic,FALSE, FALSE);
7137 /* if bitfield then unpack the bits */
7138 if (IS_BITVAR(retype))
7139 genPackBits (retype,right,rname,PPOINTER);
7141 /* we have can just get the values */
7142 int size = AOP_SIZE(right);
7146 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7149 emitcode("movx","@%s,a",rname);
7152 emitcode("inc","%s",rname);
7158 /* now some housekeeping stuff */
7160 /* we had to allocate for this iCode */
7161 freeAsmop(NULL,aop,ic,TRUE);
7163 /* we did not allocate which means left
7164 already in a pointer register, then
7165 if size > 0 && this could be used again
7166 we have to point it back to where it
7168 if (AOP_SIZE(right) > 1 &&
7169 !OP_SYMBOL(result)->remat &&
7170 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7172 int size = AOP_SIZE(right) - 1;
7174 emitcode("dec","%s",rname);
7179 freeAsmop(right,NULL,ic,TRUE);
7184 /*-----------------------------------------------------------------*/
7185 /* genFarPointerSet - set value from far space */
7186 /*-----------------------------------------------------------------*/
7187 static void genFarPointerSet (operand *right,
7188 operand *result, iCode *ic)
7191 link *retype = getSpec(operandType(right));
7193 aopOp(result,ic,FALSE, FALSE);
7195 /* if the operand is already in dptr
7196 then we do nothing else we move the value to dptr */
7197 if (AOP_TYPE(result) != AOP_STR) {
7198 /* if this is remateriazable */
7199 if (AOP_TYPE(result) == AOP_IMMD)
7200 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7203 /* we need to get it byte by byte */
7204 if (AOP_TYPE(result) != AOP_DPTR)
7206 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7207 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7208 if (options.model == MODEL_FLAT24)
7210 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7215 /* We need to generate a load to DPTR indirect through DPTR. */
7216 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7217 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7218 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7219 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7220 emitcode("pop", "dph");
7221 emitcode("pop", "dpl");
7225 /* so dptr know contains the address */
7226 freeAsmop(result,NULL,ic,TRUE);
7227 aopOp(right,ic,FALSE, TRUE);
7229 /* if bit then unpack */
7230 if (IS_BITVAR(retype))
7231 genPackBits(retype,right,"dptr",FPOINTER);
7233 size = AOP_SIZE(right);
7237 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7239 emitcode("movx","@dptr,a");
7241 emitcode("inc","dptr");
7245 freeAsmop(right,NULL,ic,TRUE);
7248 /*-----------------------------------------------------------------*/
7249 /* genGenPointerSet - set value from generic pointer space */
7250 /*-----------------------------------------------------------------*/
7251 static void genGenPointerSet (operand *right,
7252 operand *result, iCode *ic)
7255 link *retype = getSpec(operandType(right));
7257 aopOp(result,ic,FALSE, TRUE);
7259 /* if the operand is already in dptr
7260 then we do nothing else we move the value to dptr */
7261 if (AOP_TYPE(result) != AOP_STR) {
7262 /* if this is remateriazable */
7263 if (AOP_TYPE(result) == AOP_IMMD) {
7264 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7265 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7267 else { /* we need to get it byte by byte */
7268 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7269 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7270 if (options.model == MODEL_FLAT24)
7272 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7273 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7277 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7281 /* so dptr know contains the address */
7282 freeAsmop(result,NULL,ic,TRUE);
7283 aopOp(right,ic,FALSE, TRUE);
7285 /* if bit then unpack */
7286 if (IS_BITVAR(retype))
7287 genPackBits(retype,right,"dptr",GPOINTER);
7289 size = AOP_SIZE(right);
7293 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7295 emitcode("lcall","__gptrput");
7297 emitcode("inc","dptr");
7301 freeAsmop(right,NULL,ic,TRUE);
7304 /*-----------------------------------------------------------------*/
7305 /* genPointerSet - stores the value into a pointer location */
7306 /*-----------------------------------------------------------------*/
7307 static void genPointerSet (iCode *ic)
7309 operand *right, *result ;
7313 D(emitcode(";", "genPointerSet "););
7315 right = IC_RIGHT(ic);
7316 result = IC_RESULT(ic) ;
7318 /* depending on the type of pointer we need to
7319 move it to the correct pointer register */
7320 type = operandType(result);
7321 etype = getSpec(type);
7322 /* if left is of type of pointer then it is simple */
7323 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7324 p_type = DCL_TYPE(type);
7327 /* we have to go by the storage class */
7328 p_type = PTR_TYPE(SPEC_OCLS(etype));
7330 /* if (SPEC_OCLS(etype)->codesp ) { */
7331 /* p_type = CPOINTER ; */
7334 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7335 /* p_type = FPOINTER ; */
7337 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7338 /* p_type = PPOINTER ; */
7340 /* if (SPEC_OCLS(etype) == idata ) */
7341 /* p_type = IPOINTER ; */
7343 /* p_type = POINTER ; */
7346 /* now that we have the pointer type we assign
7347 the pointer values */
7352 genNearPointerSet (right,result,ic);
7356 genPagedPointerSet (right,result,ic);
7360 genFarPointerSet (right,result,ic);
7364 genGenPointerSet (right,result,ic);
7370 /*-----------------------------------------------------------------*/
7371 /* genIfx - generate code for Ifx statement */
7372 /*-----------------------------------------------------------------*/
7373 static void genIfx (iCode *ic, iCode *popIc)
7375 operand *cond = IC_COND(ic);
7378 D(emitcode(";", "genIfx "););
7380 aopOp(cond,ic,FALSE, FALSE);
7382 /* get the value into acc */
7383 if (AOP_TYPE(cond) != AOP_CRY)
7387 /* the result is now in the accumulator */
7388 freeAsmop(cond,NULL,ic,TRUE);
7390 /* if there was something to be popped then do it */
7394 /* if the condition is a bit variable */
7395 if (isbit && IS_ITEMP(cond) &&
7397 genIfxJump(ic,SPIL_LOC(cond)->rname);
7399 if (isbit && !IS_ITEMP(cond))
7400 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7407 /*-----------------------------------------------------------------*/
7408 /* genAddrOf - generates code for address of */
7409 /*-----------------------------------------------------------------*/
7410 static void genAddrOf (iCode *ic)
7412 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7415 D(emitcode(";", "genAddrOf "););
7417 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7419 /* if the operand is on the stack then we
7420 need to get the stack offset of this
7423 /* if it has an offset then we need to compute
7426 emitcode("mov","a,_bp");
7427 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7428 aopPut(AOP(IC_RESULT(ic)),"a",0);
7430 /* we can just move _bp */
7431 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7433 /* fill the result with zero */
7434 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7437 if (options.stack10bit && size < (FPTRSIZE - 1))
7440 "*** warning: pointer to stack var truncated.\n");
7447 if (options.stack10bit && offset == 2)
7449 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7453 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7460 /* object not on stack then we need the name */
7461 size = AOP_SIZE(IC_RESULT(ic));
7465 char s[SDCC_NAME_MAX];
7467 sprintf(s,"#(%s >> %d)",
7471 sprintf(s,"#%s",sym->rname);
7472 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7476 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7480 /*-----------------------------------------------------------------*/
7481 /* genFarFarAssign - assignment when both are in far space */
7482 /*-----------------------------------------------------------------*/
7483 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7485 int size = AOP_SIZE(right);
7488 /* first push the right side on to the stack */
7490 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7492 emitcode ("push","acc");
7495 D(emitcode(";", "genFarFarAssign "););
7497 freeAsmop(right,NULL,ic,FALSE);
7498 /* now assign DPTR to result */
7499 aopOp(result,ic,FALSE, FALSE);
7500 size = AOP_SIZE(result);
7502 emitcode ("pop","acc");
7503 aopPut(AOP(result),"a",--offset);
7505 freeAsmop(result,NULL,ic,FALSE);
7509 /*-----------------------------------------------------------------*/
7510 /* genAssign - generate code for assignment */
7511 /*-----------------------------------------------------------------*/
7512 static void genAssign (iCode *ic)
7514 operand *result, *right;
7516 unsigned long lit = 0L;
7518 D(emitcode(";", "genAssign "););
7520 result = IC_RESULT(ic);
7521 right = IC_RIGHT(ic) ;
7523 /* if they are the same */
7524 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7527 aopOp(right,ic,FALSE, FALSE);
7529 emitcode(";", "genAssign: resultIsFar = %s",
7530 isOperandInFarSpace(result) ?
7533 /* special case both in far space */
7534 if ((AOP_TYPE(right) == AOP_DPTR ||
7535 AOP_TYPE(right) == AOP_DPTR2) &&
7536 /* IS_TRUE_SYMOP(result) && */
7537 isOperandInFarSpace(result)) {
7539 genFarFarAssign (result,right,ic);
7543 aopOp(result,ic,TRUE, FALSE);
7545 /* if they are the same registers */
7546 if (sameRegs(AOP(right),AOP(result)))
7549 /* if the result is a bit */
7550 if (AOP_TYPE(result) == AOP_CRY) {
7552 /* if the right size is a literal then
7553 we know what the value is */
7554 if (AOP_TYPE(right) == AOP_LIT) {
7555 if (((int) operandLitValue(right)))
7556 aopPut(AOP(result),one,0);
7558 aopPut(AOP(result),zero,0);
7562 /* the right is also a bit variable */
7563 if (AOP_TYPE(right) == AOP_CRY) {
7564 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7565 aopPut(AOP(result),"c",0);
7571 aopPut(AOP(result),"a",0);
7575 /* bit variables done */
7577 size = AOP_SIZE(result);
7579 if(AOP_TYPE(right) == AOP_LIT)
7580 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7582 (AOP_TYPE(result) != AOP_REG) &&
7583 (AOP_TYPE(right) == AOP_LIT) &&
7584 !IS_FLOAT(operandType(right)) &&
7586 emitcode("clr","a");
7588 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7589 aopPut(AOP(result),"a",size);
7592 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
7598 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7605 freeAsmop (right,NULL,ic,FALSE);
7606 freeAsmop (result,NULL,ic,TRUE);
7609 /*-----------------------------------------------------------------*/
7610 /* genJumpTab - genrates code for jump table */
7611 /*-----------------------------------------------------------------*/
7612 static void genJumpTab (iCode *ic)
7617 D(emitcode(";", "genJumpTab "););
7619 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7620 /* get the condition into accumulator */
7621 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
7623 /* multiply by four! */
7624 emitcode("add","a,acc");
7625 emitcode("add","a,acc");
7626 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7628 jtab = newiTempLabel(NULL);
7629 emitcode("mov","dptr,#%05d$",jtab->key+100);
7630 emitcode("jmp","@a+dptr");
7631 emitcode("","%05d$:",jtab->key+100);
7632 /* now generate the jump labels */
7633 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7634 jtab = setNextItem(IC_JTLABELS(ic)))
7635 emitcode("ljmp","%05d$",jtab->key+100);
7639 /*-----------------------------------------------------------------*/
7640 /* genCast - gen code for casting */
7641 /*-----------------------------------------------------------------*/
7642 static void genCast (iCode *ic)
7644 operand *result = IC_RESULT(ic);
7645 link *ctype = operandType(IC_LEFT(ic));
7646 link *rtype = operandType(IC_RIGHT(ic));
7647 operand *right = IC_RIGHT(ic);
7650 D(emitcode(";", "genCast "););
7652 /* if they are equivalent then do nothing */
7653 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7656 aopOp(right,ic,FALSE, FALSE) ;
7657 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7659 /* if the result is a bit */
7660 if (AOP_TYPE(result) == AOP_CRY) {
7661 /* if the right size is a literal then
7662 we know what the value is */
7663 if (AOP_TYPE(right) == AOP_LIT) {
7664 if (((int) operandLitValue(right)))
7665 aopPut(AOP(result),one,0);
7667 aopPut(AOP(result),zero,0);
7672 /* the right is also a bit variable */
7673 if (AOP_TYPE(right) == AOP_CRY) {
7674 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7675 aopPut(AOP(result),"c",0);
7681 aopPut(AOP(result),"a",0);
7685 /* if they are the same size : or less */
7686 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7688 /* if they are in the same place */
7689 if (sameRegs(AOP(right),AOP(result)))
7692 /* if they in different places then copy */
7693 size = AOP_SIZE(result);
7697 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7705 /* if the result is of type pointer */
7706 if (IS_PTR(ctype)) {
7709 link *type = operandType(right);
7711 /* pointer to generic pointer */
7712 if (IS_GENPTR(ctype)) {
7717 p_type = DCL_TYPE(type);
7721 #if OLD_CAST_BEHAVIOR
7722 /* KV: we are converting a non-pointer type to
7723 * a generic pointer. This (ifdef'd out) code
7724 * says that the resulting generic pointer
7725 * should have the same class as the storage
7726 * location of the non-pointer variable.
7728 * For example, converting an int (which happens
7729 * to be stored in DATA space) to a pointer results
7730 * in a DATA generic pointer; if the original int
7731 * in XDATA space, so will be the resulting pointer.
7733 * I don't like that behavior, and thus this change:
7734 * all such conversions will be forced to XDATA and
7735 * throw a warning. If you want some non-XDATA
7736 * type, or you want to suppress the warning, you
7737 * must go through an intermediate cast, like so:
7739 * char _generic *gp = (char _xdata *)(intVar);
7741 link *etype = getSpec(type);
7743 /* we have to go by the storage class */
7744 if (SPEC_OCLS(etype) != generic)
7746 p_type = PTR_TYPE(SPEC_OCLS(etype));
7751 /* Converting unknown class (i.e. register variable)
7752 * to generic pointer. This is not good, but
7753 * we'll make a guess (and throw a warning).
7756 werror(W_INT_TO_GEN_PTR_CAST);
7760 /* the first two bytes are known */
7761 size = GPTRSIZE - 1;
7765 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7770 /* the last byte depending on type */
7787 /* this should never happen */
7788 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7789 "got unknown pointer type");
7792 aopPut(AOP(result),l, GPTRSIZE - 1);
7796 /* just copy the pointers */
7797 size = AOP_SIZE(result);
7801 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7808 /* so we now know that the size of destination is greater
7809 than the size of the source */
7810 /* we move to result for the size of source */
7811 size = AOP_SIZE(right);
7815 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7820 /* now depending on the sign of the source && destination */
7821 size = AOP_SIZE(result) - AOP_SIZE(right);
7822 /* if unsigned or not an integral type */
7823 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
7825 aopPut(AOP(result),zero,offset++);
7827 /* we need to extend the sign :{ */
7828 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7831 emitcode("rlc","a");
7832 emitcode("subb","a,acc");
7834 aopPut(AOP(result),"a",offset++);
7837 /* we are done hurray !!!! */
7840 freeAsmop(right,NULL,ic,TRUE);
7841 freeAsmop(result,NULL,ic,TRUE);
7845 /*-----------------------------------------------------------------*/
7846 /* genDjnz - generate decrement & jump if not zero instrucion */
7847 /*-----------------------------------------------------------------*/
7848 static int genDjnz (iCode *ic, iCode *ifx)
7854 /* if the if condition has a false label
7855 then we cannot save */
7859 /* if the minus is not of the form
7861 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7862 !IS_OP_LITERAL(IC_RIGHT(ic)))
7865 if (operandLitValue(IC_RIGHT(ic)) != 1)
7868 /* if the size of this greater than one then no
7870 if (getSize(operandType(IC_RESULT(ic))) > 1)
7873 /* otherwise we can save BIG */
7874 lbl = newiTempLabel(NULL);
7875 lbl1= newiTempLabel(NULL);
7877 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7879 if (IS_AOP_PREG(IC_RESULT(ic))) {
7880 emitcode("dec","%s",
7881 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
7882 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
7883 emitcode("jnz","%05d$",lbl->key+100);
7885 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
7888 emitcode ("sjmp","%05d$",lbl1->key+100);
7889 emitcode ("","%05d$:",lbl->key+100);
7890 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7891 emitcode ("","%05d$:",lbl1->key+100);
7893 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7898 /*-----------------------------------------------------------------*/
7899 /* genReceive - generate code for a receive iCode */
7900 /*-----------------------------------------------------------------*/
7901 static void genReceive (iCode *ic)
7904 D(emitcode(";", "genReceive "););
7906 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7907 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7908 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7909 int size = getSize(operandType(IC_RESULT(ic)));
7910 int offset = fReturnSize_390 - size;
7912 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
7913 fReturn[fReturnSize_390 - offset - 1] : "acc"));
7916 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7917 size = AOP_SIZE(IC_RESULT(ic));
7920 emitcode ("pop","acc");
7921 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7926 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7928 assignResultValue(IC_RESULT(ic));
7931 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7934 /*-----------------------------------------------------------------*/
7935 /* gen390Code - generate code for 8051 based controllers */
7936 /*-----------------------------------------------------------------*/
7937 void gen390Code (iCode *lic)
7942 lineHead = lineCurr = NULL;
7944 /* print the allocation information */
7946 printAllocInfo( currFunc, codeOutFile);
7947 /* if debug information required */
7948 /* if (options.debug && currFunc) { */
7950 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7952 if (IS_STATIC(currFunc->etype))
7953 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7955 emitcode("","G$%s$0$0 ==.",currFunc->name);
7958 /* stack pointer name */
7959 if (options.useXstack)
7965 for (ic = lic ; ic ; ic = ic->next ) {
7967 if ( cln != ic->lineno ) {
7968 if ( options.debug ) {
7970 emitcode("","C$%s$%d$%d$%d ==.",
7971 ic->filename,ic->lineno,
7972 ic->level,ic->block);
7975 emitcode(";","%s %d",ic->filename,ic->lineno);
7978 /* if the result is marked as
7979 spilt and rematerializable or code for
7980 this has already been generated then
7982 if (resultRemat(ic) || ic->generated )
7985 /* depending on the operation */
8004 /* IPOP happens only when trying to restore a
8005 spilt live range, if there is an ifx statement
8006 following this pop then the if statement might
8007 be using some of the registers being popped which
8008 would destory the contents of the register so
8009 we need to check for this condition and handle it */
8011 ic->next->op == IFX &&
8012 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8013 genIfx (ic->next,ic);
8031 genEndFunction (ic);
8051 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8068 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8072 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8079 /* note these two are xlated by algebraic equivalence
8080 during parsing SDCC.y */
8081 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8082 "got '>=' or '<=' shouldn't have come here");
8086 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8098 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8102 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8106 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8133 case GET_VALUE_AT_ADDRESS:
8138 if (POINTER_SET(ic))
8165 addSet(&_G.sendSet,ic);
8170 /* piCode(ic,stdout); */
8176 /* now we are ready to call the
8177 peep hole optimizer */
8178 if (!options.nopeep)
8179 peepHole (&lineHead);
8181 /* now do the actual printing */
8182 printLine (lineHead,codeOutFile);