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 -------------------------------------------------------------------------*/
40 #ifdef HAVE_SYS_ISA_DEFS_H
41 #include <sys/isa_defs.h>
47 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
48 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
53 char *aopLiteral (value *val, int offset);
59 /* this is the down and dirty file with all kinds of
60 kludgy & hacky stuff. This is what it is all about
61 CODE GENERATION for a specific MCU . some of the
62 routines may be reusable, will have to see */
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
70 unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
71 static char *fReturn[] = {"dpl","dph","dpx", "b","a" };
72 static char *accUse[] = {"a","b"};
74 static short rbank = -1;
86 static void saverbank (int, iCode *,bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
93 #define MOVA(x) { char *_mova_tmp = strdup(x); \
94 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
96 emitcode("mov","a,%s",_mova_tmp); \
100 #define CLRC emitcode("clr","c")
101 #define SETC emitcode("setb","c")
103 static lineNode *lineHead = NULL;
104 static lineNode *lineCurr = NULL;
106 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
107 0xE0, 0xC0, 0x80, 0x00};
108 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
109 0x07, 0x03, 0x01, 0x00};
116 /*-----------------------------------------------------------------*/
117 /* emitcode - writes the code into a file : for now it is simple */
118 /*-----------------------------------------------------------------*/
119 static void emitcode (char *inst,char *fmt, ...)
122 char lb[MAX_INLINEASM];
129 sprintf(lb,"%s\t",inst);
131 sprintf(lb,"%s",inst);
132 vsprintf(lb+(strlen(lb)),fmt,ap);
136 while (isspace(*lbp)) lbp++;
139 lineCurr = (lineCurr ?
140 connectLine(lineCurr,newLineNode(lb)) :
141 (lineHead = newLineNode(lb)));
142 lineCurr->isInline = _G.inLine;
143 lineCurr->isDebug = _G.debugLine;
147 /*-----------------------------------------------------------------*/
148 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
149 /*-----------------------------------------------------------------*/
150 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
152 bool r0iu = FALSE , r1iu = FALSE;
153 bool r0ou = FALSE , r1ou = FALSE;
155 /* the logic: if r0 & r1 used in the instruction
156 then we are in trouble otherwise */
158 /* first check if r0 & r1 are used by this
159 instruction, in which case we are in trouble */
160 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
161 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
166 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
167 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
169 /* if no usage of r0 then return it */
170 if (!r0iu && !r0ou) {
171 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
172 (*aopp)->type = AOP_R0;
174 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
177 /* if no usage of r1 then return it */
178 if (!r1iu && !r1ou) {
179 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
180 (*aopp)->type = AOP_R1;
182 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R1_IDX);
185 /* now we know they both have usage */
186 /* if r0 not used in this instruction */
188 /* push it if not already pushed */
190 emitcode ("push","%s",
191 ds390_regWithIdx(R0_IDX)->dname);
195 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
196 (*aopp)->type = AOP_R0;
198 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
201 /* if r1 not used then */
204 /* push it if not already pushed */
206 emitcode ("push","%s",
207 ds390_regWithIdx(R1_IDX)->dname);
211 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
212 (*aopp)->type = AOP_R1;
213 return ds390_regWithIdx(R1_IDX);
217 /* I said end of world but not quite end of world yet */
218 /* if this is a result then we can push it on the stack*/
220 (*aopp)->type = AOP_STK;
225 /* other wise this is true end of the world */
226 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
227 "getFreePtr should never reach here");
231 /*-----------------------------------------------------------------*/
232 /* newAsmop - creates a new asmOp */
233 /*-----------------------------------------------------------------*/
234 static asmop *newAsmop (short type)
238 ALLOC(aop,sizeof(asmop));
243 /* Turn this off if the world goes to hell. */
246 static int _currentDPS; /* Current processor DPS. */
247 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
248 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
250 /*-----------------------------------------------------------------*/
251 /* genSetDPTR: generate code to select which DPTR is in use (zero */
252 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
253 /* alternate DPTR (DPL1/DPH1/DPX1). */
254 /*-----------------------------------------------------------------*/
255 static void genSetDPTR(int n)
259 /* If we are doing lazy evaluation, simply note the desired
260 * change, but don't emit any code yet.
271 emitcode("mov", "dps, #0x00");
275 emitcode("mov", "dps, #0x01");
279 /*-----------------------------------------------------------------*/
280 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation*/
282 /* Any code that operates on DPTR (NB: not on the individual */
283 /* components, like DPH) *must* call _flushLazyDPS() before using */
284 /* DPTR within a lazy DPS evaluation block. */
286 /* Note that aopPut and aopGet already contain the proper calls to */
287 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
288 /* DPS evaluation block. */
290 /* Also, _flushLazyDPS must be called before any flow control */
291 /* operations that could potentially branch out of the block. */
293 /* Lazy DPS evaluation is simply an optimization (though an */
294 /* important one), so if in doubt, leave it out. */
295 /*-----------------------------------------------------------------*/
296 static void _startLazyDPSEvaluation(void)
303 /*-----------------------------------------------------------------*/
304 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
305 /* desired one. Call before using DPTR within a lazy DPS evaluation*/
307 /*-----------------------------------------------------------------*/
308 static void _flushLazyDPS(void)
316 if (_desiredDPS != _currentDPS)
320 emitcode("inc", "dps");
324 emitcode("dec", "dps");
326 _currentDPS = _desiredDPS;
330 /*-----------------------------------------------------------------*/
331 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
333 /* Forces us back to the safe state (standard DPTR selected). */
334 /*-----------------------------------------------------------------*/
335 static void _endLazyDPSEvaluation(void)
349 /*-----------------------------------------------------------------*/
350 /* pointerCode - returns the code for a pointer type */
351 /*-----------------------------------------------------------------*/
352 static int pointerCode (link *etype)
355 return PTR_TYPE(SPEC_OCLS(etype));
359 /*-----------------------------------------------------------------*/
360 /* aopForSym - for a true symbol */
361 /*-----------------------------------------------------------------*/
362 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
365 memmap *space= SPEC_OCLS(sym->etype);
367 /* if already has one */
371 /* assign depending on the storage class */
372 /* if it is on the stack or indirectly addressable */
373 /* space we need to assign either r0 or r1 to it */
374 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
375 sym->aop = aop = newAsmop(0);
376 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
377 aop->size = getSize(sym->type);
379 /* now assign the address of the variable to
380 the pointer register */
381 if (aop->type != AOP_STK) {
385 emitcode("push","acc");
387 emitcode("mov","a,_bp");
388 emitcode("add","a,#0x%02x",
390 ((char)(sym->stack - _G.nRegsSaved )) :
391 ((char)sym->stack)) & 0xff);
392 emitcode("mov","%s,a",
393 aop->aopu.aop_ptr->name);
396 emitcode("pop","acc");
398 emitcode("mov","%s,#%s",
399 aop->aopu.aop_ptr->name,
401 aop->paged = space->paged;
403 aop->aopu.aop_stk = sym->stack;
407 if (sym->onStack && options.stack10bit)
409 /* It's on the 10 bit stack, which is located in
414 emitcode("push","acc");
416 emitcode("mov","a,_bp");
417 emitcode("add","a,#0x%02x",
419 ((char)(sym->stack - _G.nRegsSaved )) :
420 ((char)sym->stack)) & 0xff);
425 emitcode ("mov","dpx1,#0x40");
426 emitcode ("mov","dph1,#0x00");
427 emitcode ("mov","dpl1, a");
432 emitcode ("mov","dpx,#0x40");
433 emitcode ("mov","dph,#0x00");
434 emitcode ("mov","dpl, a");
438 emitcode("pop","acc");
440 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
441 aop->size = getSize(sym->type);
445 /* if in bit space */
446 if (IN_BITSPACE(space)) {
447 sym->aop = aop = newAsmop (AOP_CRY);
448 aop->aopu.aop_dir = sym->rname ;
449 aop->size = getSize(sym->type);
452 /* if it is in direct space */
453 if (IN_DIRSPACE(space)) {
454 sym->aop = aop = newAsmop (AOP_DIR);
455 aop->aopu.aop_dir = sym->rname ;
456 aop->size = getSize(sym->type);
460 /* special case for a function */
461 if (IS_FUNC(sym->type)) {
462 sym->aop = aop = newAsmop(AOP_IMMD);
463 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
464 strcpy(aop->aopu.aop_immd,sym->rname);
465 aop->size = FPTRSIZE;
469 /* only remaining is far space */
470 /* in which case DPTR gets the address */
471 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
476 emitcode ("mov","dptr,#%s", sym->rname);
481 emitcode ("mov","dptr,#%s", sym->rname);
483 aop->size = getSize(sym->type);
485 /* if it is in code space */
486 if (IN_CODESPACE(space))
492 /*-----------------------------------------------------------------*/
493 /* aopForRemat - rematerialzes an object */
494 /*-----------------------------------------------------------------*/
495 static asmop *aopForRemat (symbol *sym)
497 iCode *ic = sym->rematiCode;
498 asmop *aop = newAsmop(AOP_IMMD);
504 val += operandLitValue(IC_RIGHT(ic));
505 else if (ic->op == '-')
506 val -= operandLitValue(IC_RIGHT(ic));
510 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
514 sprintf(buffer,"(%s %c 0x%04x)",
515 OP_SYMBOL(IC_LEFT(ic))->rname,
516 val >= 0 ? '+' : '-',
519 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
521 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
522 strcpy(aop->aopu.aop_immd,buffer);
526 /*-----------------------------------------------------------------*/
527 /* regsInCommon - two operands have some registers in common */
528 /*-----------------------------------------------------------------*/
529 static bool regsInCommon (operand *op1, operand *op2)
534 /* if they have registers in common */
535 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
538 sym1 = OP_SYMBOL(op1);
539 sym2 = OP_SYMBOL(op2);
541 if (sym1->nRegs == 0 || sym2->nRegs == 0)
544 for (i = 0 ; i < sym1->nRegs ; i++) {
549 for (j = 0 ; j < sym2->nRegs ;j++ ) {
553 if (sym2->regs[j] == sym1->regs[i])
561 /*-----------------------------------------------------------------*/
562 /* operandsEqu - equivalent */
563 /*-----------------------------------------------------------------*/
564 static bool operandsEqu ( operand *op1, operand *op2)
568 /* if they not symbols */
569 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
572 sym1 = OP_SYMBOL(op1);
573 sym2 = OP_SYMBOL(op2);
575 /* if both are itemps & one is spilt
576 and the other is not then false */
577 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
578 sym1->isspilt != sym2->isspilt )
581 /* if they are the same */
585 if (strcmp(sym1->rname,sym2->rname) == 0)
589 /* if left is a tmp & right is not */
593 (sym1->usl.spillLoc == sym2))
600 (sym2->usl.spillLoc == sym1))
606 /*-----------------------------------------------------------------*/
607 /* sameRegs - two asmops have the same registers */
608 /*-----------------------------------------------------------------*/
609 static bool sameRegs (asmop *aop1, asmop *aop2 )
615 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
622 if (aop1->type != AOP_REG ||
623 aop2->type != AOP_REG )
626 if (aop1->size != aop2->size )
629 for (i = 0 ; i < aop1->size ; i++ )
630 if (aop1->aopu.aop_reg[i] !=
631 aop2->aopu.aop_reg[i] )
637 /*-----------------------------------------------------------------*/
638 /* aopOp - allocates an asmop for an operand : */
639 /*-----------------------------------------------------------------*/
640 static void aopOp (operand *op, iCode *ic, bool result, bool useDP2)
649 /* if this a literal */
650 if (IS_OP_LITERAL(op)) {
651 op->aop = aop = newAsmop(AOP_LIT);
652 aop->aopu.aop_lit = op->operand.valOperand;
653 aop->size = getSize(operandType(op));
657 /* if already has a asmop then continue */
661 /* if the underlying symbol has a aop */
662 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
663 op->aop = OP_SYMBOL(op)->aop;
667 /* if this is a true symbol */
668 if (IS_TRUE_SYMOP(op)) {
669 op->aop = aopForSym(ic,OP_SYMBOL(op),result, useDP2);
673 /* this is a temporary : this has
679 e) can be a return use only */
684 /* if the type is a conditional */
685 if (sym->regType == REG_CND) {
686 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
691 /* if it is spilt then two situations
693 b) has a spill location */
694 if (sym->isspilt || sym->nRegs == 0) {
696 /* rematerialize it NOW */
698 sym->aop = op->aop = aop =
700 aop->size = getSize(sym->type);
706 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
707 aop->size = getSize(sym->type);
708 for ( i = 0 ; i < 2 ; i++ )
709 aop->aopu.aop_str[i] = accUse[i];
715 aop = op->aop = sym->aop = newAsmop(AOP_STR);
716 aop->size = getSize(sym->type);
717 for ( i = 0 ; i < fReturnSize_390 ; i++ )
718 aop->aopu.aop_str[i] = fReturn[i];
722 /* else spill location */
723 sym->aop = op->aop = aop =
724 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
725 aop->size = getSize(sym->type);
729 /* must be in a register */
730 sym->aop = op->aop = aop = newAsmop(AOP_REG);
731 aop->size = sym->nRegs;
732 for ( i = 0 ; i < sym->nRegs ;i++)
733 aop->aopu.aop_reg[i] = sym->regs[i];
736 /*-----------------------------------------------------------------*/
737 /* freeAsmop - free up the asmop given to an operand */
738 /*----------------------------------------------------------------*/
739 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
756 /* depending on the asmop type only three cases need work AOP_RO
757 , AOP_R1 && AOP_STK */
762 emitcode ("pop","ar0");
766 bitVectUnSetBit(ic->rUsed,R0_IDX);
772 emitcode ("pop","ar1");
776 bitVectUnSetBit(ic->rUsed,R1_IDX);
782 int stk = aop->aopu.aop_stk + aop->size;
783 bitVectUnSetBit(ic->rUsed,R0_IDX);
784 bitVectUnSetBit(ic->rUsed,R1_IDX);
786 getFreePtr(ic,&aop,FALSE);
788 if (options.stack10bit)
790 /* I'm not sure what to do here yet... */
793 "*** Warning: probably generating bad code for "
794 "10 bit stack mode.\n");
798 emitcode ("mov","a,_bp");
799 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
800 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
802 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
806 emitcode("pop","acc");
807 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
809 emitcode("dec","%s",aop->aopu.aop_ptr->name);
812 freeAsmop(op,NULL,ic,TRUE);
814 emitcode("pop","ar0");
819 emitcode("pop","ar1");
826 /* all other cases just dealloc */
830 OP_SYMBOL(op)->aop = NULL;
831 /* if the symbol has a spill */
833 SPIL_LOC(op)->aop = NULL;
838 /*------------------------------------------------------------------*/
839 /* aopGet - for fetching value of the aop */
841 /* Set canClobberACC if you are aure it is OK to clobber the value */
842 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe,*/
843 /* just less efficient. */
844 /*------------------------------------------------------------------*/
846 static char *aopGet (asmop *aop,
855 /* offset is greater than
857 if (offset > (aop->size - 1) &&
858 aop->type != AOP_LIT)
861 /* depending on type */
866 /* if we need to increment it */
867 while (offset > aop->coff) {
868 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
872 while (offset < aop->coff) {
873 emitcode("dec","%s",aop->aopu.aop_ptr->name);
879 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
880 return (dname ? "acc" : "a");
882 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
883 ALLOC_ATOMIC(rs,strlen(s)+1);
890 if (aop->type == AOP_DPTR2)
894 #ifndef KEVIN_BROKE_IT
898 emitcode("xch", "a, ap");
904 while (offset > aop->coff) {
905 emitcode ("inc","dptr");
909 while (offset < aop->coff) {
910 emitcode("lcall","__decdptr");
917 emitcode("movc","a,@a+dptr");
920 emitcode("movx","a,@dptr");
923 if (aop->type == AOP_DPTR2)
927 #ifndef KEVIN_BROKE_IT
931 emitcode("xch", "a, ap");
936 return (dname ? "acc" : "a");
940 sprintf (s,"#%s",aop->aopu.aop_immd);
943 sprintf(s,"#(%s >> %d)",
949 ALLOC_ATOMIC(rs,strlen(s)+1);
955 sprintf(s,"(%s + %d)",
959 sprintf(s,"%s",aop->aopu.aop_dir);
960 ALLOC_ATOMIC(rs,strlen(s)+1);
966 return aop->aopu.aop_reg[offset]->dname;
968 return aop->aopu.aop_reg[offset]->name;
972 emitcode("mov","c,%s",aop->aopu.aop_dir);
973 emitcode("rlc","a") ;
974 return (dname ? "acc" : "a");
977 if (!offset && dname)
979 return aop->aopu.aop_str[offset];
982 return aopLiteral (aop->aopu.aop_lit,offset);
986 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
990 return aop->aopu.aop_str[offset];
994 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
995 "aopget got unsupported aop->type");
998 /*-----------------------------------------------------------------*/
999 /* aopPut - puts a string for a aop */
1000 /*-----------------------------------------------------------------*/
1001 static void aopPut (asmop *aop, char *s, int offset)
1006 if (aop->size && offset > ( aop->size - 1)) {
1007 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1008 "aopPut got offset > aop->size");
1012 /* will assign value to value */
1013 /* depending on where it is ofcourse */
1014 switch (aop->type) {
1017 sprintf(d,"(%s + %d)",
1018 aop->aopu.aop_dir,offset);
1020 sprintf(d,"%s",aop->aopu.aop_dir);
1023 emitcode("mov","%s,%s",d,s);
1028 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1029 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1031 strcmp(s,"r0") == 0 ||
1032 strcmp(s,"r1") == 0 ||
1033 strcmp(s,"r2") == 0 ||
1034 strcmp(s,"r3") == 0 ||
1035 strcmp(s,"r4") == 0 ||
1036 strcmp(s,"r5") == 0 ||
1037 strcmp(s,"r6") == 0 ||
1038 strcmp(s,"r7") == 0 )
1039 emitcode("mov","%s,%s",
1040 aop->aopu.aop_reg[offset]->dname,s);
1042 emitcode("mov","%s,%s",
1043 aop->aopu.aop_reg[offset]->name,s);
1050 if (aop->type == AOP_DPTR2)
1057 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1058 "aopPut writting to code space");
1062 while (offset > aop->coff) {
1064 emitcode ("inc","dptr");
1067 while (offset < aop->coff) {
1069 emitcode("lcall","__decdptr");
1074 /* if not in accumulater */
1077 emitcode ("movx","@dptr,a");
1079 if (aop->type == AOP_DPTR2)
1087 while (offset > aop->coff) {
1089 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1091 while (offset < aop->coff) {
1093 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1099 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1104 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1106 if (strcmp(s,"r0") == 0 ||
1107 strcmp(s,"r1") == 0 ||
1108 strcmp(s,"r2") == 0 ||
1109 strcmp(s,"r3") == 0 ||
1110 strcmp(s,"r4") == 0 ||
1111 strcmp(s,"r5") == 0 ||
1112 strcmp(s,"r6") == 0 ||
1113 strcmp(s,"r7") == 0 ) {
1115 sprintf(buffer,"a%s",s);
1116 emitcode("mov","@%s,%s",
1117 aop->aopu.aop_ptr->name,buffer);
1119 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1124 if (strcmp(s,"a") == 0)
1125 emitcode("push","acc");
1127 emitcode("push","%s",s);
1132 /* if bit variable */
1133 if (!aop->aopu.aop_dir) {
1134 emitcode("clr","a");
1135 emitcode("rlc","a");
1138 emitcode("clr","%s",aop->aopu.aop_dir);
1141 emitcode("setb","%s",aop->aopu.aop_dir);
1144 emitcode("mov","%s,c",aop->aopu.aop_dir);
1146 lbl = newiTempLabel(NULL);
1148 if (strcmp(s,"a")) {
1151 emitcode("clr","c");
1152 emitcode("jz","%05d$",lbl->key+100);
1153 emitcode("cpl","c");
1154 emitcode("","%05d$:",lbl->key+100);
1155 emitcode("mov","%s,c",aop->aopu.aop_dir);
1162 if (strcmp(aop->aopu.aop_str[offset],s))
1163 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1168 if (!offset && (strcmp(s,"acc") == 0))
1171 if (strcmp(aop->aopu.aop_str[offset],s))
1172 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1176 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1177 "aopPut got unsupported aop->type");
1184 /*-----------------------------------------------------------------*/
1185 /* reAdjustPreg - points a register back to where it should */
1186 /*-----------------------------------------------------------------*/
1187 static void reAdjustPreg (asmop *aop)
1192 if ((size = aop->size) <= 1)
1195 switch (aop->type) {
1199 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1203 if (aop->type == AOP_DPTR2)
1210 emitcode("lcall","__decdptr");
1213 if (aop->type == AOP_DPTR2)
1223 #define AOP(op) op->aop
1224 #define AOP_TYPE(op) AOP(op)->type
1225 #define AOP_SIZE(op) AOP(op)->size
1226 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1227 AOP_TYPE(x) == AOP_R0))
1229 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1230 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1233 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1234 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1235 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1237 /* Workaround for DS80C390 bug: div ab may return bogus results
1238 * if A is accessed in instruction immediately before the div.
1240 * Will be fixed in B4 rev of processor, Dallas claims.
1243 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1244 if (!AOP_NEEDSACC(RIGHT)) \
1246 /* We can load A first, then B, since \
1247 * B (the RIGHT operand) won't clobber A, \
1248 * thus avoiding touching A right before the div. \
1250 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1251 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1253 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1257 /* Just stuff in a nop after loading A. */ \
1258 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1259 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1261 emitcode("nop", "; workaround for DS80C390 div bug."); \
1264 /*-----------------------------------------------------------------*/
1265 /* genNotFloat - generates not for float operations */
1266 /*-----------------------------------------------------------------*/
1267 static void genNotFloat (operand *op, operand *res)
1273 D(emitcode(";", "genNotFloat "););
1275 /* we will put 127 in the first byte of
1277 aopPut(AOP(res),"#127",0);
1278 size = AOP_SIZE(op) - 1;
1281 _startLazyDPSEvaluation();
1282 l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
1286 emitcode("orl","a,%s",
1288 offset++,FALSE,FALSE,FALSE));
1290 _endLazyDPSEvaluation();
1291 tlbl = newiTempLabel(NULL);
1293 tlbl = newiTempLabel(NULL);
1294 aopPut(res->aop,one,1);
1295 emitcode("jz","%05d$",(tlbl->key+100));
1296 aopPut(res->aop,zero,1);
1297 emitcode("","%05d$:",(tlbl->key+100));
1299 size = res->aop->size - 2;
1301 /* put zeros in the rest */
1303 aopPut(res->aop,zero,offset++);
1306 /*-----------------------------------------------------------------*/
1307 /* opIsGptr: returns non-zero if the passed operand is */
1308 /* a generic pointer type. */
1309 /*-----------------------------------------------------------------*/
1310 static int opIsGptr(operand *op)
1312 link *type = operandType(op);
1314 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1321 /*-----------------------------------------------------------------*/
1322 /* getDataSize - get the operand data size */
1323 /*-----------------------------------------------------------------*/
1324 static int getDataSize(operand *op)
1327 size = AOP_SIZE(op);
1328 if (size == GPTRSIZE)
1330 link *type = operandType(op);
1331 if (IS_GENPTR(type))
1333 /* generic pointer; arithmetic operations
1334 * should ignore the high byte (pointer type).
1342 /*-----------------------------------------------------------------*/
1343 /* outAcc - output Acc */
1344 /*-----------------------------------------------------------------*/
1345 static void outAcc(operand *result)
1348 size = getDataSize(result);
1350 aopPut(AOP(result),"a",0);
1353 /* unsigned or positive */
1355 aopPut(AOP(result),zero,offset++);
1360 /*-----------------------------------------------------------------*/
1361 /* outBitC - output a bit C */
1362 /*-----------------------------------------------------------------*/
1363 static void outBitC(operand *result)
1365 /* if the result is bit */
1366 if (AOP_TYPE(result) == AOP_CRY)
1367 aopPut(AOP(result),"c",0);
1369 emitcode("clr","a");
1370 emitcode("rlc","a");
1375 /*-----------------------------------------------------------------*/
1376 /* toBoolean - emit code for orl a,operator(sizeop) */
1377 /*-----------------------------------------------------------------*/
1378 static void toBoolean(operand *oper)
1380 int size = AOP_SIZE(oper) - 1;
1383 /* The generic part of a generic pointer should
1384 * not participate in it's truth value.
1386 * i.e. 0x10000000 is zero.
1390 D(emitcode(";", "toBoolean: generic ptr special case."););
1394 _startLazyDPSEvaluation();
1395 if (AOP_NEEDSACC(oper))
1397 emitcode("push", "b");
1398 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1402 MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1406 if (AOP_NEEDSACC(oper))
1408 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1412 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1415 _endLazyDPSEvaluation();
1417 if (AOP_NEEDSACC(oper))
1419 emitcode("mov", "a,b");
1420 emitcode("pop", "b");
1425 /*-----------------------------------------------------------------*/
1426 /* genNot - generate code for ! operation */
1427 /*-----------------------------------------------------------------*/
1428 static void genNot (iCode *ic)
1431 link *optype = operandType(IC_LEFT(ic));
1433 D(emitcode(";", "genNot "););
1435 /* assign asmOps to operand & result */
1436 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1437 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1439 /* if in bit space then a special case */
1440 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1441 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1442 emitcode("cpl","c");
1443 outBitC(IC_RESULT(ic));
1447 /* if type float then do float */
1448 if (IS_FLOAT(optype)) {
1449 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1453 toBoolean(IC_LEFT(ic));
1455 tlbl = newiTempLabel(NULL);
1456 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1457 emitcode("","%05d$:",tlbl->key+100);
1458 outBitC(IC_RESULT(ic));
1461 /* release the aops */
1462 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1463 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1467 /*-----------------------------------------------------------------*/
1468 /* genCpl - generate code for complement */
1469 /*-----------------------------------------------------------------*/
1470 static void genCpl (iCode *ic)
1475 D(emitcode(";", "genCpl "););
1478 /* assign asmOps to operand & result */
1479 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1480 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1482 /* if both are in bit space then
1484 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1485 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1487 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1488 emitcode("cpl","c");
1489 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1493 size = AOP_SIZE(IC_RESULT(ic));
1494 _startLazyDPSEvaluation();
1496 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1498 emitcode("cpl","a");
1499 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1501 _endLazyDPSEvaluation();
1505 /* release the aops */
1506 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1507 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1510 /*-----------------------------------------------------------------*/
1511 /* genUminusFloat - unary minus for floating points */
1512 /*-----------------------------------------------------------------*/
1513 static void genUminusFloat(operand *op,operand *result)
1515 int size ,offset =0 ;
1517 /* for this we just need to flip the
1518 first it then copy the rest in place */
1519 D(emitcode(";", "genUminusFloat"););
1521 _startLazyDPSEvaluation();
1522 size = AOP_SIZE(op) - 1;
1523 l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1526 emitcode("cpl","acc.7");
1527 aopPut(AOP(result),"a",3);
1531 aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1535 _endLazyDPSEvaluation();
1538 /*-----------------------------------------------------------------*/
1539 /* genUminus - unary minus code generation */
1540 /*-----------------------------------------------------------------*/
1541 static void genUminus (iCode *ic)
1544 link *optype, *rtype;
1546 D(emitcode(";", "genUminus "););
1550 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1551 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1553 /* if both in bit space then special
1555 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1556 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1558 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1559 emitcode("cpl","c");
1560 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1564 optype = operandType(IC_LEFT(ic));
1565 rtype = operandType(IC_RESULT(ic));
1567 /* if float then do float stuff */
1568 if (IS_FLOAT(optype)) {
1569 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1573 /* otherwise subtract from zero */
1574 size = AOP_SIZE(IC_LEFT(ic));
1576 _startLazyDPSEvaluation();
1578 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1579 if (!strcmp(l,"a")) {
1582 emitcode("cpl","a");
1583 emitcode("addc", "a,#0");
1587 emitcode("clr","a");
1588 emitcode("subb","a,%s",l);
1590 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1592 _endLazyDPSEvaluation();
1594 /* if any remaining bytes in the result */
1595 /* we just need to propagate the sign */
1596 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1597 emitcode("rlc","a");
1598 emitcode("subb","a,acc");
1600 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1604 /* release the aops */
1605 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1606 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1609 /*-----------------------------------------------------------------*/
1610 /* saveRegisters - will look for a call and save the registers */
1611 /*-----------------------------------------------------------------*/
1612 static void saveRegisters(iCode *lic)
1620 for (ic = lic ; ic ; ic = ic->next)
1621 if (ic->op == CALL || ic->op == PCALL)
1625 fprintf(stderr,"found parameter push with no function call\n");
1629 /* if the registers have been saved already then
1631 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1634 /* find the registers in use at this time
1635 and push them away to safety */
1636 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1640 if (options.useXstack) {
1641 if (bitVectBitValue(rsave,R0_IDX))
1642 emitcode("mov","b,r0");
1643 emitcode("mov","r0,%s",spname);
1644 for (i = 0 ; i < ds390_nRegs ; i++) {
1645 if (bitVectBitValue(rsave,i)) {
1647 emitcode("mov","a,b");
1649 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1650 emitcode("movx","@r0,a");
1651 emitcode("inc","r0");
1654 emitcode("mov","%s,r0",spname);
1655 if (bitVectBitValue(rsave,R0_IDX))
1656 emitcode("mov","r0,b");
1658 for (i = 0 ; i < ds390_nRegs ; i++) {
1659 if (bitVectBitValue(rsave,i))
1660 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1663 detype = getSpec(operandType(IC_LEFT(ic)));
1665 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1666 IS_ISR(currFunc->etype) &&
1669 saverbank(SPEC_BANK(detype),ic,TRUE);
1672 /*-----------------------------------------------------------------*/
1673 /* unsaveRegisters - pop the pushed registers */
1674 /*-----------------------------------------------------------------*/
1675 static void unsaveRegisters (iCode *ic)
1679 /* find the registers in use at this time
1680 and push them away to safety */
1681 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1684 if (options.useXstack) {
1685 emitcode("mov","r0,%s",spname);
1686 for (i = ds390_nRegs ; i >= 0 ; i--) {
1687 if (bitVectBitValue(rsave,i)) {
1688 emitcode("dec","r0");
1689 emitcode("movx","a,@r0");
1691 emitcode("mov","b,a");
1693 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1697 emitcode("mov","%s,r0",spname);
1698 if (bitVectBitValue(rsave,R0_IDX))
1699 emitcode("mov","r0,b");
1701 for (i = ds390_nRegs ; i >= 0 ; i--) {
1702 if (bitVectBitValue(rsave,i))
1703 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1709 /*-----------------------------------------------------------------*/
1711 /*-----------------------------------------------------------------*/
1712 static void pushSide(operand * oper, int size)
1715 _startLazyDPSEvaluation();
1717 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1718 if (AOP_TYPE(oper) != AOP_REG &&
1719 AOP_TYPE(oper) != AOP_DIR &&
1721 emitcode("mov","a,%s",l);
1722 emitcode("push","acc");
1724 emitcode("push","%s",l);
1726 _endLazyDPSEvaluation();
1729 /*-----------------------------------------------------------------*/
1730 /* assignResultValue - */
1731 /*-----------------------------------------------------------------*/
1732 static void assignResultValue(operand * oper)
1735 int size = AOP_SIZE(oper);
1737 _startLazyDPSEvaluation();
1739 aopPut(AOP(oper),fReturn[offset],offset);
1742 _endLazyDPSEvaluation();
1746 /*-----------------------------------------------------------------*/
1747 /* genXpush - pushes onto the external stack */
1748 /*-----------------------------------------------------------------*/
1749 static void genXpush (iCode *ic)
1751 asmop *aop = newAsmop(0);
1753 int size,offset = 0;
1755 D(emitcode(";", "genXpush "););
1757 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1758 r = getFreePtr(ic,&aop,FALSE);
1761 emitcode("mov","%s,_spx",r->name);
1763 size = AOP_SIZE(IC_LEFT(ic));
1764 _startLazyDPSEvaluation();
1767 char *l = aopGet(AOP(IC_LEFT(ic)),
1768 offset++,FALSE,FALSE,TRUE);
1770 emitcode("movx","@%s,a",r->name);
1771 emitcode("inc","%s",r->name);
1774 _endLazyDPSEvaluation();
1777 emitcode("mov","_spx,%s",r->name);
1779 freeAsmop(NULL,aop,ic,TRUE);
1780 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1783 /*-----------------------------------------------------------------*/
1784 /* genIpush - genrate code for pushing this gets a little complex */
1785 /*-----------------------------------------------------------------*/
1786 static void genIpush (iCode *ic)
1788 int size, offset = 0 ;
1791 D(emitcode(";", "genIpush "););
1794 /* if this is not a parm push : ie. it is spill push
1795 and spill push is always done on the local stack */
1796 if (!ic->parmPush) {
1798 /* and the item is spilt then do nothing */
1799 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1802 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1803 size = AOP_SIZE(IC_LEFT(ic));
1804 /* push it on the stack */
1805 _startLazyDPSEvaluation();
1807 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1812 emitcode("push","%s",l);
1814 _endLazyDPSEvaluation();
1818 /* this is a paramter push: in this case we call
1819 the routine to find the call and save those
1820 registers that need to be saved */
1823 /* if use external stack then call the external
1824 stack pushing routine */
1825 if (options.useXstack) {
1830 /* then do the push */
1831 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1833 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1834 size = AOP_SIZE(IC_LEFT(ic));
1836 _startLazyDPSEvaluation();
1838 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1839 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1840 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1842 emitcode("mov","a,%s",l);
1843 emitcode("push","acc");
1845 emitcode("push","%s",l);
1847 _endLazyDPSEvaluation();
1849 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1852 /*-----------------------------------------------------------------*/
1853 /* genIpop - recover the registers: can happen only for spilling */
1854 /*-----------------------------------------------------------------*/
1855 static void genIpop (iCode *ic)
1859 D(emitcode(";", "genIpop "););
1862 /* if the temp was not pushed then */
1863 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1866 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1867 size = AOP_SIZE(IC_LEFT(ic));
1869 _startLazyDPSEvaluation();
1872 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1875 _endLazyDPSEvaluation();
1877 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1880 /*-----------------------------------------------------------------*/
1881 /* unsaverbank - restores the resgister bank from stack */
1882 /*-----------------------------------------------------------------*/
1883 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1890 if (options.useXstack) {
1892 r = getFreePtr(ic,&aop,FALSE);
1895 emitcode("mov","%s,_spx",r->name);
1896 emitcode("movx","a,@%s",r->name);
1897 emitcode("mov","psw,a");
1898 emitcode("dec","%s",r->name);
1901 emitcode ("pop","psw");
1904 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1905 if (options.useXstack) {
1906 emitcode("movx","a,@%s",r->name);
1907 emitcode("mov","(%s+%d),a",
1908 regs390[i].base,8*bank+regs390[i].offset);
1909 emitcode("dec","%s",r->name);
1912 emitcode("pop","(%s+%d)",
1913 regs390[i].base,8*bank+regs390[i].offset);
1916 if (options.useXstack) {
1918 emitcode("mov","_spx,%s",r->name);
1919 freeAsmop(NULL,aop,ic,TRUE);
1924 /*-----------------------------------------------------------------*/
1925 /* saverbank - saves an entire register bank on the stack */
1926 /*-----------------------------------------------------------------*/
1927 static void saverbank (int bank, iCode *ic, bool pushPsw)
1933 if (options.useXstack) {
1936 r = getFreePtr(ic,&aop,FALSE);
1937 emitcode("mov","%s,_spx",r->name);
1941 for (i = 0 ; i < ds390_nRegs ;i++) {
1942 if (options.useXstack) {
1943 emitcode("inc","%s",r->name);
1944 emitcode("mov","a,(%s+%d)",
1945 regs390[i].base,8*bank+regs390[i].offset);
1946 emitcode("movx","@%s,a",r->name);
1948 emitcode("push","(%s+%d)",
1949 regs390[i].base,8*bank+regs390[i].offset);
1953 if (options.useXstack) {
1954 emitcode("mov","a,psw");
1955 emitcode("movx","@%s,a",r->name);
1956 emitcode("inc","%s",r->name);
1957 emitcode("mov","_spx,%s",r->name);
1958 freeAsmop (NULL,aop,ic,TRUE);
1961 emitcode("push","psw");
1963 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1969 /*-----------------------------------------------------------------*/
1970 /* genCall - generates a call statement */
1971 /*-----------------------------------------------------------------*/
1972 static void genCall (iCode *ic)
1976 D(emitcode(";", "genCall "););
1978 /* if caller saves & we have not saved then */
1982 /* if we are calling a function that is not using
1983 the same register bank then we need to save the
1984 destination registers on the stack */
1985 detype = getSpec(operandType(IC_LEFT(ic)));
1987 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1988 IS_ISR(currFunc->etype) &&
1991 saverbank(SPEC_BANK(detype),ic,TRUE);
1993 /* if send set is not empty the assign */
1997 for (sic = setFirstItem(_G.sendSet) ; sic ;
1998 sic = setNextItem(_G.sendSet))
2000 int size, offset = 0;
2002 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
2003 size = AOP_SIZE(IC_LEFT(sic));
2005 _startLazyDPSEvaluation();
2007 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2008 FALSE, FALSE, TRUE);
2009 if (strcmp(l,fReturn[offset]))
2010 emitcode("mov","%s,%s",
2015 _endLazyDPSEvaluation();
2016 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2021 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2022 OP_SYMBOL(IC_LEFT(ic))->rname :
2023 OP_SYMBOL(IC_LEFT(ic))->name));
2025 /* if we need assign a result value */
2026 if ((IS_ITEMP(IC_RESULT(ic)) &&
2027 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2028 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2029 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2032 /* Not really related to LAZY_DPS_OPT, but don't want
2033 * another testing flag right now...
2035 #define FAR_RETURN_OPT
2036 #ifdef FAR_RETURN_OPT
2037 if (isOperandInFarSpace(IC_RESULT(ic))
2038 && getSize(operandType(IC_RESULT(ic))) <= 2)
2040 int size = getSize(operandType(IC_RESULT(ic)));
2042 /* Special case for 1 or 2 byte return in far space. */
2043 emitcode(";", "Kevin function call abuse #1");
2048 emitcode("mov", "b,%s", fReturn[1]);
2051 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2052 aopPut(AOP(IC_RESULT(ic)),"a",0);
2056 aopPut(AOP(IC_RESULT(ic)),"b",1);
2058 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2064 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2067 assignResultValue(IC_RESULT(ic));
2069 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2072 if (!isOperandInFarSpace(IC_RESULT(ic)))
2075 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2078 assignResultValue(IC_RESULT(ic));
2080 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2084 /* Result is in far space, and requires DPTR to access
2085 * it. Push the result onto the stack and restore from
2088 int size = getSize(operandType(IC_RESULT(ic)));
2089 int offset = size - 1;
2092 emitcode(";", "Kevin function call abuse #1");
2094 /* first push the right side on to the stack */
2095 /* NB: this relies on the fact that "a" is the last
2096 * register in fReturn. If it were not, the MOVA
2097 * would potentially clobber a returned byte in A.
2100 l = fReturn[offset--];
2102 emitcode ("push","acc");
2105 /* now assign DPTR to result */
2106 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2107 size = AOP_SIZE(IC_RESULT(ic));
2108 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
2110 emitcode ("pop","acc");
2111 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
2113 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2118 /* adjust the stack for parameters if
2120 if (IC_LEFT(ic)->parmBytes) {
2122 if (IC_LEFT(ic)->parmBytes > 3) {
2123 emitcode("mov","a,%s",spname);
2124 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2125 emitcode("mov","%s,a",spname);
2127 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2128 emitcode("dec","%s",spname);
2132 /* if register bank was saved then pop them */
2134 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2136 /* if we hade saved some registers then unsave them */
2137 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2138 unsaveRegisters (ic);
2143 /*-----------------------------------------------------------------*/
2144 /* genPcall - generates a call by pointer statement */
2145 /*-----------------------------------------------------------------*/
2146 static void genPcall (iCode *ic)
2149 symbol *rlbl = newiTempLabel(NULL);
2151 D(emitcode(";", "genPcall "););
2154 /* if caller saves & we have not saved then */
2158 /* if we are calling a function that is not using
2159 the same register bank then we need to save the
2160 destination registers on the stack */
2161 detype = getSpec(operandType(IC_LEFT(ic)));
2163 IS_ISR(currFunc->etype) &&
2164 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2165 saverbank(SPEC_BANK(detype),ic,TRUE);
2168 /* push the return address on to the stack */
2169 emitcode("mov","a,#%05d$",(rlbl->key+100));
2170 emitcode("push","acc");
2171 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2172 emitcode("push","acc");
2174 if (options.model == MODEL_FLAT24)
2176 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2177 emitcode("push","acc");
2180 /* now push the calling address */
2181 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2183 pushSide(IC_LEFT(ic), FPTRSIZE);
2185 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2187 /* if send set is not empty the assign */
2191 for (sic = setFirstItem(_G.sendSet) ; sic ;
2192 sic = setNextItem(_G.sendSet))
2194 int size, offset = 0;
2196 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2197 size = AOP_SIZE(IC_LEFT(sic));
2198 _startLazyDPSEvaluation();
2201 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2203 if (strcmp(l,fReturn[offset]))
2205 emitcode("mov","%s,%s",
2211 _endLazyDPSEvaluation();
2212 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2218 emitcode("","%05d$:",(rlbl->key+100));
2221 /* if we need assign a result value */
2222 if ((IS_ITEMP(IC_RESULT(ic)) &&
2223 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2224 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2225 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2228 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2231 assignResultValue(IC_RESULT(ic));
2233 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2236 /* adjust the stack for parameters if
2238 if (IC_LEFT(ic)->parmBytes) {
2240 if (IC_LEFT(ic)->parmBytes > 3) {
2241 emitcode("mov","a,%s",spname);
2242 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2243 emitcode("mov","%s,a",spname);
2245 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2246 emitcode("dec","%s",spname);
2250 /* if register bank was saved then unsave them */
2252 (SPEC_BANK(currFunc->etype) !=
2254 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2256 /* if we hade saved some registers then
2259 unsaveRegisters (ic);
2263 /*-----------------------------------------------------------------*/
2264 /* resultRemat - result is rematerializable */
2265 /*-----------------------------------------------------------------*/
2266 static int resultRemat (iCode *ic)
2268 if (SKIP_IC(ic) || ic->op == IFX)
2271 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2272 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2273 if (sym->remat && !POINTER_SET(ic))
2281 #define STRCASECMP stricmp
2283 #define STRCASECMP strcasecmp
2286 /*-----------------------------------------------------------------*/
2287 /* inExcludeList - return 1 if the string is in exclude Reg list */
2288 /*-----------------------------------------------------------------*/
2289 static bool inExcludeList(char *s)
2293 if (options.excludeRegs[i] &&
2294 STRCASECMP(options.excludeRegs[i],"none") == 0)
2297 for ( i = 0 ; options.excludeRegs[i]; i++) {
2298 if (options.excludeRegs[i] &&
2299 STRCASECMP(s,options.excludeRegs[i]) == 0)
2305 /*-----------------------------------------------------------------*/
2306 /* genFunction - generated code for function entry */
2307 /*-----------------------------------------------------------------*/
2308 static void genFunction (iCode *ic)
2313 D(emitcode(";", "genFunction "););
2316 /* create the function header */
2317 emitcode(";","-----------------------------------------");
2318 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2319 emitcode(";","-----------------------------------------");
2321 emitcode("","%s:",sym->rname);
2322 fetype = getSpec(operandType(IC_LEFT(ic)));
2324 /* if critical function then turn interrupts off */
2325 if (SPEC_CRTCL(fetype))
2326 emitcode("clr","ea");
2328 /* here we need to generate the equates for the
2329 register bank if required */
2330 if (SPEC_BANK(fetype) != rbank) {
2333 rbank = SPEC_BANK(fetype);
2334 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2335 if (strcmp(regs390[i].base,"0") == 0)
2336 emitcode("","%s = 0x%02x",
2338 8*rbank+regs390[i].offset);
2340 emitcode ("","%s = %s + 0x%02x",
2343 8*rbank+regs390[i].offset);
2347 /* if this is an interrupt service routine then
2348 save acc, b, dpl, dph */
2349 if (IS_ISR(sym->etype)) {
2351 if (!inExcludeList("acc"))
2352 emitcode ("push","acc");
2353 if (!inExcludeList("b"))
2354 emitcode ("push","b");
2355 if (!inExcludeList("dpl"))
2356 emitcode ("push","dpl");
2357 if (!inExcludeList("dph"))
2358 emitcode ("push","dph");
2359 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2361 emitcode ("push", "dpx");
2362 /* Make sure we're using standard DPTR */
2363 emitcode ("push", "dps");
2364 emitcode ("mov", "dps, #0x00");
2365 if (options.stack10bit)
2367 /* This ISR could conceivably use DPTR2. Better save it. */
2368 emitcode ("push", "dpl1");
2369 emitcode ("push", "dph1");
2370 emitcode ("push", "dpx1");
2371 emitcode ("push", "ap");
2374 /* if this isr has no bank i.e. is going to
2375 run with bank 0 , then we need to save more
2377 if (!SPEC_BANK(sym->etype)) {
2379 /* if this function does not call any other
2380 function then we can be economical and
2381 save only those registers that are used */
2382 if (! sym->hasFcall) {
2385 /* if any registers used */
2386 if (sym->regsUsed) {
2387 /* save the registers used */
2388 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2389 if (bitVectBitValue(sym->regsUsed,i) ||
2390 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2391 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2396 /* this function has a function call cannot
2397 determines register usage so we will have the
2399 saverbank(0,ic,FALSE);
2403 /* if callee-save to be used for this function
2404 then save the registers being used in this function */
2405 if (sym->calleeSave) {
2408 /* if any registers used */
2409 if (sym->regsUsed) {
2410 /* save the registers used */
2411 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2412 if (bitVectBitValue(sym->regsUsed,i) ||
2413 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2414 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2422 /* set the register bank to the desired value */
2423 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2424 emitcode("push","psw");
2425 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2428 if (IS_RENT(sym->etype) || options.stackAuto) {
2430 if (options.useXstack) {
2431 emitcode("mov","r0,%s",spname);
2432 emitcode("mov","a,_bp");
2433 emitcode("movx","@r0,a");
2434 emitcode("inc","%s",spname);
2438 /* set up the stack */
2439 emitcode ("push","_bp"); /* save the callers stack */
2441 emitcode ("mov","_bp,%s",spname);
2444 /* adjust the stack for the function */
2449 werror(W_STACK_OVERFLOW,sym->name);
2451 if (i > 3 && sym->recvSize < 4) {
2453 emitcode ("mov","a,sp");
2454 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2455 emitcode ("mov","sp,a");
2460 emitcode("inc","sp");
2465 emitcode ("mov","a,_spx");
2466 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2467 emitcode ("mov","_spx,a");
2472 /*-----------------------------------------------------------------*/
2473 /* genEndFunction - generates epilogue for functions */
2474 /*-----------------------------------------------------------------*/
2475 static void genEndFunction (iCode *ic)
2477 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2479 D(emitcode(";", "genEndFunction "););
2481 if (IS_RENT(sym->etype) || options.stackAuto)
2483 emitcode ("mov","%s,_bp",spname);
2486 /* if use external stack but some variables were
2487 added to the local stack then decrement the
2489 if (options.useXstack && sym->stack) {
2490 emitcode("mov","a,sp");
2491 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2492 emitcode("mov","sp,a");
2496 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2497 if (options.useXstack) {
2498 emitcode("mov","r0,%s",spname);
2499 emitcode("movx","a,@r0");
2500 emitcode("mov","_bp,a");
2501 emitcode("dec","%s",spname);
2505 emitcode ("pop","_bp");
2509 /* restore the register bank */
2510 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2511 emitcode ("pop","psw");
2513 if (IS_ISR(sym->etype)) {
2515 /* now we need to restore the registers */
2516 /* if this isr has no bank i.e. is going to
2517 run with bank 0 , then we need to save more
2519 if (!SPEC_BANK(sym->etype)) {
2521 /* if this function does not call any other
2522 function then we can be economical and
2523 save only those registers that are used */
2524 if (! sym->hasFcall) {
2527 /* if any registers used */
2528 if (sym->regsUsed) {
2529 /* save the registers used */
2530 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2531 if (bitVectBitValue(sym->regsUsed,i) ||
2532 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2533 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2538 /* this function has a function call cannot
2539 determines register usage so we will have the
2541 unsaverbank(0,ic,FALSE);
2545 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2547 if (options.stack10bit)
2549 emitcode ("pop", "ap");
2550 emitcode ("pop", "dpx1");
2551 emitcode ("pop", "dph1");
2552 emitcode ("pop", "dpl1");
2554 emitcode ("pop", "dps");
2555 emitcode ("pop", "dpx");
2557 if (!inExcludeList("dph"))
2558 emitcode ("pop","dph");
2559 if (!inExcludeList("dpl"))
2560 emitcode ("pop","dpl");
2561 if (!inExcludeList("b"))
2562 emitcode ("pop","b");
2563 if (!inExcludeList("acc"))
2564 emitcode ("pop","acc");
2566 if (SPEC_CRTCL(sym->etype))
2567 emitcode("setb","ea");
2569 /* if debug then send end of function */
2570 /* if (options.debug && currFunc) { */
2573 emitcode("","C$%s$%d$%d$%d ==.",
2574 ic->filename,currFunc->lastLine,
2575 ic->level,ic->block);
2576 if (IS_STATIC(currFunc->etype))
2577 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2579 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2583 emitcode ("reti","");
2586 if (SPEC_CRTCL(sym->etype))
2587 emitcode("setb","ea");
2589 if (sym->calleeSave) {
2592 /* if any registers used */
2593 if (sym->regsUsed) {
2594 /* save the registers used */
2595 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2596 if (bitVectBitValue(sym->regsUsed,i) ||
2597 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2598 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2604 /* if debug then send end of function */
2607 emitcode("","C$%s$%d$%d$%d ==.",
2608 ic->filename,currFunc->lastLine,
2609 ic->level,ic->block);
2610 if (IS_STATIC(currFunc->etype))
2611 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2613 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2617 emitcode ("ret","");
2622 /*-----------------------------------------------------------------*/
2623 /* genRet - generate code for return statement */
2624 /*-----------------------------------------------------------------*/
2625 static void genRet (iCode *ic)
2627 int size,offset = 0 , pushed = 0;
2629 D(emitcode(";", "genRet "););
2631 /* if we have no return value then
2632 just generate the "ret" */
2636 /* we have something to return then
2637 move the return value into place */
2638 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2639 size = AOP_SIZE(IC_LEFT(ic));
2641 _startLazyDPSEvaluation();
2644 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2645 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2647 emitcode("push","%s",l);
2650 l = aopGet(AOP(IC_LEFT(ic)),offset,
2652 if (strcmp(fReturn[offset],l))
2653 emitcode("mov","%s,%s",fReturn[offset++],l);
2656 _endLazyDPSEvaluation();
2661 if (strcmp(fReturn[pushed],"a"))
2662 emitcode("pop",fReturn[pushed]);
2664 emitcode("pop","acc");
2667 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2670 /* generate a jump to the return label
2671 if the next is not the return statement */
2672 if (!(ic->next && ic->next->op == LABEL &&
2673 IC_LABEL(ic->next) == returnLabel))
2675 emitcode("ljmp","%05d$",(returnLabel->key+100));
2679 /*-----------------------------------------------------------------*/
2680 /* genLabel - generates a label */
2681 /*-----------------------------------------------------------------*/
2682 static void genLabel (iCode *ic)
2684 /* special case never generate */
2685 if (IC_LABEL(ic) == entryLabel)
2688 D(emitcode(";", "genLabel "););
2690 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2693 /*-----------------------------------------------------------------*/
2694 /* genGoto - generates a ljmp */
2695 /*-----------------------------------------------------------------*/
2696 static void genGoto (iCode *ic)
2698 D(emitcode(";", "genGoto "););
2699 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2702 /*-----------------------------------------------------------------*/
2703 /* findLabelBackwards: walks back through the iCode chain looking */
2704 /* for the given label. Returns number of iCode instructions */
2705 /* between that label and given ic. */
2706 /* Returns zero if label not found. */
2707 /*-----------------------------------------------------------------*/
2708 static int findLabelBackwards(iCode *ic, int key)
2717 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2719 /* printf("findLabelBackwards = %d\n", count); */
2727 /*-----------------------------------------------------------------*/
2728 /* genPlusIncr :- does addition with increment if possible */
2729 /*-----------------------------------------------------------------*/
2730 static bool genPlusIncr (iCode *ic)
2732 unsigned int icount ;
2733 unsigned int size = getDataSize(IC_RESULT(ic));
2735 /* will try to generate an increment */
2736 /* if the right side is not a literal
2738 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2741 /* if the literal value of the right hand side
2742 is greater than 4 then it is not worth it */
2743 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2746 /* if increment 16 bits in register */
2748 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2749 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2750 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2757 /* If the next instruction is a goto and the goto target
2758 * is <= 5 instructions previous to this, we can generate
2759 * jumps straight to that target.
2761 if (ic->next && ic->next->op == GOTO
2762 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2763 && labelRange <= 5 )
2765 emitcode(";", "tail increment optimized (range %d)", labelRange);
2766 tlbl = IC_LABEL(ic->next);
2771 tlbl = newiTempLabel(NULL);
2774 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2775 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2776 IS_AOP_PREG(IC_RESULT(ic)))
2777 emitcode("cjne","%s,#0x00,%05d$"
2778 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2781 emitcode("clr","a");
2782 emitcode("cjne","a,%s,%05d$"
2783 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2787 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2790 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2791 IS_AOP_PREG(IC_RESULT(ic)))
2792 emitcode("cjne","%s,#0x00,%05d$"
2793 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2796 emitcode("cjne","a,%s,%05d$"
2797 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2800 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2804 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2805 IS_AOP_PREG(IC_RESULT(ic)))
2806 emitcode("cjne","%s,#0x00,%05d$"
2807 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2810 emitcode("cjne","a,%s,%05d$"
2811 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2814 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2819 emitcode("","%05d$:",tlbl->key+100);
2824 /* if the sizes are greater than 1 then we cannot */
2825 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2826 AOP_SIZE(IC_LEFT(ic)) > 1 )
2829 /* we can if the aops of the left & result match or
2830 if they are in registers and the registers are the
2833 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2834 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2835 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2838 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2839 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2840 aopPut(AOP(IC_RESULT(ic)),"a",0);
2843 _startLazyDPSEvaluation();
2846 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2848 _endLazyDPSEvaluation();
2857 /*-----------------------------------------------------------------*/
2858 /* outBitAcc - output a bit in acc */
2859 /*-----------------------------------------------------------------*/
2860 static void outBitAcc(operand *result)
2862 symbol *tlbl = newiTempLabel(NULL);
2863 /* if the result is a bit */
2864 if (AOP_TYPE(result) == AOP_CRY){
2865 aopPut(AOP(result),"a",0);
2868 emitcode("jz","%05d$",tlbl->key+100);
2869 emitcode("mov","a,%s",one);
2870 emitcode("","%05d$:",tlbl->key+100);
2875 /*-----------------------------------------------------------------*/
2876 /* genPlusBits - generates code for addition of two bits */
2877 /*-----------------------------------------------------------------*/
2878 static void genPlusBits (iCode *ic)
2880 D(emitcode(";", "genPlusBits "););
2881 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2882 symbol *lbl = newiTempLabel(NULL);
2883 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2884 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2885 emitcode("cpl","c");
2886 emitcode("","%05d$:",(lbl->key+100));
2887 outBitC(IC_RESULT(ic));
2890 emitcode("clr","a");
2891 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2892 emitcode("rlc","a");
2893 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2894 emitcode("addc","a,#0x00");
2895 outAcc(IC_RESULT(ic));
2899 static void adjustArithmeticResult(iCode *ic)
2901 if (opIsGptr(IC_RESULT(ic)) &&
2902 opIsGptr(IC_LEFT(ic)) &&
2903 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2905 aopPut(AOP(IC_RESULT(ic)),
2906 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2910 if (opIsGptr(IC_RESULT(ic)) &&
2911 opIsGptr(IC_RIGHT(ic)) &&
2912 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2914 aopPut(AOP(IC_RESULT(ic)),
2915 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2919 if (opIsGptr(IC_RESULT(ic)) &&
2920 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2921 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2922 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2923 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2925 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2926 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2930 #define AOP_OP_3(ic) \
2931 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2932 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2933 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2934 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2935 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2937 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2939 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2942 #define AOP_SET_LOCALS(ic) \
2943 left = IC_LEFT(ic); \
2944 right = IC_RIGHT(ic); \
2945 result = IC_RESULT(ic);
2947 /*-----------------------------------------------------------------*/
2948 /* genPlus - generates code for addition */
2949 /*-----------------------------------------------------------------*/
2950 static void genPlus (iCode *ic)
2952 int size, offset = 0;
2953 bool pushResult = FALSE;
2956 D(emitcode(";", "genPlus "););
2958 /* special cases :- */
2961 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2962 aopOp (IC_LEFT(ic),ic,FALSE,
2963 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
2965 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2966 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2968 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2969 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2975 aopOp (IC_RESULT(ic),ic,TRUE,
2976 ((AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)
2977 || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR)));
2979 /* if literal, literal on the right or
2980 if left requires ACC or right is already
2982 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2983 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2984 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2985 operand *t = IC_RIGHT(ic);
2986 IC_RIGHT(ic) = IC_LEFT(ic);
2990 /* if both left & right are in bit
2992 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2993 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2998 /* if left in bit space & right literal */
2999 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3000 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3001 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3002 /* if result in bit space */
3003 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3004 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
3005 emitcode("cpl","c");
3006 outBitC(IC_RESULT(ic));
3008 size = getDataSize(IC_RESULT(ic));
3009 _startLazyDPSEvaluation();
3011 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3012 emitcode("addc","a,#00");
3013 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3015 _endLazyDPSEvaluation();
3020 /* if I can do an increment instead
3021 of add then GOOD for ME */
3022 if (genPlusIncr (ic) == TRUE)
3026 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3028 _startLazyDPSEvaluation();
3031 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3033 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3035 emitcode("add","a,%s",
3036 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3038 emitcode("addc","a,%s",
3039 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3041 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3043 emitcode("add","a,%s",
3044 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3046 emitcode("addc","a,%s",
3047 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3051 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3055 emitcode("push", "acc");
3059 _endLazyDPSEvaluation();
3063 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3065 size = getDataSize(IC_LEFT(ic));
3066 rSize = getDataSize(IC_RESULT(ic));
3068 /* If the pushed data is bigger than the result,
3069 * simply discard unused bytes. Icky, but works.
3071 * Should we throw a warning here? We're losing data...
3073 while (size > rSize)
3075 D(emitcode(";", "discarding unused result byte."););
3076 emitcode("pop", "acc");
3082 emitcode("clr", "a");
3083 /* Conversly, we haven't pushed enough here.
3084 * just zero-pad, and all is well.
3086 while (size < rSize)
3088 emitcode("push", "acc");
3094 _startLazyDPSEvaluation();
3097 emitcode("pop", "acc");
3098 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3100 _endLazyDPSEvaluation();
3103 adjustArithmeticResult(ic);
3106 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3107 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3108 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3111 /*-----------------------------------------------------------------*/
3112 /* genMinusDec :- does subtraction with deccrement if possible */
3113 /*-----------------------------------------------------------------*/
3114 static bool genMinusDec (iCode *ic)
3116 unsigned int icount ;
3117 unsigned int size = getDataSize(IC_RESULT(ic));
3119 /* will try to generate an increment */
3120 /* if the right side is not a literal
3122 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3125 /* if the literal value of the right hand side
3126 is greater than 4 then it is not worth it */
3127 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3130 /* if decrement 16 bits in register */
3131 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3132 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3133 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3140 /* If the next instruction is a goto and the goto target
3141 * is <= 5 instructions previous to this, we can generate
3142 * jumps straight to that target.
3144 if (ic->next && ic->next->op == GOTO
3145 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3146 && labelRange <= 5 )
3148 emitcode(";", "tail decrement optimized (range %d)", labelRange);
3149 tlbl = IC_LABEL(ic->next);
3154 tlbl = newiTempLabel(NULL);
3158 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3159 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3160 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3161 IS_AOP_PREG(IC_RESULT(ic)))
3162 emitcode("cjne","%s,#0xff,%05d$"
3163 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3166 emitcode("mov","a,#0xff");
3167 emitcode("cjne","a,%s,%05d$"
3168 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3171 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3174 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3175 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3176 IS_AOP_PREG(IC_RESULT(ic)))
3177 emitcode("cjne","%s,#0xff,%05d$"
3178 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3181 emitcode("cjne","a,%s,%05d$"
3182 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3185 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3189 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3190 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3191 IS_AOP_PREG(IC_RESULT(ic)))
3192 emitcode("cjne","%s,#0xff,%05d$"
3193 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3196 emitcode("cjne","a,%s,%05d$"
3197 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3200 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3204 emitcode("","%05d$:",tlbl->key+100);
3209 /* if the sizes are greater than 1 then we cannot */
3210 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3211 AOP_SIZE(IC_LEFT(ic)) > 1 )
3214 /* we can if the aops of the left & result match or
3215 if they are in registers and the registers are the
3218 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3219 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3220 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3222 _startLazyDPSEvaluation();
3225 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3227 _endLazyDPSEvaluation();
3235 /*-----------------------------------------------------------------*/
3236 /* addSign - complete with sign */
3237 /*-----------------------------------------------------------------*/
3238 static void addSign(operand *result, int offset, int sign)
3240 int size = (getDataSize(result) - offset);
3243 emitcode("rlc","a");
3244 emitcode("subb","a,acc");
3246 aopPut(AOP(result),"a",offset++);
3249 aopPut(AOP(result),zero,offset++);
3253 /*-----------------------------------------------------------------*/
3254 /* genMinusBits - generates code for subtraction of two bits */
3255 /*-----------------------------------------------------------------*/
3256 static void genMinusBits (iCode *ic)
3258 symbol *lbl = newiTempLabel(NULL);
3260 D(emitcode(";", "genMinusBits "););
3262 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3263 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3264 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3265 emitcode("cpl","c");
3266 emitcode("","%05d$:",(lbl->key+100));
3267 outBitC(IC_RESULT(ic));
3270 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3271 emitcode("subb","a,acc");
3272 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3273 emitcode("inc","a");
3274 emitcode("","%05d$:",(lbl->key+100));
3275 aopPut(AOP(IC_RESULT(ic)),"a",0);
3276 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3280 /*-----------------------------------------------------------------*/
3281 /* genMinus - generates code for subtraction */
3282 /*-----------------------------------------------------------------*/
3283 static void genMinus (iCode *ic)
3285 int size, offset = 0;
3287 unsigned long lit = 0L;
3288 bool pushResult = FALSE;
3290 D(emitcode(";", "genMinus "););
3292 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3293 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3294 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3295 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3301 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3303 /* special cases :- */
3304 /* if both left & right are in bit space */
3305 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3306 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3311 /* if I can do an decrement instead
3312 of subtract then GOOD for ME */
3313 if (genMinusDec (ic) == TRUE)
3318 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3320 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3324 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3329 /* if literal, add a,#-lit, else normal subb */
3330 _startLazyDPSEvaluation();
3332 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3333 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3334 emitcode("subb","a,%s",
3335 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3337 /* first add without previous c */
3339 emitcode("add","a,#0x%02x",
3340 (unsigned int)(lit & 0x0FFL));
3342 emitcode("addc","a,#0x%02x",
3343 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3348 emitcode("push", "acc");
3352 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3356 _endLazyDPSEvaluation();
3360 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3362 size = getDataSize(IC_LEFT(ic));
3363 rSize = getDataSize(IC_RESULT(ic));
3365 /* If the pushed data is bigger than the result,
3366 * simply discard unused bytes. Icky, but works.
3368 * Should we throw a warning here? We're losing data...
3370 while (size > getDataSize(IC_RESULT(ic)))
3372 emitcode(";", "discarding unused result byte.");
3373 emitcode("pop", "acc");
3379 emitcode("clr", "a");
3380 /* Conversly, we haven't pushed enough here.
3381 * just zero-pad, and all is well.
3383 while (size < rSize)
3385 emitcode("push", "acc");
3393 emitcode("pop", "acc");
3394 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3398 adjustArithmeticResult(ic);
3401 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3402 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3403 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3407 /*-----------------------------------------------------------------*/
3408 /* genMultbits :- multiplication of bits */
3409 /*-----------------------------------------------------------------*/
3410 static void genMultbits (operand *left,
3414 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3415 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3420 /*-----------------------------------------------------------------*/
3421 /* genMultOneByte : 8 bit multiplication & division */
3422 /*-----------------------------------------------------------------*/
3423 static void genMultOneByte (operand *left,
3427 link *opetype = operandType(result);
3432 /* (if two literals, the value is computed before) */
3433 /* if one literal, literal on the right */
3434 if (AOP_TYPE(left) == AOP_LIT){
3440 size = AOP_SIZE(result);
3441 /* signed or unsigned */
3442 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3443 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3445 emitcode("mul","ab");
3446 /* if result size = 1, mul signed = mul unsigned */
3447 aopPut(AOP(result),"a",0);
3449 if (SPEC_USIGN(opetype)){
3450 aopPut(AOP(result),"b",1);
3452 /* for filling the MSBs */
3453 emitcode("clr","a");
3456 emitcode("mov","a,b");
3458 /* adjust the MSB if left or right neg */
3460 /* if one literal */
3461 if (AOP_TYPE(right) == AOP_LIT){
3462 /* AND literal negative */
3463 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3464 /* adjust MSB (c==0 after mul) */
3465 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3469 lbl = newiTempLabel(NULL);
3470 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3471 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3472 emitcode("","%05d$:",(lbl->key+100));
3473 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3474 lbl = newiTempLabel(NULL);
3475 emitcode("jc","%05d$",(lbl->key+100));
3476 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3477 emitcode("","%05d$:",(lbl->key+100));
3480 lbl = newiTempLabel(NULL);
3481 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3482 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3483 emitcode("","%05d$:",(lbl->key+100));
3484 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3485 lbl = newiTempLabel(NULL);
3486 emitcode("jc","%05d$",(lbl->key+100));
3487 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3488 emitcode("","%05d$:",(lbl->key+100));
3490 aopPut(AOP(result),"a",1);
3493 emitcode("rlc","a");
3494 emitcode("subb","a,acc");
3501 aopPut(AOP(result),"a",offset++);
3505 /*-----------------------------------------------------------------*/
3506 /* genMult - generates code for multiplication */
3507 /*-----------------------------------------------------------------*/
3508 static void genMult (iCode *ic)
3510 operand *left = IC_LEFT(ic);
3511 operand *right = IC_RIGHT(ic);
3512 operand *result= IC_RESULT(ic);
3514 D(emitcode(";", "genMult "););
3516 /* assign the amsops */
3519 aopOp (left,ic,FALSE, FALSE);
3520 aopOp (right,ic,FALSE, TRUE);
3521 aopOp (result,ic,TRUE, FALSE);
3524 /* special cases first */
3526 if (AOP_TYPE(left) == AOP_CRY &&
3527 AOP_TYPE(right)== AOP_CRY) {
3528 genMultbits(left,right,result);
3532 /* if both are of size == 1 */
3533 if (AOP_SIZE(left) == 1 &&
3534 AOP_SIZE(right) == 1 ) {
3535 genMultOneByte(left,right,result);
3539 /* should have been converted to function call */
3543 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3544 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3545 freeAsmop(result,NULL,ic,TRUE);
3548 /*-----------------------------------------------------------------*/
3549 /* genDivbits :- division of bits */
3550 /*-----------------------------------------------------------------*/
3551 static void genDivbits (operand *left,
3558 /* the result must be bit */
3559 LOAD_AB_FOR_DIV(left, right, l);
3560 emitcode("div","ab");
3561 emitcode("rrc","a");
3562 aopPut(AOP(result),"c",0);
3565 /*-----------------------------------------------------------------*/
3566 /* genDivOneByte : 8 bit division */
3567 /*-----------------------------------------------------------------*/
3568 static void genDivOneByte (operand *left,
3572 link *opetype = operandType(result);
3577 size = AOP_SIZE(result) - 1;
3579 /* signed or unsigned */
3580 if (SPEC_USIGN(opetype)) {
3581 /* unsigned is easy */
3582 LOAD_AB_FOR_DIV(left, right, l);
3583 emitcode("div","ab");
3584 aopPut(AOP(result),"a",0);
3586 aopPut(AOP(result),zero,offset++);
3590 /* signed is a little bit more difficult */
3592 /* save the signs of the operands */
3593 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3595 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3596 emitcode("push","acc"); /* save it on the stack */
3598 /* now sign adjust for both left & right */
3599 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3601 lbl = newiTempLabel(NULL);
3602 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3603 emitcode("cpl","a");
3604 emitcode("inc","a");
3605 emitcode("","%05d$:",(lbl->key+100));
3606 emitcode("mov","b,a");
3608 /* sign adjust left side */
3609 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3612 lbl = newiTempLabel(NULL);
3613 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3614 emitcode("cpl","a");
3615 emitcode("inc","a");
3616 emitcode("","%05d$:",(lbl->key+100));
3618 /* now the division */
3619 emitcode("nop", "; workaround for DS80C390 div bug.");
3620 emitcode("div","ab");
3621 /* we are interested in the lower order
3623 emitcode("mov","b,a");
3624 lbl = newiTempLabel(NULL);
3625 emitcode("pop","acc");
3626 /* if there was an over flow we don't
3627 adjust the sign of the result */
3628 emitcode("jb","ov,%05d$",(lbl->key+100));
3629 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3631 emitcode("clr","a");
3632 emitcode("subb","a,b");
3633 emitcode("mov","b,a");
3634 emitcode("","%05d$:",(lbl->key+100));
3636 /* now we are done */
3637 aopPut(AOP(result),"b",0);
3639 emitcode("mov","c,b.7");
3640 emitcode("subb","a,acc");
3643 aopPut(AOP(result),"a",offset++);
3647 /*-----------------------------------------------------------------*/
3648 /* genDiv - generates code for division */
3649 /*-----------------------------------------------------------------*/
3650 static void genDiv (iCode *ic)
3652 operand *left = IC_LEFT(ic);
3653 operand *right = IC_RIGHT(ic);
3654 operand *result= IC_RESULT(ic);
3656 D(emitcode(";", "genDiv "););
3658 /* assign the amsops */
3661 aopOp (left,ic,FALSE, FALSE);
3662 aopOp (right,ic,FALSE, TRUE);
3663 aopOp (result,ic,TRUE, FALSE);
3666 /* special cases first */
3668 if (AOP_TYPE(left) == AOP_CRY &&
3669 AOP_TYPE(right)== AOP_CRY) {
3670 genDivbits(left,right,result);
3674 /* if both are of size == 1 */
3675 if (AOP_SIZE(left) == 1 &&
3676 AOP_SIZE(right) == 1 ) {
3677 genDivOneByte(left,right,result);
3681 /* should have been converted to function call */
3684 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3685 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3686 freeAsmop(result,NULL,ic,TRUE);
3689 /*-----------------------------------------------------------------*/
3690 /* genModbits :- modulus of bits */
3691 /*-----------------------------------------------------------------*/
3692 static void genModbits (operand *left,
3699 /* the result must be bit */
3700 LOAD_AB_FOR_DIV(left, right, l);
3701 emitcode("div","ab");
3702 emitcode("mov","a,b");
3703 emitcode("rrc","a");
3704 aopPut(AOP(result),"c",0);
3707 /*-----------------------------------------------------------------*/
3708 /* genModOneByte : 8 bit modulus */
3709 /*-----------------------------------------------------------------*/
3710 static void genModOneByte (operand *left,
3714 link *opetype = operandType(result);
3718 /* signed or unsigned */
3719 if (SPEC_USIGN(opetype)) {
3720 /* unsigned is easy */
3721 LOAD_AB_FOR_DIV(left, right, l);
3722 emitcode("div","ab");
3723 aopPut(AOP(result),"b",0);
3727 /* signed is a little bit more difficult */
3729 /* save the signs of the operands */
3730 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3733 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3734 emitcode("push","acc"); /* save it on the stack */
3736 /* now sign adjust for both left & right */
3737 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3740 lbl = newiTempLabel(NULL);
3741 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3742 emitcode("cpl","a");
3743 emitcode("inc","a");
3744 emitcode("","%05d$:",(lbl->key+100));
3745 emitcode("mov","b,a");
3747 /* sign adjust left side */
3748 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3751 lbl = newiTempLabel(NULL);
3752 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3753 emitcode("cpl","a");
3754 emitcode("inc","a");
3755 emitcode("","%05d$:",(lbl->key+100));
3757 /* now the multiplication */
3758 emitcode("nop", "; workaround for DS80C390 div bug.");
3759 emitcode("div","ab");
3760 /* we are interested in the lower order
3762 lbl = newiTempLabel(NULL);
3763 emitcode("pop","acc");
3764 /* if there was an over flow we don't
3765 adjust the sign of the result */
3766 emitcode("jb","ov,%05d$",(lbl->key+100));
3767 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3769 emitcode("clr","a");
3770 emitcode("subb","a,b");
3771 emitcode("mov","b,a");
3772 emitcode("","%05d$:",(lbl->key+100));
3774 /* now we are done */
3775 aopPut(AOP(result),"b",0);
3779 /*-----------------------------------------------------------------*/
3780 /* genMod - generates code for division */
3781 /*-----------------------------------------------------------------*/
3782 static void genMod (iCode *ic)
3784 operand *left = IC_LEFT(ic);
3785 operand *right = IC_RIGHT(ic);
3786 operand *result= IC_RESULT(ic);
3788 D(emitcode(";", "genMod "););
3790 /* assign the amsops */
3793 aopOp (left,ic,FALSE, FALSE);
3794 aopOp (right,ic,FALSE, TRUE);
3795 aopOp (result,ic,TRUE, FALSE);
3798 /* special cases first */
3800 if (AOP_TYPE(left) == AOP_CRY &&
3801 AOP_TYPE(right)== AOP_CRY) {
3802 genModbits(left,right,result);
3806 /* if both are of size == 1 */
3807 if (AOP_SIZE(left) == 1 &&
3808 AOP_SIZE(right) == 1 ) {
3809 genModOneByte(left,right,result);
3813 /* should have been converted to function call */
3817 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3818 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3819 freeAsmop(result,NULL,ic,TRUE);
3822 /*-----------------------------------------------------------------*/
3823 /* genIfxJump :- will create a jump depending on the ifx */
3824 /*-----------------------------------------------------------------*/
3825 static void genIfxJump (iCode *ic, char *jval)
3828 symbol *tlbl = newiTempLabel(NULL);
3831 D(emitcode(";", "genIfxJump "););
3833 /* if true label then we jump if condition
3835 if ( IC_TRUE(ic) ) {
3837 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3838 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3841 /* false label is present */
3842 jlbl = IC_FALSE(ic) ;
3843 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3844 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3846 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3847 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3849 emitcode(inst,"%05d$",tlbl->key+100);
3850 emitcode("ljmp","%05d$",jlbl->key+100);
3851 emitcode("","%05d$:",tlbl->key+100);
3853 /* mark the icode as generated */
3857 /*-----------------------------------------------------------------*/
3858 /* genCmp :- greater or less than comparison */
3859 /*-----------------------------------------------------------------*/
3860 static void genCmp (operand *left,operand *right,
3861 operand *result, iCode *ifx, int sign)
3863 int size, offset = 0 ;
3864 unsigned long lit = 0L;
3865 bool swappedOps = FALSE;
3867 D(emitcode(";", "genCmp"););
3870 /* If left if lit and right isn't, swap 'em. */
3871 if (AOP_TYPE(left) == AOP_LIT &&
3872 AOP_TYPE(right) != AOP_LIT)
3874 operand *tmp = left;
3877 D(emitcode(";", "kevin literal hack"););
3878 swappedOps = !swappedOps;
3881 if (AOP_NEEDSACC(right))
3883 if (AOP_NEEDSACC(left))
3885 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3886 "both CMP operands need ACC!");
3891 operand *tmp = left;
3894 D(emitcode(";", "kevin ACC hack"););
3895 swappedOps = !swappedOps;
3900 /* if left & right are bit variables */
3901 if (AOP_TYPE(left) == AOP_CRY &&
3902 AOP_TYPE(right) == AOP_CRY ) {
3903 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3904 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3906 /* subtract right from left if at the
3907 end the carry flag is set then we know that
3908 left is greater than right */
3909 size = max(AOP_SIZE(left),AOP_SIZE(right));
3911 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3912 if((size == 1) && !sign &&
3913 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3914 symbol *lbl = newiTempLabel(NULL);
3915 emitcode("cjne","%s,%s,%05d$",
3916 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3917 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3919 emitcode("","%05d$:",lbl->key+100);
3921 if(AOP_TYPE(right) == AOP_LIT){
3922 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3923 /* optimize if(x < 0) or if(x >= 0) */
3929 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3930 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3931 genIfxJump (ifx,"acc.7");
3935 emitcode("rlc","a");
3943 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3944 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3945 emitcode(";", "genCmp #2");
3946 if (sign && (size == 0))
3948 emitcode(";", "genCmp #3");
3949 emitcode("xrl","a,#0x80");
3950 if (AOP_TYPE(right) == AOP_LIT)
3952 unsigned long lit = (unsigned long)
3953 floatFromVal(AOP(right)->aopu.aop_lit);
3954 emitcode(";", "genCmp #3.1");
3955 emitcode("subb","a,#0x%02x",
3956 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3960 emitcode(";", "genCmp #3.2");
3961 if (AOP_NEEDSACC(right))
3963 emitcode("push", "acc");
3965 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3966 FALSE,FALSE,FALSE));
3967 emitcode("xrl","b,#0x80");
3968 if (AOP_NEEDSACC(right))
3970 emitcode("pop", "acc");
3972 emitcode("subb","a,b");
3979 emitcode(";", "genCmp #4");
3980 if (AOP_NEEDSACC(right))
3983 emitcode(";", "genCmp #4.1");
3984 emitcode("xch", "a, b");
3985 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3986 emitcode("xch", "a, b");
3991 emitcode(";", "genCmp #4.2");
3992 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
3995 emitcode("subb","a,%s",s);
4004 D(emitcode(";","kevHack: flip carry."););
4005 emitcode("cpl", "c");
4008 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4011 /* if the result is used in the next
4012 ifx conditional branch then generate
4013 code a little differently */
4015 genIfxJump (ifx,"c");
4018 /* leave the result in acc */
4022 /*-----------------------------------------------------------------*/
4023 /* genCmpGt :- greater than comparison */
4024 /*-----------------------------------------------------------------*/
4025 static void genCmpGt (iCode *ic, iCode *ifx)
4027 operand *left, *right, *result;
4028 link *letype , *retype;
4031 D(emitcode(";", "genCmpGt "););
4034 right= IC_RIGHT(ic);
4035 result = IC_RESULT(ic);
4037 letype = getSpec(operandType(left));
4038 retype =getSpec(operandType(right));
4039 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4040 /* assign the amsops */
4043 aopOp (left,ic,FALSE, TRUE);
4044 aopOp (right,ic,FALSE, FALSE);
4045 aopOp (result,ic,TRUE, FALSE);
4048 genCmp(right, left, result, ifx, sign);
4050 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4051 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4052 freeAsmop(result,NULL,ic,TRUE);
4055 /*-----------------------------------------------------------------*/
4056 /* genCmpLt - less than comparisons */
4057 /*-----------------------------------------------------------------*/
4058 static void genCmpLt (iCode *ic, iCode *ifx)
4060 operand *left, *right, *result;
4061 link *letype , *retype;
4064 D(emitcode(";", "genCmpLt "););
4067 right= IC_RIGHT(ic);
4068 result = IC_RESULT(ic);
4070 letype = getSpec(operandType(left));
4071 retype =getSpec(operandType(right));
4072 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4074 /* assign the amsops */
4077 aopOp (left,ic,FALSE, FALSE);
4078 aopOp (right,ic,FALSE, TRUE);
4079 aopOp (result,ic,TRUE, FALSE);
4082 genCmp(left, right, result, ifx, sign);
4084 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4085 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4086 freeAsmop(result,NULL,ic,TRUE);
4089 /*-----------------------------------------------------------------*/
4090 /* gencjneshort - compare and jump if not equal */
4091 /*-----------------------------------------------------------------*/
4092 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4094 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4096 unsigned long lit = 0L;
4098 D(emitcode(";", "gencjneshort"););
4100 /* if the left side is a literal or
4101 if the right is in a pointer register and left
4103 if ((AOP_TYPE(left) == AOP_LIT) ||
4104 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4110 if(AOP_TYPE(right) == AOP_LIT)
4111 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4113 if (opIsGptr(left) || opIsGptr(right))
4115 /* We are comparing a generic pointer to something.
4116 * Exclude the generic type byte from the comparison.
4119 D(emitcode(";", "cjneshort: generic ptr special case.");)
4123 /* if the right side is a literal then anything goes */
4124 if (AOP_TYPE(right) == AOP_LIT &&
4125 AOP_TYPE(left) != AOP_DIR ) {
4127 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4129 emitcode("cjne","a,%s,%05d$",
4130 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4136 /* if the right side is in a register or in direct space or
4137 if the left is a pointer register & right is not */
4138 else if (AOP_TYPE(right) == AOP_REG ||
4139 AOP_TYPE(right) == AOP_DIR ||
4140 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4141 (IS_AOP_PREG(left) && !IS_AOP_PREG(right)))
4145 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4146 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4147 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4148 emitcode("jnz","%05d$",lbl->key+100);
4150 emitcode("cjne","a,%s,%05d$",
4151 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4156 /* right is a pointer reg need both a & b */
4158 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4160 emitcode("mov","b,%s",l);
4161 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4162 emitcode("cjne","a,b,%05d$",lbl->key+100);
4168 /*-----------------------------------------------------------------*/
4169 /* gencjne - compare and jump if not equal */
4170 /*-----------------------------------------------------------------*/
4171 static void gencjne(operand *left, operand *right, symbol *lbl)
4173 symbol *tlbl = newiTempLabel(NULL);
4175 D(emitcode(";", "gencjne"););
4177 gencjneshort(left, right, lbl);
4179 emitcode("mov","a,%s",one);
4180 emitcode("sjmp","%05d$",tlbl->key+100);
4181 emitcode("","%05d$:",lbl->key+100);
4182 emitcode("clr","a");
4183 emitcode("","%05d$:",tlbl->key+100);
4186 /*-----------------------------------------------------------------*/
4187 /* genCmpEq - generates code for equal to */
4188 /*-----------------------------------------------------------------*/
4189 static void genCmpEq (iCode *ic, iCode *ifx)
4191 operand *left, *right, *result;
4193 D(emitcode(";", "genCmpEq "););
4198 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4199 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4200 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4203 /* if literal, literal on the right or
4204 if the right is in a pointer register and left
4206 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4207 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4208 operand *t = IC_RIGHT(ic);
4209 IC_RIGHT(ic) = IC_LEFT(ic);
4213 if(ifx && !AOP_SIZE(result)){
4215 /* if they are both bit variables */
4216 if (AOP_TYPE(left) == AOP_CRY &&
4217 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4218 if(AOP_TYPE(right) == AOP_LIT){
4219 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4221 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4222 emitcode("cpl","c");
4223 } else if(lit == 1L) {
4224 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4226 emitcode("clr","c");
4228 /* AOP_TYPE(right) == AOP_CRY */
4230 symbol *lbl = newiTempLabel(NULL);
4231 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4232 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4233 emitcode("cpl","c");
4234 emitcode("","%05d$:",(lbl->key+100));
4236 /* if true label then we jump if condition
4238 tlbl = newiTempLabel(NULL);
4239 if ( IC_TRUE(ifx) ) {
4240 emitcode("jnc","%05d$",tlbl->key+100);
4241 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4243 emitcode("jc","%05d$",tlbl->key+100);
4244 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4246 emitcode("","%05d$:",tlbl->key+100);
4248 tlbl = newiTempLabel(NULL);
4249 gencjneshort(left, right, tlbl);
4250 if ( IC_TRUE(ifx) ) {
4251 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4252 emitcode("","%05d$:",tlbl->key+100);
4254 symbol *lbl = newiTempLabel(NULL);
4255 emitcode("sjmp","%05d$",lbl->key+100);
4256 emitcode("","%05d$:",tlbl->key+100);
4257 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4258 emitcode("","%05d$:",lbl->key+100);
4261 /* mark the icode as generated */
4266 /* if they are both bit variables */
4267 if (AOP_TYPE(left) == AOP_CRY &&
4268 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4269 if(AOP_TYPE(right) == AOP_LIT){
4270 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4272 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4273 emitcode("cpl","c");
4274 } else if(lit == 1L) {
4275 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4277 emitcode("clr","c");
4279 /* AOP_TYPE(right) == AOP_CRY */
4281 symbol *lbl = newiTempLabel(NULL);
4282 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4283 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4284 emitcode("cpl","c");
4285 emitcode("","%05d$:",(lbl->key+100));
4288 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4293 genIfxJump (ifx,"c");
4296 /* if the result is used in an arithmetic operation
4297 then put the result in place */
4300 gencjne(left,right,newiTempLabel(NULL));
4301 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4302 aopPut(AOP(result),"a",0);
4306 genIfxJump (ifx,"a");
4309 /* if the result is used in an arithmetic operation
4310 then put the result in place */
4311 if (AOP_TYPE(result) != AOP_CRY)
4313 /* leave the result in acc */
4317 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4318 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4319 freeAsmop(result,NULL,ic,TRUE);
4322 /*-----------------------------------------------------------------*/
4323 /* ifxForOp - returns the icode containing the ifx for operand */
4324 /*-----------------------------------------------------------------*/
4325 static iCode *ifxForOp ( operand *op, iCode *ic )
4327 /* if true symbol then needs to be assigned */
4328 if (IS_TRUE_SYMOP(op))
4331 /* if this has register type condition and
4332 the next instruction is ifx with the same operand
4333 and live to of the operand is upto the ifx only then */
4335 ic->next->op == IFX &&
4336 IC_COND(ic->next)->key == op->key &&
4337 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4342 /*-----------------------------------------------------------------*/
4343 /* genAndOp - for && operation */
4344 /*-----------------------------------------------------------------*/
4345 static void genAndOp (iCode *ic)
4347 operand *left,*right, *result;
4350 D(emitcode(";", "genAndOp "););
4352 /* note here that && operations that are in an
4353 if statement are taken away by backPatchLabels
4354 only those used in arthmetic operations remain */
4358 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4359 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4360 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4363 /* if both are bit variables */
4364 if (AOP_TYPE(left) == AOP_CRY &&
4365 AOP_TYPE(right) == AOP_CRY ) {
4366 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4367 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4370 tlbl = newiTempLabel(NULL);
4372 emitcode("jz","%05d$",tlbl->key+100);
4374 emitcode("","%05d$:",tlbl->key+100);
4378 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4379 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4380 freeAsmop(result,NULL,ic,TRUE);
4384 /*-----------------------------------------------------------------*/
4385 /* genOrOp - for || operation */
4386 /*-----------------------------------------------------------------*/
4387 static void genOrOp (iCode *ic)
4389 operand *left,*right, *result;
4392 D(emitcode(";", "genOrOp "););
4394 /* note here that || operations that are in an
4395 if statement are taken away by backPatchLabels
4396 only those used in arthmetic operations remain */
4400 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4401 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4402 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4405 /* if both are bit variables */
4406 if (AOP_TYPE(left) == AOP_CRY &&
4407 AOP_TYPE(right) == AOP_CRY ) {
4408 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4409 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4412 tlbl = newiTempLabel(NULL);
4414 emitcode("jnz","%05d$",tlbl->key+100);
4416 emitcode("","%05d$:",tlbl->key+100);
4420 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4421 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4422 freeAsmop(result,NULL,ic,TRUE);
4425 /*-----------------------------------------------------------------*/
4426 /* isLiteralBit - test if lit == 2^n */
4427 /*-----------------------------------------------------------------*/
4428 static int isLiteralBit(unsigned long lit)
4430 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4431 0x100L,0x200L,0x400L,0x800L,
4432 0x1000L,0x2000L,0x4000L,0x8000L,
4433 0x10000L,0x20000L,0x40000L,0x80000L,
4434 0x100000L,0x200000L,0x400000L,0x800000L,
4435 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4436 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4439 for(idx = 0; idx < 32; idx++)
4445 /*-----------------------------------------------------------------*/
4446 /* continueIfTrue - */
4447 /*-----------------------------------------------------------------*/
4448 static void continueIfTrue (iCode *ic)
4451 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4455 /*-----------------------------------------------------------------*/
4457 /*-----------------------------------------------------------------*/
4458 static void jumpIfTrue (iCode *ic)
4461 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4465 /*-----------------------------------------------------------------*/
4466 /* jmpTrueOrFalse - */
4467 /*-----------------------------------------------------------------*/
4468 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4470 // ugly but optimized by peephole
4472 symbol *nlbl = newiTempLabel(NULL);
4473 emitcode("sjmp","%05d$",nlbl->key+100);
4474 emitcode("","%05d$:",tlbl->key+100);
4475 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4476 emitcode("","%05d$:",nlbl->key+100);
4479 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4480 emitcode("","%05d$:",tlbl->key+100);
4485 /*-----------------------------------------------------------------*/
4486 /* genAnd - code for and */
4487 /*-----------------------------------------------------------------*/
4488 static void genAnd (iCode *ic, iCode *ifx)
4490 operand *left, *right, *result;
4492 unsigned long lit = 0L;
4496 D(emitcode(";", "genAnd "););
4501 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4502 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4503 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4507 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4509 AOP_TYPE(left), AOP_TYPE(right));
4510 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4512 AOP_SIZE(left), AOP_SIZE(right));
4515 /* if left is a literal & right is not then exchange them */
4516 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4517 AOP_NEEDSACC(left)) {
4518 operand *tmp = right ;
4523 /* if result = right then exchange them */
4524 if(sameRegs(AOP(result),AOP(right))){
4525 operand *tmp = right ;
4530 /* if right is bit then exchange them */
4531 if (AOP_TYPE(right) == AOP_CRY &&
4532 AOP_TYPE(left) != AOP_CRY){
4533 operand *tmp = right ;
4537 if(AOP_TYPE(right) == AOP_LIT)
4538 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4540 size = AOP_SIZE(result);
4543 // result = bit & yy;
4544 if (AOP_TYPE(left) == AOP_CRY){
4545 // c = bit & literal;
4546 if(AOP_TYPE(right) == AOP_LIT){
4548 if(size && sameRegs(AOP(result),AOP(left)))
4551 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4554 if(size && (AOP_TYPE(result) == AOP_CRY)){
4555 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4558 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4562 emitcode("clr","c");
4565 if (AOP_TYPE(right) == AOP_CRY){
4567 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4568 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4571 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4573 emitcode("rrc","a");
4574 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4582 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4583 genIfxJump(ifx, "c");
4587 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4588 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4589 if((AOP_TYPE(right) == AOP_LIT) &&
4590 (AOP_TYPE(result) == AOP_CRY) &&
4591 (AOP_TYPE(left) != AOP_CRY)){
4592 int posbit = isLiteralBit(lit);
4596 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4599 emitcode("mov","c,acc.%d",posbit&0x07);
4603 sprintf(buffer,"acc.%d",posbit&0x07);
4604 genIfxJump(ifx, buffer);
4609 symbol *tlbl = newiTempLabel(NULL);
4610 int sizel = AOP_SIZE(left);
4612 emitcode("setb","c");
4614 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4615 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4617 if((posbit = isLiteralBit(bytelit)) != 0)
4618 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4620 if(bytelit != 0x0FFL)
4621 emitcode("anl","a,%s",
4622 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4623 emitcode("jnz","%05d$",tlbl->key+100);
4628 // bit = left & literal
4630 emitcode("clr","c");
4631 emitcode("","%05d$:",tlbl->key+100);
4633 // if(left & literal)
4636 jmpTrueOrFalse(ifx, tlbl);
4644 /* if left is same as result */
4645 if(sameRegs(AOP(result),AOP(left))){
4646 for(;size--; offset++) {
4647 if(AOP_TYPE(right) == AOP_LIT){
4648 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4652 aopPut(AOP(result),zero,offset);
4654 if (IS_AOP_PREG(result)) {
4655 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4656 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4657 aopPut(AOP(result),"a",offset);
4659 emitcode("anl","%s,%s",
4660 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4661 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4663 if (AOP_TYPE(left) == AOP_ACC)
4664 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4666 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4667 if (IS_AOP_PREG(result)) {
4668 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4669 aopPut(AOP(result),"a",offset);
4672 emitcode("anl","%s,a",
4673 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4678 // left & result in different registers
4679 if(AOP_TYPE(result) == AOP_CRY){
4681 // if(size), result in bit
4682 // if(!size && ifx), conditional oper: if(left & right)
4683 symbol *tlbl = newiTempLabel(NULL);
4684 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4686 emitcode("setb","c");
4688 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4689 emitcode("anl","a,%s",
4690 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4691 emitcode("jnz","%05d$",tlbl->key+100);
4696 emitcode("","%05d$:",tlbl->key+100);
4699 jmpTrueOrFalse(ifx, tlbl);
4701 for(;(size--);offset++) {
4703 // result = left & right
4704 if(AOP_TYPE(right) == AOP_LIT){
4705 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4707 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4710 } else if(bytelit == 0){
4711 aopPut(AOP(result),zero,offset);
4715 // faster than result <- left, anl result,right
4716 // and better if result is SFR
4717 if (AOP_TYPE(left) == AOP_ACC)
4718 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4720 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4721 emitcode("anl","a,%s",
4722 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4724 aopPut(AOP(result),"a",offset);
4730 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4731 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4732 freeAsmop(result,NULL,ic,TRUE);
4735 /*-----------------------------------------------------------------*/
4736 /* genOr - code for or */
4737 /*-----------------------------------------------------------------*/
4738 static void genOr (iCode *ic, iCode *ifx)
4740 operand *left, *right, *result;
4742 unsigned long lit = 0L;
4744 D(emitcode(";", "genOr "););
4749 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4750 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4751 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4755 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4757 AOP_TYPE(left), AOP_TYPE(right));
4758 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4760 AOP_SIZE(left), AOP_SIZE(right));
4763 /* if left is a literal & right is not then exchange them */
4764 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4765 AOP_NEEDSACC(left)) {
4766 operand *tmp = right ;
4771 /* if result = right then exchange them */
4772 if(sameRegs(AOP(result),AOP(right))){
4773 operand *tmp = right ;
4778 /* if right is bit then exchange them */
4779 if (AOP_TYPE(right) == AOP_CRY &&
4780 AOP_TYPE(left) != AOP_CRY){
4781 operand *tmp = right ;
4785 if(AOP_TYPE(right) == AOP_LIT)
4786 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4788 size = AOP_SIZE(result);
4792 if (AOP_TYPE(left) == AOP_CRY){
4793 if(AOP_TYPE(right) == AOP_LIT){
4794 // c = bit & literal;
4796 // lit != 0 => result = 1
4797 if(AOP_TYPE(result) == AOP_CRY){
4799 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4801 continueIfTrue(ifx);
4804 emitcode("setb","c");
4806 // lit == 0 => result = left
4807 if(size && sameRegs(AOP(result),AOP(left)))
4809 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4812 if (AOP_TYPE(right) == AOP_CRY){
4814 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4815 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4819 symbol *tlbl = newiTempLabel(NULL);
4820 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4821 emitcode("setb","c");
4822 emitcode("jb","%s,%05d$",
4823 AOP(left)->aopu.aop_dir,tlbl->key+100);
4825 emitcode("jnz","%05d$",tlbl->key+100);
4826 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4827 jmpTrueOrFalse(ifx, tlbl);
4831 emitcode("","%05d$:",tlbl->key+100);
4840 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4841 genIfxJump(ifx, "c");
4845 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4846 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4847 if((AOP_TYPE(right) == AOP_LIT) &&
4848 (AOP_TYPE(result) == AOP_CRY) &&
4849 (AOP_TYPE(left) != AOP_CRY)){
4853 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4855 continueIfTrue(ifx);
4858 // lit = 0, result = boolean(left)
4860 emitcode("setb","c");
4863 symbol *tlbl = newiTempLabel(NULL);
4864 emitcode("jnz","%05d$",tlbl->key+100);
4866 emitcode("","%05d$:",tlbl->key+100);
4868 genIfxJump (ifx,"a");
4876 /* if left is same as result */
4877 if(sameRegs(AOP(result),AOP(left))){
4878 for(;size--; offset++) {
4879 if(AOP_TYPE(right) == AOP_LIT){
4880 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4883 if (IS_AOP_PREG(left)) {
4884 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4885 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4886 aopPut(AOP(result),"a",offset);
4888 emitcode("orl","%s,%s",
4889 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4890 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4892 if (AOP_TYPE(left) == AOP_ACC)
4893 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4895 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4896 if (IS_AOP_PREG(left)) {
4897 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4898 aopPut(AOP(result),"a",offset);
4900 emitcode("orl","%s,a",
4901 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4906 // left & result in different registers
4907 if(AOP_TYPE(result) == AOP_CRY){
4909 // if(size), result in bit
4910 // if(!size && ifx), conditional oper: if(left | right)
4911 symbol *tlbl = newiTempLabel(NULL);
4912 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4914 emitcode("setb","c");
4916 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4917 emitcode("orl","a,%s",
4918 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4919 emitcode("jnz","%05d$",tlbl->key+100);
4924 emitcode("","%05d$:",tlbl->key+100);
4927 jmpTrueOrFalse(ifx, tlbl);
4928 } else for(;(size--);offset++){
4930 // result = left & right
4931 if(AOP_TYPE(right) == AOP_LIT){
4932 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4934 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4939 // faster than result <- left, anl result,right
4940 // and better if result is SFR
4941 if (AOP_TYPE(left) == AOP_ACC)
4942 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4944 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4945 emitcode("orl","a,%s",
4946 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4948 aopPut(AOP(result),"a",offset);
4953 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4954 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4955 freeAsmop(result,NULL,ic,TRUE);
4958 /*-----------------------------------------------------------------*/
4959 /* genXor - code for xclusive or */
4960 /*-----------------------------------------------------------------*/
4961 static void genXor (iCode *ic, iCode *ifx)
4963 operand *left, *right, *result;
4965 unsigned long lit = 0L;
4967 D(emitcode(";", "genXor "););
4972 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4973 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4974 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4978 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4980 AOP_TYPE(left), AOP_TYPE(right));
4981 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4983 AOP_SIZE(left), AOP_SIZE(right));
4986 /* if left is a literal & right is not ||
4987 if left needs acc & right does not */
4988 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4989 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4990 operand *tmp = right ;
4995 /* if result = right then exchange them */
4996 if(sameRegs(AOP(result),AOP(right))){
4997 operand *tmp = right ;
5002 /* if right is bit then exchange them */
5003 if (AOP_TYPE(right) == AOP_CRY &&
5004 AOP_TYPE(left) != AOP_CRY){
5005 operand *tmp = right ;
5009 if(AOP_TYPE(right) == AOP_LIT)
5010 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5012 size = AOP_SIZE(result);
5016 if (AOP_TYPE(left) == AOP_CRY){
5017 if(AOP_TYPE(right) == AOP_LIT){
5018 // c = bit & literal;
5020 // lit>>1 != 0 => result = 1
5021 if(AOP_TYPE(result) == AOP_CRY){
5023 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5025 continueIfTrue(ifx);
5028 emitcode("setb","c");
5032 // lit == 0, result = left
5033 if(size && sameRegs(AOP(result),AOP(left)))
5035 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5037 // lit == 1, result = not(left)
5038 if(size && sameRegs(AOP(result),AOP(left))){
5039 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5042 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5043 emitcode("cpl","c");
5050 symbol *tlbl = newiTempLabel(NULL);
5051 if (AOP_TYPE(right) == AOP_CRY){
5053 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5056 int sizer = AOP_SIZE(right);
5058 // if val>>1 != 0, result = 1
5059 emitcode("setb","c");
5061 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5063 // test the msb of the lsb
5064 emitcode("anl","a,#0xfe");
5065 emitcode("jnz","%05d$",tlbl->key+100);
5069 emitcode("rrc","a");
5071 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5072 emitcode("cpl","c");
5073 emitcode("","%05d$:",(tlbl->key+100));
5080 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5081 genIfxJump(ifx, "c");
5085 if(sameRegs(AOP(result),AOP(left))){
5086 /* if left is same as result */
5087 for(;size--; offset++) {
5088 if(AOP_TYPE(right) == AOP_LIT){
5089 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5092 if (IS_AOP_PREG(left)) {
5093 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5094 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5095 aopPut(AOP(result),"a",offset);
5097 emitcode("xrl","%s,%s",
5098 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5099 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5101 if (AOP_TYPE(left) == AOP_ACC)
5102 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5104 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5105 if (IS_AOP_PREG(left)) {
5106 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5107 aopPut(AOP(result),"a",offset);
5109 emitcode("xrl","%s,a",
5110 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5115 // left & result in different registers
5116 if(AOP_TYPE(result) == AOP_CRY){
5118 // if(size), result in bit
5119 // if(!size && ifx), conditional oper: if(left ^ right)
5120 symbol *tlbl = newiTempLabel(NULL);
5121 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5123 emitcode("setb","c");
5125 if((AOP_TYPE(right) == AOP_LIT) &&
5126 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5127 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5129 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5130 emitcode("xrl","a,%s",
5131 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5133 emitcode("jnz","%05d$",tlbl->key+100);
5138 emitcode("","%05d$:",tlbl->key+100);
5141 jmpTrueOrFalse(ifx, tlbl);
5142 } else for(;(size--);offset++){
5144 // result = left & right
5145 if(AOP_TYPE(right) == AOP_LIT){
5146 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
5148 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5153 // faster than result <- left, anl result,right
5154 // and better if result is SFR
5155 if (AOP_TYPE(left) == AOP_ACC)
5156 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5158 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5159 emitcode("xrl","a,%s",
5160 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5162 aopPut(AOP(result),"a",offset);
5167 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5168 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5169 freeAsmop(result,NULL,ic,TRUE);
5172 /*-----------------------------------------------------------------*/
5173 /* genInline - write the inline code out */
5174 /*-----------------------------------------------------------------*/
5175 static void genInline (iCode *ic)
5177 char buffer[MAX_INLINEASM];
5181 D(emitcode(";", "genInline "););
5183 _G.inLine += (!options.asmpeep);
5184 strcpy(buffer,IC_INLINE(ic));
5186 /* emit each line as a code */
5205 /* emitcode("",buffer); */
5206 _G.inLine -= (!options.asmpeep);
5209 /*-----------------------------------------------------------------*/
5210 /* genRRC - rotate right with carry */
5211 /*-----------------------------------------------------------------*/
5212 static void genRRC (iCode *ic)
5214 operand *left , *result ;
5215 int size, offset = 0;
5218 D(emitcode(";", "genRRC "););
5220 /* rotate right with carry */
5222 result=IC_RESULT(ic);
5223 aopOp (left,ic,FALSE, FALSE);
5224 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5226 /* move it to the result */
5227 size = AOP_SIZE(result);
5231 _startLazyDPSEvaluation();
5233 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5235 emitcode("rrc","a");
5236 if (AOP_SIZE(result) > 1)
5237 aopPut(AOP(result),"a",offset--);
5239 _endLazyDPSEvaluation();
5241 /* now we need to put the carry into the
5242 highest order byte of the result */
5243 if (AOP_SIZE(result) > 1) {
5244 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5247 emitcode("mov","acc.7,c");
5248 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5249 freeAsmop(left,NULL,ic,TRUE);
5250 freeAsmop(result,NULL,ic,TRUE);
5253 /*-----------------------------------------------------------------*/
5254 /* genRLC - generate code for rotate left with carry */
5255 /*-----------------------------------------------------------------*/
5256 static void genRLC (iCode *ic)
5258 operand *left , *result ;
5259 int size, offset = 0;
5262 D(emitcode(";", "genRLC "););
5264 /* rotate right with carry */
5266 result=IC_RESULT(ic);
5267 aopOp (left,ic,FALSE, FALSE);
5268 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5270 /* move it to the result */
5271 size = AOP_SIZE(result);
5274 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5276 emitcode("add","a,acc");
5277 if (AOP_SIZE(result) > 1)
5279 aopPut(AOP(result),"a",offset++);
5282 _startLazyDPSEvaluation();
5284 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5286 emitcode("rlc","a");
5287 if (AOP_SIZE(result) > 1)
5288 aopPut(AOP(result),"a",offset++);
5290 _endLazyDPSEvaluation();
5292 /* now we need to put the carry into the
5293 highest order byte of the result */
5294 if (AOP_SIZE(result) > 1) {
5295 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5298 emitcode("mov","acc.0,c");
5299 aopPut(AOP(result),"a",0);
5300 freeAsmop(left,NULL,ic,TRUE);
5301 freeAsmop(result,NULL,ic,TRUE);
5304 /*-----------------------------------------------------------------*/
5305 /* genGetHbit - generates code get highest order bit */
5306 /*-----------------------------------------------------------------*/
5307 static void genGetHbit (iCode *ic)
5309 operand *left, *result;
5311 result=IC_RESULT(ic);
5312 aopOp (left,ic,FALSE, FALSE);
5313 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5315 D(emitcode(";", "genGetHbit "););
5317 /* get the highest order byte into a */
5318 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5319 if(AOP_TYPE(result) == AOP_CRY){
5320 emitcode("rlc","a");
5325 emitcode("anl","a,#0x01");
5330 freeAsmop(left,NULL,ic,TRUE);
5331 freeAsmop(result,NULL,ic,TRUE);
5334 /*-----------------------------------------------------------------*/
5335 /* AccRol - rotate left accumulator by known count */
5336 /*-----------------------------------------------------------------*/
5337 static void AccRol (int shCount)
5339 shCount &= 0x0007; // shCount : 0..7
5351 emitcode("swap","a");
5355 emitcode("swap","a");
5358 emitcode("swap","a");
5371 /*-----------------------------------------------------------------*/
5372 /* AccLsh - left shift accumulator by known count */
5373 /*-----------------------------------------------------------------*/
5374 static void AccLsh (int shCount)
5378 emitcode("add","a,acc");
5381 emitcode("add","a,acc");
5382 emitcode("add","a,acc");
5384 /* rotate left accumulator */
5386 /* and kill the lower order bits */
5387 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5392 /*-----------------------------------------------------------------*/
5393 /* AccRsh - right shift accumulator by known count */
5394 /*-----------------------------------------------------------------*/
5395 static void AccRsh (int shCount)
5400 emitcode("rrc","a");
5402 /* rotate right accumulator */
5403 AccRol(8 - shCount);
5404 /* and kill the higher order bits */
5405 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5412 /*-----------------------------------------------------------------*/
5413 /* AccSRsh - signed right shift accumulator by known count */
5414 /*-----------------------------------------------------------------*/
5415 static void AccSRsh (int shCount)
5420 emitcode("mov","c,acc.7");
5421 emitcode("rrc","a");
5422 } else if(shCount == 2){
5423 emitcode("mov","c,acc.7");
5424 emitcode("rrc","a");
5425 emitcode("mov","c,acc.7");
5426 emitcode("rrc","a");
5428 tlbl = newiTempLabel(NULL);
5429 /* rotate right accumulator */
5430 AccRol(8 - shCount);
5431 /* and kill the higher order bits */
5432 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5433 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5434 emitcode("orl","a,#0x%02x",
5435 (unsigned char)~SRMask[shCount]);
5436 emitcode("","%05d$:",tlbl->key+100);
5444 /*-----------------------------------------------------------------*/
5445 /* shiftR1Left2Result - shift right one byte from left to result */
5446 /*-----------------------------------------------------------------*/
5447 static void shiftR1Left2Result (operand *left, int offl,
5448 operand *result, int offr,
5449 int shCount, int sign)
5451 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5452 /* shift right accumulator */
5457 aopPut(AOP(result),"a",offr);
5463 /*-----------------------------------------------------------------*/
5464 /* shiftL1Left2Result - shift left one byte from left to result */
5465 /*-----------------------------------------------------------------*/
5466 static void shiftL1Left2Result (operand *left, int offl,
5467 operand *result, int offr, int shCount)
5470 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5472 /* shift left accumulator */
5474 aopPut(AOP(result),"a",offr);
5480 /*-----------------------------------------------------------------*/
5481 /* movLeft2Result - move byte from left to result */
5482 /*-----------------------------------------------------------------*/
5483 static void movLeft2Result (operand *left, int offl,
5484 operand *result, int offr, int sign)
5487 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5488 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5490 if (*l == '@' && (IS_AOP_PREG(result))) {
5491 emitcode("mov","a,%s",l);
5492 aopPut(AOP(result),"a",offr);
5495 aopPut(AOP(result),l,offr);
5497 /* MSB sign in acc.7 ! */
5498 if(getDataSize(left) == offl+1){
5499 emitcode("mov","a,%s",l);
5500 aopPut(AOP(result),"a",offr);
5510 /*-----------------------------------------------------------------*/
5511 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5512 /*-----------------------------------------------------------------*/
5513 static void AccAXRrl1 (char *x)
5515 emitcode("rrc","a");
5516 emitcode("xch","a,%s", x);
5517 emitcode("rrc","a");
5518 emitcode("xch","a,%s", x);
5524 /*-----------------------------------------------------------------*/
5525 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5526 /*-----------------------------------------------------------------*/
5527 static void AccAXLrl1 (char *x)
5529 emitcode("xch","a,%s",x);
5530 emitcode("rlc","a");
5531 emitcode("xch","a,%s",x);
5532 emitcode("rlc","a");
5538 /*-----------------------------------------------------------------*/
5539 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5540 /*-----------------------------------------------------------------*/
5541 static void AccAXLsh1 (char *x)
5543 emitcode("xch","a,%s",x);
5544 emitcode("add","a,acc");
5545 emitcode("xch","a,%s",x);
5546 emitcode("rlc","a");
5552 /*-----------------------------------------------------------------*/
5553 /* AccAXLsh - left shift a:x by known count (0..7) */
5554 /*-----------------------------------------------------------------*/
5555 static void AccAXLsh (char *x, int shCount)
5569 case 5 : // AAAAABBB:CCCCCDDD
5570 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5571 emitcode("anl","a,#0x%02x",
5572 SLMask[shCount]); // BBB00000:CCCCCDDD
5573 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5574 AccRol(shCount); // DDDCCCCC:BBB00000
5575 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5576 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5577 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5578 emitcode("anl","a,#0x%02x",
5579 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5580 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5581 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5583 case 6 : // AAAAAABB:CCCCCCDD
5584 emitcode("anl","a,#0x%02x",
5585 SRMask[shCount]); // 000000BB:CCCCCCDD
5586 emitcode("mov","c,acc.0"); // c = B
5587 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5588 AccAXRrl1(x); // BCCCCCCD:D000000B
5589 AccAXRrl1(x); // BBCCCCCC:DD000000
5591 case 7 : // a:x <<= 7
5592 emitcode("anl","a,#0x%02x",
5593 SRMask[shCount]); // 0000000B:CCCCCCCD
5594 emitcode("mov","c,acc.0"); // c = B
5595 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5596 AccAXRrl1(x); // BCCCCCCC:D0000000
5606 /*-----------------------------------------------------------------*/
5607 /* AccAXRsh - right shift a:x known count (0..7) */
5608 /*-----------------------------------------------------------------*/
5609 static void AccAXRsh (char *x, int shCount)
5616 AccAXRrl1(x); // 0->a:x
5620 AccAXRrl1(x); // 0->a:x
5622 AccAXRrl1(x); // 0->a:x
5626 case 5 : // AAAAABBB:CCCCCDDD = a:x
5627 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5628 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5629 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5630 emitcode("anl","a,#0x%02x",
5631 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5632 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5633 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5634 emitcode("anl","a,#0x%02x",
5635 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5636 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5637 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5638 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5640 case 6 : // AABBBBBB:CCDDDDDD
5641 emitcode("mov","c,acc.7");
5642 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5643 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5644 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5645 emitcode("anl","a,#0x%02x",
5646 SRMask[shCount]); // 000000AA:BBBBBBCC
5648 case 7 : // ABBBBBBB:CDDDDDDD
5649 emitcode("mov","c,acc.7"); // c = A
5650 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5651 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5652 emitcode("anl","a,#0x%02x",
5653 SRMask[shCount]); // 0000000A:BBBBBBBC
5663 /*-----------------------------------------------------------------*/
5664 /* AccAXRshS - right shift signed a:x known count (0..7) */
5665 /*-----------------------------------------------------------------*/
5666 static void AccAXRshS (char *x, int shCount)
5673 emitcode("mov","c,acc.7");
5674 AccAXRrl1(x); // s->a:x
5677 emitcode("mov","c,acc.7");
5678 AccAXRrl1(x); // s->a:x
5679 emitcode("mov","c,acc.7");
5680 AccAXRrl1(x); // s->a:x
5684 case 5 : // AAAAABBB:CCCCCDDD = a:x
5685 tlbl = newiTempLabel(NULL);
5686 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5687 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5688 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5689 emitcode("anl","a,#0x%02x",
5690 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5691 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5692 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5693 emitcode("anl","a,#0x%02x",
5694 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5695 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5696 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5697 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5698 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5699 emitcode("orl","a,#0x%02x",
5700 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5701 emitcode("","%05d$:",tlbl->key+100);
5702 break; // SSSSAAAA:BBBCCCCC
5703 case 6 : // AABBBBBB:CCDDDDDD
5704 tlbl = newiTempLabel(NULL);
5705 emitcode("mov","c,acc.7");
5706 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5707 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5708 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5709 emitcode("anl","a,#0x%02x",
5710 SRMask[shCount]); // 000000AA:BBBBBBCC
5711 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5712 emitcode("orl","a,#0x%02x",
5713 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5714 emitcode("","%05d$:",tlbl->key+100);
5716 case 7 : // ABBBBBBB:CDDDDDDD
5717 tlbl = newiTempLabel(NULL);
5718 emitcode("mov","c,acc.7"); // c = A
5719 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5720 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5721 emitcode("anl","a,#0x%02x",
5722 SRMask[shCount]); // 0000000A:BBBBBBBC
5723 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5724 emitcode("orl","a,#0x%02x",
5725 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5726 emitcode("","%05d$:",tlbl->key+100);
5736 /*-----------------------------------------------------------------*/
5737 /* shiftL2Left2Result - shift left two bytes from left to result */
5738 /*-----------------------------------------------------------------*/
5739 static void shiftL2Left2Result (operand *left, int offl,
5740 operand *result, int offr, int shCount)
5742 if(sameRegs(AOP(result), AOP(left)) &&
5743 ((offl + MSB16) == offr)){
5744 /* don't crash result[offr] */
5745 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5746 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5748 movLeft2Result(left,offl, result, offr, 0);
5749 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5751 /* ax << shCount (x = lsb(result))*/
5752 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5753 aopPut(AOP(result),"a",offr+MSB16);
5759 /*-----------------------------------------------------------------*/
5760 /* shiftR2Left2Result - shift right two bytes from left to result */
5761 /*-----------------------------------------------------------------*/
5762 static void shiftR2Left2Result (operand *left, int offl,
5763 operand *result, int offr,
5764 int shCount, int sign)
5766 if(sameRegs(AOP(result), AOP(left)) &&
5767 ((offl + MSB16) == offr)){
5768 /* don't crash result[offr] */
5769 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5770 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5772 movLeft2Result(left,offl, result, offr, 0);
5773 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5775 /* a:x >> shCount (x = lsb(result))*/
5777 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5779 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5780 if(getDataSize(result) > 1)
5781 aopPut(AOP(result),"a",offr+MSB16);
5787 /*-----------------------------------------------------------------*/
5788 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5789 /*-----------------------------------------------------------------*/
5790 static void shiftLLeftOrResult (operand *left, int offl,
5791 operand *result, int offr, int shCount)
5793 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5794 /* shift left accumulator */
5796 /* or with result */
5797 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5798 /* back to result */
5799 aopPut(AOP(result),"a",offr);
5805 /*-----------------------------------------------------------------*/
5806 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5807 /*-----------------------------------------------------------------*/
5808 static void shiftRLeftOrResult (operand *left, int offl,
5809 operand *result, int offr, int shCount)
5811 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5812 /* shift right accumulator */
5814 /* or with result */
5815 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5816 /* back to result */
5817 aopPut(AOP(result),"a",offr);
5823 /*-----------------------------------------------------------------*/
5824 /* genlshOne - left shift a one byte quantity by known count */
5825 /*-----------------------------------------------------------------*/
5826 static void genlshOne (operand *result, operand *left, int shCount)
5828 D(emitcode(";", "genlshOne "););
5829 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5835 /*-----------------------------------------------------------------*/
5836 /* genlshTwo - left shift two bytes by known amount != 0 */
5837 /*-----------------------------------------------------------------*/
5838 static void genlshTwo (operand *result,operand *left, int shCount)
5842 D(emitcode(";", "genlshTwo "););
5844 size = getDataSize(result);
5846 /* if shCount >= 8 */
5852 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5854 movLeft2Result(left, LSB, result, MSB16, 0);
5856 aopPut(AOP(result),zero,LSB);
5859 /* 1 <= shCount <= 7 */
5862 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5864 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5871 /*-----------------------------------------------------------------*/
5872 /* shiftLLong - shift left one long from left to result */
5873 /* offl = LSB or MSB16 */
5874 /*-----------------------------------------------------------------*/
5875 static void shiftLLong (operand *left, operand *result, int offr )
5878 int size = AOP_SIZE(result);
5880 if(size >= LSB+offr){
5881 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5883 emitcode("add","a,acc");
5884 if (sameRegs(AOP(left),AOP(result)) &&
5885 size >= MSB16+offr && offr != LSB )
5886 emitcode("xch","a,%s",
5887 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5889 aopPut(AOP(result),"a",LSB+offr);
5892 if(size >= MSB16+offr){
5893 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5894 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5897 emitcode("rlc","a");
5898 if (sameRegs(AOP(left),AOP(result)) &&
5899 size >= MSB24+offr && offr != LSB)
5900 emitcode("xch","a,%s",
5901 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5903 aopPut(AOP(result),"a",MSB16+offr);
5906 if(size >= MSB24+offr){
5907 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5908 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5911 emitcode("rlc","a");
5912 if (sameRegs(AOP(left),AOP(result)) &&
5913 size >= MSB32+offr && offr != LSB )
5914 emitcode("xch","a,%s",
5915 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5917 aopPut(AOP(result),"a",MSB24+offr);
5920 if(size > MSB32+offr){
5921 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5922 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5925 emitcode("rlc","a");
5926 aopPut(AOP(result),"a",MSB32+offr);
5929 aopPut(AOP(result),zero,LSB);
5935 /*-----------------------------------------------------------------*/
5936 /* genlshFour - shift four byte by a known amount != 0 */
5937 /*-----------------------------------------------------------------*/
5938 static void genlshFour (operand *result, operand *left, int shCount)
5942 D(emitcode(";", "genlshFour "););
5944 size = AOP_SIZE(result);
5946 /* if shifting more that 3 bytes */
5947 if (shCount >= 24 ) {
5950 /* lowest order of left goes to the highest
5951 order of the destination */
5952 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5954 movLeft2Result(left, LSB, result, MSB32, 0);
5955 aopPut(AOP(result),zero,LSB);
5956 aopPut(AOP(result),zero,MSB16);
5957 aopPut(AOP(result),zero,MSB32);
5961 /* more than two bytes */
5962 else if ( shCount >= 16 ) {
5963 /* lower order two bytes goes to higher order two bytes */
5965 /* if some more remaining */
5967 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5969 movLeft2Result(left, MSB16, result, MSB32, 0);
5970 movLeft2Result(left, LSB, result, MSB24, 0);
5972 aopPut(AOP(result),zero,MSB16);
5973 aopPut(AOP(result),zero,LSB);
5977 /* if more than 1 byte */
5978 else if ( shCount >= 8 ) {
5979 /* lower order three bytes goes to higher order three bytes */
5983 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5985 movLeft2Result(left, LSB, result, MSB16, 0);
5987 else{ /* size = 4 */
5989 movLeft2Result(left, MSB24, result, MSB32, 0);
5990 movLeft2Result(left, MSB16, result, MSB24, 0);
5991 movLeft2Result(left, LSB, result, MSB16, 0);
5992 aopPut(AOP(result),zero,LSB);
5994 else if(shCount == 1)
5995 shiftLLong(left, result, MSB16);
5997 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5998 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5999 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6000 aopPut(AOP(result),zero,LSB);
6005 /* 1 <= shCount <= 7 */
6006 else if(shCount <= 2){
6007 shiftLLong(left, result, LSB);
6009 shiftLLong(result, result, LSB);
6011 /* 3 <= shCount <= 7, optimize */
6013 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6014 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6015 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6022 /*-----------------------------------------------------------------*/
6023 /* genLeftShiftLiteral - left shifting by known count */
6024 /*-----------------------------------------------------------------*/
6025 static void genLeftShiftLiteral (operand *left,
6030 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6033 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
6035 freeAsmop(right,NULL,ic,TRUE);
6037 aopOp(left,ic,FALSE, FALSE);
6038 aopOp(result,ic,FALSE, TRUE);
6040 size = getSize(operandType(result));
6043 emitcode("; shift left ","result %d, left %d",size,
6047 /* I suppose that the left size >= result size */
6050 movLeft2Result(left, size, result, size, 0);
6054 else if(shCount >= (size * 8))
6056 aopPut(AOP(result),zero,size);
6060 genlshOne (result,left,shCount);
6064 case 3: /* bug: this is for generic pointers, I bet. */
6065 genlshTwo (result,left,shCount);
6069 genlshFour (result,left,shCount);
6073 freeAsmop(left,NULL,ic,TRUE);
6074 freeAsmop(result,NULL,ic,TRUE);
6078 /*-----------------------------------------------------------------*/
6079 /* genLeftShift - generates code for left shifting */
6080 /*-----------------------------------------------------------------*/
6081 static void genLeftShift (iCode *ic)
6083 operand *left,*right, *result;
6086 symbol *tlbl , *tlbl1;
6088 D(emitcode(";", "genLeftShift "););
6090 right = IC_RIGHT(ic);
6092 result = IC_RESULT(ic);
6094 aopOp(right,ic,FALSE, FALSE);
6097 /* if the shift count is known then do it
6098 as efficiently as possible */
6099 if (AOP_TYPE(right) == AOP_LIT) {
6100 genLeftShiftLiteral (left,right,result,ic);
6105 /* shift count is unknown then we have to form
6106 a loop get the loop count in B : Note: we take
6107 only the lower order byte since shifting
6108 more that 32 bits make no sense anyway, ( the
6109 largest size of an object can be only 32 bits ) */
6111 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6112 emitcode("inc","b");
6113 freeAsmop (right,NULL,ic,TRUE);
6114 aopOp(left,ic,FALSE, FALSE);
6115 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6117 /* now move the left to the result if they are not the
6119 if (!sameRegs(AOP(left),AOP(result)) &&
6120 AOP_SIZE(result) > 1) {
6122 size = AOP_SIZE(result);
6124 _startLazyDPSEvaluation();
6126 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6127 if (*l == '@' && (IS_AOP_PREG(result))) {
6129 emitcode("mov","a,%s",l);
6130 aopPut(AOP(result),"a",offset);
6132 aopPut(AOP(result),l,offset);
6135 _endLazyDPSEvaluation();
6138 tlbl = newiTempLabel(NULL);
6139 size = AOP_SIZE(result);
6141 tlbl1 = newiTempLabel(NULL);
6143 /* if it is only one byte then */
6145 symbol *tlbl1 = newiTempLabel(NULL);
6147 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6149 emitcode("sjmp","%05d$",tlbl1->key+100);
6150 emitcode("","%05d$:",tlbl->key+100);
6151 emitcode("add","a,acc");
6152 emitcode("","%05d$:",tlbl1->key+100);
6153 emitcode("djnz","b,%05d$",tlbl->key+100);
6154 aopPut(AOP(result),"a",0);
6158 reAdjustPreg(AOP(result));
6160 emitcode("sjmp","%05d$",tlbl1->key+100);
6161 emitcode("","%05d$:",tlbl->key+100);
6162 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6164 emitcode("add","a,acc");
6165 aopPut(AOP(result),"a",offset++);
6166 _startLazyDPSEvaluation();
6168 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6170 emitcode("rlc","a");
6171 aopPut(AOP(result),"a",offset++);
6173 _endLazyDPSEvaluation();
6174 reAdjustPreg(AOP(result));
6176 emitcode("","%05d$:",tlbl1->key+100);
6177 emitcode("djnz","b,%05d$",tlbl->key+100);
6179 freeAsmop(left,NULL,ic,TRUE);
6180 freeAsmop(result,NULL,ic,TRUE);
6185 /*-----------------------------------------------------------------*/
6186 /* genrshOne - right shift a one byte quantity by known count */
6187 /*-----------------------------------------------------------------*/
6188 static void genrshOne (operand *result, operand *left,
6189 int shCount, int sign)
6191 D(emitcode(";", "genrshOne"););
6192 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6198 /*-----------------------------------------------------------------*/
6199 /* genrshTwo - right shift two bytes by known amount != 0 */
6200 /*-----------------------------------------------------------------*/
6201 static void genrshTwo (operand *result,operand *left,
6202 int shCount, int sign)
6204 D(emitcode(";", "genrshTwo"););
6206 /* if shCount >= 8 */
6210 shiftR1Left2Result(left, MSB16, result, LSB,
6213 movLeft2Result(left, MSB16, result, LSB, sign);
6214 addSign(result, MSB16, sign);
6217 /* 1 <= shCount <= 7 */
6219 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6225 /*-----------------------------------------------------------------*/
6226 /* shiftRLong - shift right one long from left to result */
6227 /* offl = LSB or MSB16 */
6228 /*-----------------------------------------------------------------*/
6229 static void shiftRLong (operand *left, int offl,
6230 operand *result, int sign)
6233 emitcode("clr","c");
6234 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6236 emitcode("mov","c,acc.7");
6237 emitcode("rrc","a");
6238 aopPut(AOP(result),"a",MSB32-offl);
6240 /* add sign of "a" */
6241 addSign(result, MSB32, sign);
6243 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6244 emitcode("rrc","a");
6245 aopPut(AOP(result),"a",MSB24-offl);
6247 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6248 emitcode("rrc","a");
6249 aopPut(AOP(result),"a",MSB16-offl);
6252 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6253 emitcode("rrc","a");
6254 aopPut(AOP(result),"a",LSB);
6261 /*-----------------------------------------------------------------*/
6262 /* genrshFour - shift four byte by a known amount != 0 */
6263 /*-----------------------------------------------------------------*/
6264 static void genrshFour (operand *result, operand *left,
6265 int shCount, int sign)
6267 D(emitcode(";", "genrshFour"););
6269 /* if shifting more that 3 bytes */
6270 if(shCount >= 24 ) {
6273 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6275 movLeft2Result(left, MSB32, result, LSB, sign);
6276 addSign(result, MSB16, sign);
6278 else if(shCount >= 16){
6281 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6283 movLeft2Result(left, MSB24, result, LSB, 0);
6284 movLeft2Result(left, MSB32, result, MSB16, sign);
6286 addSign(result, MSB24, sign);
6288 else if(shCount >= 8){
6291 shiftRLong(left, MSB16, result, sign);
6292 else if(shCount == 0){
6293 movLeft2Result(left, MSB16, result, LSB, 0);
6294 movLeft2Result(left, MSB24, result, MSB16, 0);
6295 movLeft2Result(left, MSB32, result, MSB24, sign);
6296 addSign(result, MSB32, sign);
6299 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6300 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6301 /* the last shift is signed */
6302 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6303 addSign(result, MSB32, sign);
6306 else{ /* 1 <= shCount <= 7 */
6308 shiftRLong(left, LSB, result, sign);
6310 shiftRLong(result, LSB, result, sign);
6313 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6314 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6315 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6323 /*-----------------------------------------------------------------*/
6324 /* genRightShiftLiteral - right shifting by known count */
6325 /*-----------------------------------------------------------------*/
6326 static void genRightShiftLiteral (operand *left,
6332 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6335 D(emitcode(";", "genRightShiftLiteral"););
6337 freeAsmop(right,NULL,ic,TRUE);
6339 aopOp(left,ic,FALSE, FALSE);
6340 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6343 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6347 size = getDataSize(left);
6348 /* test the LEFT size !!! */
6350 /* I suppose that the left size >= result size */
6352 size = getDataSize(result);
6354 movLeft2Result(left, size, result, size, 0);
6357 else if(shCount >= (size * 8)){
6359 /* get sign in acc.7 */
6360 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6361 addSign(result, LSB, sign);
6365 genrshOne (result,left,shCount,sign);
6369 genrshTwo (result,left,shCount,sign);
6373 genrshFour (result,left,shCount,sign);
6379 freeAsmop(left,NULL,ic,TRUE);
6380 freeAsmop(result,NULL,ic,TRUE);
6385 /*-----------------------------------------------------------------*/
6386 /* genSignedRightShift - right shift of signed number */
6387 /*-----------------------------------------------------------------*/
6388 static void genSignedRightShift (iCode *ic)
6390 operand *right, *left, *result;
6393 symbol *tlbl, *tlbl1 ;
6395 D(emitcode(";", "genSignedRightShift "););
6397 /* we do it the hard way put the shift count in b
6398 and loop thru preserving the sign */
6400 right = IC_RIGHT(ic);
6402 result = IC_RESULT(ic);
6404 aopOp(right,ic,FALSE, FALSE);
6407 if ( AOP_TYPE(right) == AOP_LIT) {
6408 genRightShiftLiteral (left,right,result,ic,1);
6412 /* shift count is unknown then we have to form
6413 a loop get the loop count in B : Note: we take
6414 only the lower order byte since shifting
6415 more that 32 bits make no sense anyway, ( the
6416 largest size of an object can be only 32 bits ) */
6418 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6419 emitcode("inc","b");
6420 freeAsmop (right,NULL,ic,TRUE);
6421 aopOp(left,ic,FALSE, FALSE);
6422 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6424 /* now move the left to the result if they are not the
6426 if (!sameRegs(AOP(left),AOP(result)) &&
6427 AOP_SIZE(result) > 1) {
6429 size = AOP_SIZE(result);
6431 _startLazyDPSEvaluation();
6433 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6434 if (*l == '@' && IS_AOP_PREG(result)) {
6436 emitcode("mov","a,%s",l);
6437 aopPut(AOP(result),"a",offset);
6439 aopPut(AOP(result),l,offset);
6442 _endLazyDPSEvaluation();
6445 /* mov the highest order bit to OVR */
6446 tlbl = newiTempLabel(NULL);
6447 tlbl1= newiTempLabel(NULL);
6449 size = AOP_SIZE(result);
6451 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6452 emitcode("rlc","a");
6453 emitcode("mov","ov,c");
6454 /* if it is only one byte then */
6456 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6458 emitcode("sjmp","%05d$",tlbl1->key+100);
6459 emitcode("","%05d$:",tlbl->key+100);
6460 emitcode("mov","c,ov");
6461 emitcode("rrc","a");
6462 emitcode("","%05d$:",tlbl1->key+100);
6463 emitcode("djnz","b,%05d$",tlbl->key+100);
6464 aopPut(AOP(result),"a",0);
6468 reAdjustPreg(AOP(result));
6469 emitcode("sjmp","%05d$",tlbl1->key+100);
6470 emitcode("","%05d$:",tlbl->key+100);
6471 emitcode("mov","c,ov");
6472 _startLazyDPSEvaluation();
6474 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6476 emitcode("rrc","a");
6477 aopPut(AOP(result),"a",offset--);
6479 _endLazyDPSEvaluation();
6480 reAdjustPreg(AOP(result));
6481 emitcode("","%05d$:",tlbl1->key+100);
6482 emitcode("djnz","b,%05d$",tlbl->key+100);
6485 freeAsmop(left,NULL,ic,TRUE);
6486 freeAsmop(result,NULL,ic,TRUE);
6489 /*-----------------------------------------------------------------*/
6490 /* genRightShift - generate code for right shifting */
6491 /*-----------------------------------------------------------------*/
6492 static void genRightShift (iCode *ic)
6494 operand *right, *left, *result;
6498 symbol *tlbl, *tlbl1 ;
6500 D(emitcode(";", "genRightShift "););
6502 /* if signed then we do it the hard way preserve the
6503 sign bit moving it inwards */
6504 retype = getSpec(operandType(IC_RESULT(ic)));
6506 if (!SPEC_USIGN(retype)) {
6507 genSignedRightShift (ic);
6511 /* signed & unsigned types are treated the same : i.e. the
6512 signed is NOT propagated inwards : quoting from the
6513 ANSI - standard : "for E1 >> E2, is equivalent to division
6514 by 2**E2 if unsigned or if it has a non-negative value,
6515 otherwise the result is implementation defined ", MY definition
6516 is that the sign does not get propagated */
6518 right = IC_RIGHT(ic);
6520 result = IC_RESULT(ic);
6522 aopOp(right,ic,FALSE, FALSE);
6525 /* if the shift count is known then do it
6526 as efficiently as possible */
6527 if (AOP_TYPE(right) == AOP_LIT) {
6528 genRightShiftLiteral (left,right,result,ic, 0);
6533 /* shift count is unknown then we have to form
6534 a loop get the loop count in B : Note: we take
6535 only the lower order byte since shifting
6536 more that 32 bits make no sense anyway, ( the
6537 largest size of an object can be only 32 bits ) */
6539 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6540 emitcode("inc","b");
6541 freeAsmop (right,NULL,ic,TRUE);
6542 aopOp(left,ic,FALSE, FALSE);
6543 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6545 /* now move the left to the result if they are not the
6547 if (!sameRegs(AOP(left),AOP(result)) &&
6548 AOP_SIZE(result) > 1) {
6550 size = AOP_SIZE(result);
6552 _startLazyDPSEvaluation();
6554 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6555 if (*l == '@' && IS_AOP_PREG(result)) {
6557 emitcode("mov","a,%s",l);
6558 aopPut(AOP(result),"a",offset);
6560 aopPut(AOP(result),l,offset);
6563 _endLazyDPSEvaluation();
6566 tlbl = newiTempLabel(NULL);
6567 tlbl1= newiTempLabel(NULL);
6568 size = AOP_SIZE(result);
6571 /* if it is only one byte then */
6573 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6575 emitcode("sjmp","%05d$",tlbl1->key+100);
6576 emitcode("","%05d$:",tlbl->key+100);
6578 emitcode("rrc","a");
6579 emitcode("","%05d$:",tlbl1->key+100);
6580 emitcode("djnz","b,%05d$",tlbl->key+100);
6581 aopPut(AOP(result),"a",0);
6585 reAdjustPreg(AOP(result));
6586 emitcode("sjmp","%05d$",tlbl1->key+100);
6587 emitcode("","%05d$:",tlbl->key+100);
6589 _startLazyDPSEvaluation();
6591 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6593 emitcode("rrc","a");
6594 aopPut(AOP(result),"a",offset--);
6596 _endLazyDPSEvaluation();
6597 reAdjustPreg(AOP(result));
6599 emitcode("","%05d$:",tlbl1->key+100);
6600 emitcode("djnz","b,%05d$",tlbl->key+100);
6603 freeAsmop(left,NULL,ic,TRUE);
6604 freeAsmop(result,NULL,ic,TRUE);
6607 /*-----------------------------------------------------------------*/
6608 /* genUnpackBits - generates code for unpacking bits */
6609 /*-----------------------------------------------------------------*/
6610 static void genUnpackBits (operand *result, char *rname, int ptype)
6617 D(emitcode(";", "genUnpackBits "););
6619 etype = getSpec(operandType(result));
6621 /* read the first byte */
6626 emitcode("mov","a,@%s",rname);
6630 emitcode("movx","a,@%s",rname);
6634 emitcode("movx","a,@dptr");
6638 emitcode("clr","a");
6639 emitcode("movc","a","@a+dptr");
6643 emitcode("lcall","__gptrget");
6647 /* if we have bitdisplacement then it fits */
6648 /* into this byte completely or if length is */
6649 /* less than a byte */
6650 if ((shCnt = SPEC_BSTR(etype)) ||
6651 (SPEC_BLEN(etype) <= 8)) {
6653 /* shift right acc */
6656 emitcode("anl","a,#0x%02x",
6657 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6658 aopPut(AOP(result),"a",offset);
6662 /* bit field did not fit in a byte */
6663 rlen = SPEC_BLEN(etype) - 8;
6664 aopPut(AOP(result),"a",offset++);
6671 emitcode("inc","%s",rname);
6672 emitcode("mov","a,@%s",rname);
6676 emitcode("inc","%s",rname);
6677 emitcode("movx","a,@%s",rname);
6681 emitcode("inc","dptr");
6682 emitcode("movx","a,@dptr");
6686 emitcode("clr","a");
6687 emitcode("inc","dptr");
6688 emitcode("movc","a","@a+dptr");
6692 emitcode("inc","dptr");
6693 emitcode("lcall","__gptrget");
6698 /* if we are done */
6702 aopPut(AOP(result),"a",offset++);
6707 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6708 aopPut(AOP(result),"a",offset);
6715 /*-----------------------------------------------------------------*/
6716 /* genDataPointerGet - generates code when ptr offset is known */
6717 /*-----------------------------------------------------------------*/
6718 static void genDataPointerGet (operand *left,
6724 int size , offset = 0;
6725 aopOp(result,ic,TRUE, FALSE);
6727 /* get the string representation of the name */
6728 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6729 size = AOP_SIZE(result);
6730 _startLazyDPSEvaluation();
6733 sprintf(buffer,"(%s + %d)",l+1,offset);
6735 sprintf(buffer,"%s",l+1);
6736 aopPut(AOP(result),buffer,offset++);
6738 _endLazyDPSEvaluation();
6740 freeAsmop(left,NULL,ic,TRUE);
6741 freeAsmop(result,NULL,ic,TRUE);
6744 /*-----------------------------------------------------------------*/
6745 /* genNearPointerGet - emitcode for near pointer fetch */
6746 /*-----------------------------------------------------------------*/
6747 static void genNearPointerGet (operand *left,
6754 link *rtype, *retype;
6755 link *ltype = operandType(left);
6758 rtype = operandType(result);
6759 retype= getSpec(rtype);
6761 aopOp(left,ic,FALSE, FALSE);
6763 /* if left is rematerialisable and
6764 result is not bit variable type and
6765 the left is pointer to data space i.e
6766 lower 128 bytes of space */
6767 if (AOP_TYPE(left) == AOP_IMMD &&
6768 !IS_BITVAR(retype) &&
6769 DCL_TYPE(ltype) == POINTER) {
6770 genDataPointerGet (left,result,ic);
6774 /* if the value is already in a pointer register
6775 then don't need anything more */
6776 if (!AOP_INPREG(AOP(left))) {
6777 /* otherwise get a free pointer register */
6779 preg = getFreePtr(ic,&aop,FALSE);
6780 emitcode("mov","%s,%s",
6782 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6783 rname = preg->name ;
6785 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6787 freeAsmop(left,NULL,ic,TRUE);
6788 aopOp (result,ic,FALSE, FALSE);
6790 /* if bitfield then unpack the bits */
6791 if (IS_BITVAR(retype))
6792 genUnpackBits (result,rname,POINTER);
6794 /* we have can just get the values */
6795 int size = AOP_SIZE(result);
6799 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6801 emitcode("mov","a,@%s",rname);
6802 aopPut(AOP(result),"a",offset);
6804 sprintf(buffer,"@%s",rname);
6805 aopPut(AOP(result),buffer,offset);
6809 emitcode("inc","%s",rname);
6813 /* now some housekeeping stuff */
6815 /* we had to allocate for this iCode */
6816 freeAsmop(NULL,aop,ic,TRUE);
6818 /* we did not allocate which means left
6819 already in a pointer register, then
6820 if size > 0 && this could be used again
6821 we have to point it back to where it
6823 if (AOP_SIZE(result) > 1 &&
6824 !OP_SYMBOL(left)->remat &&
6825 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6827 int size = AOP_SIZE(result) - 1;
6829 emitcode("dec","%s",rname);
6834 freeAsmop(result,NULL,ic,TRUE);
6838 /*-----------------------------------------------------------------*/
6839 /* genPagedPointerGet - emitcode for paged pointer fetch */
6840 /*-----------------------------------------------------------------*/
6841 static void genPagedPointerGet (operand *left,
6848 link *rtype, *retype;
6850 rtype = operandType(result);
6851 retype= getSpec(rtype);
6853 aopOp(left,ic,FALSE, FALSE);
6855 /* if the value is already in a pointer register
6856 then don't need anything more */
6857 if (!AOP_INPREG(AOP(left))) {
6858 /* otherwise get a free pointer register */
6860 preg = getFreePtr(ic,&aop,FALSE);
6861 emitcode("mov","%s,%s",
6863 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6864 rname = preg->name ;
6866 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6868 freeAsmop(left,NULL,ic,TRUE);
6869 aopOp (result,ic,FALSE, FALSE);
6871 /* if bitfield then unpack the bits */
6872 if (IS_BITVAR(retype))
6873 genUnpackBits (result,rname,PPOINTER);
6875 /* we have can just get the values */
6876 int size = AOP_SIZE(result);
6881 emitcode("movx","a,@%s",rname);
6882 aopPut(AOP(result),"a",offset);
6887 emitcode("inc","%s",rname);
6891 /* now some housekeeping stuff */
6893 /* we had to allocate for this iCode */
6894 freeAsmop(NULL,aop,ic,TRUE);
6896 /* we did not allocate which means left
6897 already in a pointer register, then
6898 if size > 0 && this could be used again
6899 we have to point it back to where it
6901 if (AOP_SIZE(result) > 1 &&
6902 !OP_SYMBOL(left)->remat &&
6903 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6905 int size = AOP_SIZE(result) - 1;
6907 emitcode("dec","%s",rname);
6912 freeAsmop(result,NULL,ic,TRUE);
6917 /*-----------------------------------------------------------------*/
6918 /* genFarPointerGet - gget value from far space */
6919 /*-----------------------------------------------------------------*/
6920 static void genFarPointerGet (operand *left,
6921 operand *result, iCode *ic)
6924 link *retype = getSpec(operandType(result));
6926 D(emitcode(";", "genFarPointerGet"););
6928 aopOp(left,ic,FALSE, FALSE);
6930 /* if the operand is already in dptr
6931 then we do nothing else we move the value to dptr */
6932 if (AOP_TYPE(left) != AOP_STR) {
6933 /* if this is remateriazable */
6934 if (AOP_TYPE(left) == AOP_IMMD)
6936 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6940 /* we need to get it byte by byte */
6941 _startLazyDPSEvaluation();
6942 if (AOP_TYPE(left) != AOP_DPTR)
6944 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6945 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6946 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6950 /* We need to generate a load to DPTR indirect through DPTR. */
6951 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6952 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6953 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6954 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6955 emitcode("pop", "dph");
6956 emitcode("pop", "dpl");
6958 _endLazyDPSEvaluation();
6961 /* so dptr know contains the address */
6962 freeAsmop(left,NULL,ic,TRUE);
6963 aopOp(result,ic,FALSE, TRUE);
6965 /* if bit then unpack */
6966 if (IS_BITVAR(retype))
6967 genUnpackBits(result,"dptr",FPOINTER);
6969 size = AOP_SIZE(result);
6972 _startLazyDPSEvaluation();
6978 emitcode("movx","a,@dptr");
6980 emitcode("inc","dptr");
6982 aopPut(AOP(result),"a",offset++);
6984 _endLazyDPSEvaluation();
6987 freeAsmop(result,NULL,ic,TRUE);
6990 /*-----------------------------------------------------------------*/
6991 /* emitcodePointerGet - gget value from code space */
6992 /*-----------------------------------------------------------------*/
6993 static void emitcodePointerGet (operand *left,
6994 operand *result, iCode *ic)
6997 link *retype = getSpec(operandType(result));
6999 aopOp(left,ic,FALSE, FALSE);
7001 /* if the operand is already in dptr
7002 then we do nothing else we move the value to dptr */
7003 if (AOP_TYPE(left) != AOP_STR) {
7004 /* if this is remateriazable */
7005 if (AOP_TYPE(left) == AOP_IMMD)
7006 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7007 else { /* we need to get it byte by byte */
7008 _startLazyDPSEvaluation();
7009 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7010 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7011 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7012 _endLazyDPSEvaluation();
7015 /* so dptr know contains the address */
7016 freeAsmop(left,NULL,ic,TRUE);
7017 aopOp(result,ic,FALSE, TRUE);
7019 /* if bit then unpack */
7020 if (IS_BITVAR(retype))
7021 genUnpackBits(result,"dptr",CPOINTER);
7023 size = AOP_SIZE(result);
7026 _startLazyDPSEvaluation();
7032 emitcode("clr","a");
7033 emitcode("movc","a,@a+dptr");
7035 emitcode("inc","dptr");
7036 aopPut(AOP(result),"a",offset++);
7038 _endLazyDPSEvaluation();
7041 freeAsmop(result,NULL,ic,TRUE);
7044 /*-----------------------------------------------------------------*/
7045 /* genGenPointerGet - gget value from generic pointer space */
7046 /*-----------------------------------------------------------------*/
7047 static void genGenPointerGet (operand *left,
7048 operand *result, iCode *ic)
7051 link *retype = getSpec(operandType(result));
7053 aopOp(left,ic,FALSE, TRUE);
7055 /* if the operand is already in dptr
7056 then we do nothing else we move the value to dptr */
7057 if (AOP_TYPE(left) != AOP_STR) {
7058 /* if this is remateriazable */
7059 if (AOP_TYPE(left) == AOP_IMMD) {
7060 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7061 emitcode("mov","b,#%d",pointerCode(retype));
7063 else { /* we need to get it byte by byte */
7064 _startLazyDPSEvaluation();
7065 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7066 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7067 if (options.model == MODEL_FLAT24)
7069 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7070 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7074 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7076 _endLazyDPSEvaluation();
7079 /* so dptr know contains the address */
7080 freeAsmop(left,NULL,ic,TRUE);
7081 aopOp(result,ic,FALSE, TRUE);
7083 /* if bit then unpack */
7084 if (IS_BITVAR(retype))
7085 genUnpackBits(result,"dptr",GPOINTER);
7087 size = AOP_SIZE(result);
7091 emitcode("lcall","__gptrget");
7092 aopPut(AOP(result),"a",offset++);
7094 emitcode("inc","dptr");
7098 freeAsmop(result,NULL,ic,TRUE);
7101 /*-----------------------------------------------------------------*/
7102 /* genPointerGet - generate code for pointer get */
7103 /*-----------------------------------------------------------------*/
7104 static void genPointerGet (iCode *ic)
7106 operand *left, *result ;
7110 D(emitcode(";", "genPointerGet "););
7113 result = IC_RESULT(ic) ;
7115 /* depending on the type of pointer we need to
7116 move it to the correct pointer register */
7117 type = operandType(left);
7118 etype = getSpec(type);
7119 /* if left is of type of pointer then it is simple */
7120 if (IS_PTR(type) && !IS_FUNC(type->next))
7121 p_type = DCL_TYPE(type);
7123 /* we have to go by the storage class */
7124 p_type = PTR_TYPE(SPEC_OCLS(etype));
7126 /* if (SPEC_OCLS(etype)->codesp ) { */
7127 /* p_type = CPOINTER ; */
7130 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7131 /* p_type = FPOINTER ; */
7133 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7134 /* p_type = PPOINTER; */
7136 /* if (SPEC_OCLS(etype) == idata ) */
7137 /* p_type = IPOINTER; */
7139 /* p_type = POINTER ; */
7142 /* now that we have the pointer type we assign
7143 the pointer values */
7148 genNearPointerGet (left,result,ic);
7152 genPagedPointerGet(left,result,ic);
7156 genFarPointerGet (left,result,ic);
7160 emitcodePointerGet (left,result,ic);
7164 genGenPointerGet (left,result,ic);
7170 /*-----------------------------------------------------------------*/
7171 /* genPackBits - generates code for packed bit storage */
7172 /*-----------------------------------------------------------------*/
7173 static void genPackBits (link *etype ,
7175 char *rname, int p_type)
7183 blen = SPEC_BLEN(etype);
7184 bstr = SPEC_BSTR(etype);
7186 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7189 /* if the bit lenth is less than or */
7190 /* it exactly fits a byte then */
7191 if (SPEC_BLEN(etype) <= 8 ) {
7192 shCount = SPEC_BSTR(etype) ;
7194 /* shift left acc */
7197 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7202 emitcode ("mov","b,a");
7203 emitcode("mov","a,@%s",rname);
7207 emitcode ("mov","b,a");
7208 emitcode("movx","a,@dptr");
7212 emitcode ("push","b");
7213 emitcode ("push","acc");
7214 emitcode ("lcall","__gptrget");
7215 emitcode ("pop","b");
7219 emitcode ("anl","a,#0x%02x",(unsigned char)
7220 ((unsigned char)(0xFF << (blen+bstr)) |
7221 (unsigned char)(0xFF >> (8-bstr)) ) );
7222 emitcode ("orl","a,b");
7223 if (p_type == GPOINTER)
7224 emitcode("pop","b");
7230 emitcode("mov","@%s,a",rname);
7234 emitcode("movx","@dptr,a");
7238 emitcode("lcall","__gptrput");
7243 if ( SPEC_BLEN(etype) <= 8 )
7246 emitcode("inc","%s",rname);
7247 rLen = SPEC_BLEN(etype) ;
7249 /* now generate for lengths greater than one byte */
7252 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7262 emitcode("mov","@%s,a",rname);
7264 emitcode("mov","@%s,%s",rname,l);
7269 emitcode("movx","@dptr,a");
7274 emitcode("lcall","__gptrput");
7277 emitcode ("inc","%s",rname);
7282 /* last last was not complete */
7284 /* save the byte & read byte */
7287 emitcode ("mov","b,a");
7288 emitcode("mov","a,@%s",rname);
7292 emitcode ("mov","b,a");
7293 emitcode("movx","a,@dptr");
7297 emitcode ("push","b");
7298 emitcode ("push","acc");
7299 emitcode ("lcall","__gptrget");
7300 emitcode ("pop","b");
7304 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7305 emitcode ("orl","a,b");
7308 if (p_type == GPOINTER)
7309 emitcode("pop","b");
7314 emitcode("mov","@%s,a",rname);
7318 emitcode("movx","@dptr,a");
7322 emitcode("lcall","__gptrput");
7326 /*-----------------------------------------------------------------*/
7327 /* genDataPointerSet - remat pointer to data space */
7328 /*-----------------------------------------------------------------*/
7329 static void genDataPointerSet(operand *right,
7333 int size, offset = 0 ;
7334 char *l, buffer[256];
7336 aopOp(right,ic,FALSE, FALSE);
7338 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7339 size = AOP_SIZE(right);
7342 sprintf(buffer,"(%s + %d)",l+1,offset);
7344 sprintf(buffer,"%s",l+1);
7345 emitcode("mov","%s,%s",buffer,
7346 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7349 freeAsmop(right,NULL,ic,TRUE);
7350 freeAsmop(result,NULL,ic,TRUE);
7353 /*-----------------------------------------------------------------*/
7354 /* genNearPointerSet - emitcode for near pointer put */
7355 /*-----------------------------------------------------------------*/
7356 static void genNearPointerSet (operand *right,
7364 link *ptype = operandType(result);
7366 retype= getSpec(operandType(right));
7368 aopOp(result,ic,FALSE, FALSE);
7370 /* if the result is rematerializable &
7371 in data space & not a bit variable */
7372 if (AOP_TYPE(result) == AOP_IMMD &&
7373 DCL_TYPE(ptype) == POINTER &&
7374 !IS_BITVAR(retype)) {
7375 genDataPointerSet (right,result,ic);
7379 /* if the value is already in a pointer register
7380 then don't need anything more */
7381 if (!AOP_INPREG(AOP(result))) {
7382 /* otherwise get a free pointer register */
7384 preg = getFreePtr(ic,&aop,FALSE);
7385 emitcode("mov","%s,%s",
7387 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7388 rname = preg->name ;
7390 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7392 freeAsmop(result,NULL,ic,TRUE);
7393 aopOp (right,ic,FALSE, FALSE);
7395 /* if bitfield then unpack the bits */
7396 if (IS_BITVAR(retype))
7397 genPackBits (retype,right,rname,POINTER);
7399 /* we have can just get the values */
7400 int size = AOP_SIZE(right);
7404 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7407 emitcode("mov","@%s,a",rname);
7409 emitcode("mov","@%s,%s",rname,l);
7411 emitcode("inc","%s",rname);
7416 /* now some housekeeping stuff */
7418 /* we had to allocate for this iCode */
7419 freeAsmop(NULL,aop,ic,TRUE);
7421 /* we did not allocate which means left
7422 already in a pointer register, then
7423 if size > 0 && this could be used again
7424 we have to point it back to where it
7426 if (AOP_SIZE(right) > 1 &&
7427 !OP_SYMBOL(result)->remat &&
7428 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7430 int size = AOP_SIZE(right) - 1;
7432 emitcode("dec","%s",rname);
7437 freeAsmop(right,NULL,ic,TRUE);
7442 /*-----------------------------------------------------------------*/
7443 /* genPagedPointerSet - emitcode for Paged pointer put */
7444 /*-----------------------------------------------------------------*/
7445 static void genPagedPointerSet (operand *right,
7454 retype= getSpec(operandType(right));
7456 aopOp(result,ic,FALSE, FALSE);
7458 /* if the value is already in a pointer register
7459 then don't need anything more */
7460 if (!AOP_INPREG(AOP(result))) {
7461 /* otherwise get a free pointer register */
7463 preg = getFreePtr(ic,&aop,FALSE);
7464 emitcode("mov","%s,%s",
7466 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7467 rname = preg->name ;
7469 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7471 freeAsmop(result,NULL,ic,TRUE);
7472 aopOp (right,ic,FALSE, FALSE);
7474 /* if bitfield then unpack the bits */
7475 if (IS_BITVAR(retype))
7476 genPackBits (retype,right,rname,PPOINTER);
7478 /* we have can just get the values */
7479 int size = AOP_SIZE(right);
7483 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7486 emitcode("movx","@%s,a",rname);
7489 emitcode("inc","%s",rname);
7495 /* now some housekeeping stuff */
7497 /* we had to allocate for this iCode */
7498 freeAsmop(NULL,aop,ic,TRUE);
7500 /* we did not allocate which means left
7501 already in a pointer register, then
7502 if size > 0 && this could be used again
7503 we have to point it back to where it
7505 if (AOP_SIZE(right) > 1 &&
7506 !OP_SYMBOL(result)->remat &&
7507 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7509 int size = AOP_SIZE(right) - 1;
7511 emitcode("dec","%s",rname);
7516 freeAsmop(right,NULL,ic,TRUE);
7521 /*-----------------------------------------------------------------*/
7522 /* genFarPointerSet - set value from far space */
7523 /*-----------------------------------------------------------------*/
7524 static void genFarPointerSet (operand *right,
7525 operand *result, iCode *ic)
7528 link *retype = getSpec(operandType(right));
7530 aopOp(result,ic,FALSE, FALSE);
7532 /* if the operand is already in dptr
7533 then we do nothing else we move the value to dptr */
7534 if (AOP_TYPE(result) != AOP_STR) {
7535 /* if this is remateriazable */
7536 if (AOP_TYPE(result) == AOP_IMMD)
7537 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7540 /* we need to get it byte by byte */
7541 _startLazyDPSEvaluation();
7542 if (AOP_TYPE(result) != AOP_DPTR)
7544 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7545 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7546 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7550 /* We need to generate a load to DPTR indirect through DPTR. */
7551 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7552 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7553 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7554 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7555 emitcode("pop", "dph");
7556 emitcode("pop", "dpl");
7558 _endLazyDPSEvaluation();
7561 /* so dptr know contains the address */
7562 freeAsmop(result,NULL,ic,TRUE);
7563 aopOp(right,ic,FALSE, TRUE);
7565 /* if bit then unpack */
7566 if (IS_BITVAR(retype))
7567 genPackBits(retype,right,"dptr",FPOINTER);
7569 size = AOP_SIZE(right);
7572 _startLazyDPSEvaluation();
7574 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7580 emitcode("movx","@dptr,a");
7582 emitcode("inc","dptr");
7584 _endLazyDPSEvaluation();
7587 freeAsmop(right,NULL,ic,TRUE);
7590 /*-----------------------------------------------------------------*/
7591 /* genGenPointerSet - set value from generic pointer space */
7592 /*-----------------------------------------------------------------*/
7593 static void genGenPointerSet (operand *right,
7594 operand *result, iCode *ic)
7597 link *retype = getSpec(operandType(right));
7599 aopOp(result,ic,FALSE, TRUE);
7601 /* if the operand is already in dptr
7602 then we do nothing else we move the value to dptr */
7603 if (AOP_TYPE(result) != AOP_STR) {
7604 _startLazyDPSEvaluation();
7605 /* if this is remateriazable */
7606 if (AOP_TYPE(result) == AOP_IMMD) {
7607 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7608 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7610 else { /* we need to get it byte by byte */
7611 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7612 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7613 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7614 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7616 _endLazyDPSEvaluation();
7618 /* so dptr know contains the address */
7619 freeAsmop(result,NULL,ic,TRUE);
7620 aopOp(right,ic,FALSE, TRUE);
7622 /* if bit then unpack */
7623 if (IS_BITVAR(retype))
7624 genPackBits(retype,right,"dptr",GPOINTER);
7626 size = AOP_SIZE(right);
7629 _startLazyDPSEvaluation();
7631 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7637 emitcode("lcall","__gptrput");
7639 emitcode("inc","dptr");
7641 _endLazyDPSEvaluation();
7644 freeAsmop(right,NULL,ic,TRUE);
7647 /*-----------------------------------------------------------------*/
7648 /* genPointerSet - stores the value into a pointer location */
7649 /*-----------------------------------------------------------------*/
7650 static void genPointerSet (iCode *ic)
7652 operand *right, *result ;
7656 D(emitcode(";", "genPointerSet "););
7658 right = IC_RIGHT(ic);
7659 result = IC_RESULT(ic) ;
7661 /* depending on the type of pointer we need to
7662 move it to the correct pointer register */
7663 type = operandType(result);
7664 etype = getSpec(type);
7665 /* if left is of type of pointer then it is simple */
7666 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7667 p_type = DCL_TYPE(type);
7670 /* we have to go by the storage class */
7671 p_type = PTR_TYPE(SPEC_OCLS(etype));
7673 /* if (SPEC_OCLS(etype)->codesp ) { */
7674 /* p_type = CPOINTER ; */
7677 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7678 /* p_type = FPOINTER ; */
7680 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7681 /* p_type = PPOINTER ; */
7683 /* if (SPEC_OCLS(etype) == idata ) */
7684 /* p_type = IPOINTER ; */
7686 /* p_type = POINTER ; */
7689 /* now that we have the pointer type we assign
7690 the pointer values */
7695 genNearPointerSet (right,result,ic);
7699 genPagedPointerSet (right,result,ic);
7703 genFarPointerSet (right,result,ic);
7707 genGenPointerSet (right,result,ic);
7713 /*-----------------------------------------------------------------*/
7714 /* genIfx - generate code for Ifx statement */
7715 /*-----------------------------------------------------------------*/
7716 static void genIfx (iCode *ic, iCode *popIc)
7718 operand *cond = IC_COND(ic);
7721 D(emitcode(";", "genIfx "););
7723 aopOp(cond,ic,FALSE, FALSE);
7725 /* get the value into acc */
7726 if (AOP_TYPE(cond) != AOP_CRY)
7730 /* the result is now in the accumulator */
7731 freeAsmop(cond,NULL,ic,TRUE);
7733 /* if there was something to be popped then do it */
7737 /* if the condition is a bit variable */
7738 if (isbit && IS_ITEMP(cond) &&
7740 genIfxJump(ic,SPIL_LOC(cond)->rname);
7742 if (isbit && !IS_ITEMP(cond))
7743 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7750 /*-----------------------------------------------------------------*/
7751 /* genAddrOf - generates code for address of */
7752 /*-----------------------------------------------------------------*/
7753 static void genAddrOf (iCode *ic)
7755 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7758 D(emitcode(";", "genAddrOf "););
7760 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7762 /* if the operand is on the stack then we
7763 need to get the stack offset of this
7766 /* if it has an offset then we need to compute
7769 emitcode("mov","a,_bp");
7770 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7771 aopPut(AOP(IC_RESULT(ic)),"a",0);
7773 /* we can just move _bp */
7774 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7776 /* fill the result with zero */
7777 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7780 if (options.stack10bit && size < (FPTRSIZE - 1))
7783 "*** warning: pointer to stack var truncated.\n");
7790 if (options.stack10bit && offset == 2)
7792 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7796 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7803 /* object not on stack then we need the name */
7804 size = AOP_SIZE(IC_RESULT(ic));
7808 char s[SDCC_NAME_MAX];
7810 sprintf(s,"#(%s >> %d)",
7814 sprintf(s,"#%s",sym->rname);
7815 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7819 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7823 /*-----------------------------------------------------------------*/
7824 /* genFarFarAssign - assignment when both are in far space */
7825 /*-----------------------------------------------------------------*/
7826 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7828 int size = AOP_SIZE(right);
7835 /* This is a net loss for size == 1, but a big gain
7838 D(emitcode(";", "genFarFarAssign (improved)"););
7840 aopOp(result,ic,TRUE, TRUE);
7842 _startLazyDPSEvaluation();
7846 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7850 _endLazyDPSEvaluation();
7851 freeAsmop(result,NULL,ic,FALSE);
7852 freeAsmop(right,NULL,ic,FALSE);
7857 D(emitcode(";", "genFarFarAssign "););
7859 /* first push the right side on to the stack */
7860 _startLazyDPSEvaluation();
7862 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7864 emitcode ("push","acc");
7867 freeAsmop(right,NULL,ic,FALSE);
7868 /* now assign DPTR to result */
7869 aopOp(result,ic,FALSE, FALSE);
7870 size = AOP_SIZE(result);
7872 emitcode ("pop","acc");
7873 aopPut(AOP(result),"a",--offset);
7875 freeAsmop(result,NULL,ic,FALSE);
7876 _endLazyDPSEvaluation();
7880 /*-----------------------------------------------------------------*/
7881 /* genAssign - generate code for assignment */
7882 /*-----------------------------------------------------------------*/
7883 static void genAssign (iCode *ic)
7885 operand *result, *right;
7887 unsigned long lit = 0L;
7889 D(emitcode(";", "genAssign "););
7891 result = IC_RESULT(ic);
7892 right = IC_RIGHT(ic) ;
7894 /* if they are the same */
7895 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7898 aopOp(right,ic,FALSE, FALSE);
7900 emitcode(";", "genAssign: resultIsFar = %s",
7901 isOperandInFarSpace(result) ?
7904 /* special case both in far space */
7905 if ((AOP_TYPE(right) == AOP_DPTR ||
7906 AOP_TYPE(right) == AOP_DPTR2) &&
7907 /* IS_TRUE_SYMOP(result) && */
7908 isOperandInFarSpace(result)) {
7910 genFarFarAssign (result,right,ic);
7914 aopOp(result,ic,TRUE, FALSE);
7916 /* if they are the same registers */
7917 if (sameRegs(AOP(right),AOP(result)))
7920 /* if the result is a bit */
7921 if (AOP_TYPE(result) == AOP_CRY) {
7923 /* if the right size is a literal then
7924 we know what the value is */
7925 if (AOP_TYPE(right) == AOP_LIT) {
7926 if (((int) operandLitValue(right)))
7927 aopPut(AOP(result),one,0);
7929 aopPut(AOP(result),zero,0);
7933 /* the right is also a bit variable */
7934 if (AOP_TYPE(right) == AOP_CRY) {
7935 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7936 aopPut(AOP(result),"c",0);
7942 aopPut(AOP(result),"a",0);
7946 /* bit variables done */
7948 size = AOP_SIZE(result);
7950 if(AOP_TYPE(right) == AOP_LIT)
7951 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7954 (AOP_TYPE(result) != AOP_REG) &&
7955 (AOP_TYPE(right) == AOP_LIT) &&
7956 !IS_FLOAT(operandType(right))
7957 #ifndef LAZY_DPS_OPT
7963 D(emitcode(";", "Kevin's better literal load code"););
7964 _startLazyDPSEvaluation();
7965 while (size && ((unsigned int)(lit >> (offset*8)) != 0))
7968 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
7973 /* And now fill the rest with zeros. */
7976 emitcode("clr","a");
7980 aopPut(AOP(result), "a", offset++);
7982 _endLazyDPSEvaluation();
7984 emitcode("clr","a");
7986 _startLazyDPSEvaluation();
7989 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7990 aopPut(AOP(result),"a",size);
7993 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
7996 _endLazyDPSEvaluation();
8001 _startLazyDPSEvaluation();
8005 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8009 _endLazyDPSEvaluation();
8013 freeAsmop (right,NULL,ic,FALSE);
8014 freeAsmop (result,NULL,ic,TRUE);
8017 /*-----------------------------------------------------------------*/
8018 /* genJumpTab - generates code for jump table */
8019 /*-----------------------------------------------------------------*/
8020 static void genJumpTab (iCode *ic)
8025 D(emitcode(";", "genJumpTab "););
8027 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
8028 /* get the condition into accumulator */
8029 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
8031 /* multiply by four! */
8032 emitcode("add","a,acc");
8033 emitcode("add","a,acc");
8034 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8036 jtab = newiTempLabel(NULL);
8037 emitcode("mov","dptr,#%05d$",jtab->key+100);
8038 emitcode("jmp","@a+dptr");
8039 emitcode("","%05d$:",jtab->key+100);
8040 /* now generate the jump labels */
8041 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8042 jtab = setNextItem(IC_JTLABELS(ic)))
8043 emitcode("ljmp","%05d$",jtab->key+100);
8047 /*-----------------------------------------------------------------*/
8048 /* genCast - gen code for casting */
8049 /*-----------------------------------------------------------------*/
8050 static void genCast (iCode *ic)
8052 operand *result = IC_RESULT(ic);
8053 link *ctype = operandType(IC_LEFT(ic));
8054 link *rtype = operandType(IC_RIGHT(ic));
8055 operand *right = IC_RIGHT(ic);
8058 D(emitcode(";", "genCast "););
8060 /* if they are equivalent then do nothing */
8061 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8064 aopOp(right,ic,FALSE, FALSE) ;
8065 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
8067 /* if the result is a bit */
8068 if (AOP_TYPE(result) == AOP_CRY) {
8069 /* if the right size is a literal then
8070 we know what the value is */
8071 if (AOP_TYPE(right) == AOP_LIT) {
8072 if (((int) operandLitValue(right)))
8073 aopPut(AOP(result),one,0);
8075 aopPut(AOP(result),zero,0);
8080 /* the right is also a bit variable */
8081 if (AOP_TYPE(right) == AOP_CRY) {
8082 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8083 aopPut(AOP(result),"c",0);
8089 aopPut(AOP(result),"a",0);
8093 /* if they are the same size : or less */
8094 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8096 /* if they are in the same place */
8097 if (sameRegs(AOP(right),AOP(result)))
8100 /* if they in different places then copy */
8101 size = AOP_SIZE(result);
8103 _startLazyDPSEvaluation();
8106 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8110 _endLazyDPSEvaluation();
8115 /* if the result is of type pointer */
8116 if (IS_PTR(ctype)) {
8119 link *type = operandType(right);
8121 /* pointer to generic pointer */
8122 if (IS_GENPTR(ctype)) {
8127 p_type = DCL_TYPE(type);
8131 #if OLD_CAST_BEHAVIOR
8132 /* KV: we are converting a non-pointer type to
8133 * a generic pointer. This (ifdef'd out) code
8134 * says that the resulting generic pointer
8135 * should have the same class as the storage
8136 * location of the non-pointer variable.
8138 * For example, converting an int (which happens
8139 * to be stored in DATA space) to a pointer results
8140 * in a DATA generic pointer; if the original int
8141 * in XDATA space, so will be the resulting pointer.
8143 * I don't like that behavior, and thus this change:
8144 * all such conversions will be forced to XDATA and
8145 * throw a warning. If you want some non-XDATA
8146 * type, or you want to suppress the warning, you
8147 * must go through an intermediate cast, like so:
8149 * char _generic *gp = (char _xdata *)(intVar);
8151 link *etype = getSpec(type);
8153 /* we have to go by the storage class */
8154 if (SPEC_OCLS(etype) != generic)
8156 p_type = PTR_TYPE(SPEC_OCLS(etype));
8161 /* Converting unknown class (i.e. register variable)
8162 * to generic pointer. This is not good, but
8163 * we'll make a guess (and throw a warning).
8166 werror(W_INT_TO_GEN_PTR_CAST);
8170 /* the first two bytes are known */
8171 size = GPTRSIZE - 1;
8173 _startLazyDPSEvaluation();
8176 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8180 _endLazyDPSEvaluation();
8182 /* the last byte depending on type */
8199 /* this should never happen */
8200 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8201 "got unknown pointer type");
8204 aopPut(AOP(result),l, GPTRSIZE - 1);
8208 /* just copy the pointers */
8209 size = AOP_SIZE(result);
8211 _startLazyDPSEvaluation();
8214 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8218 _endLazyDPSEvaluation();
8222 /* so we now know that the size of destination is greater
8223 than the size of the source */
8224 /* we move to result for the size of source */
8225 size = AOP_SIZE(right);
8227 _startLazyDPSEvaluation();
8230 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8234 _endLazyDPSEvaluation();
8236 /* now depending on the sign of the source && destination */
8237 size = AOP_SIZE(result) - AOP_SIZE(right);
8238 /* if unsigned or not an integral type */
8239 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
8241 aopPut(AOP(result),zero,offset++);
8243 /* we need to extend the sign :{ */
8244 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8247 emitcode("rlc","a");
8248 emitcode("subb","a,acc");
8250 aopPut(AOP(result),"a",offset++);
8253 /* we are done hurray !!!! */
8256 freeAsmop(right,NULL,ic,TRUE);
8257 freeAsmop(result,NULL,ic,TRUE);
8261 /*-----------------------------------------------------------------*/
8262 /* genDjnz - generate decrement & jump if not zero instrucion */
8263 /*-----------------------------------------------------------------*/
8264 static int genDjnz (iCode *ic, iCode *ifx)
8270 /* if the if condition has a false label
8271 then we cannot save */
8275 /* if the minus is not of the form
8277 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8278 !IS_OP_LITERAL(IC_RIGHT(ic)))
8281 if (operandLitValue(IC_RIGHT(ic)) != 1)
8284 /* if the size of this greater than one then no
8286 if (getSize(operandType(IC_RESULT(ic))) > 1)
8289 /* otherwise we can save BIG */
8290 lbl = newiTempLabel(NULL);
8291 lbl1= newiTempLabel(NULL);
8293 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8295 if (IS_AOP_PREG(IC_RESULT(ic))) {
8296 emitcode("dec","%s",
8297 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8298 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8299 emitcode("jnz","%05d$",lbl->key+100);
8301 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8304 emitcode ("sjmp","%05d$",lbl1->key+100);
8305 emitcode ("","%05d$:",lbl->key+100);
8306 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8307 emitcode ("","%05d$:",lbl1->key+100);
8309 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8314 /*-----------------------------------------------------------------*/
8315 /* genReceive - generate code for a receive iCode */
8316 /*-----------------------------------------------------------------*/
8317 static void genReceive (iCode *ic)
8320 D(emitcode(";", "genReceive "););
8322 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8323 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8324 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8325 int size = getSize(operandType(IC_RESULT(ic)));
8326 int offset = fReturnSize_390 - size;
8328 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8329 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8332 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8333 size = AOP_SIZE(IC_RESULT(ic));
8336 emitcode ("pop","acc");
8337 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8342 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8344 assignResultValue(IC_RESULT(ic));
8347 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8350 /*-----------------------------------------------------------------*/
8351 /* gen390Code - generate code for Dallas 390 based controllers */
8352 /*-----------------------------------------------------------------*/
8353 void gen390Code (iCode *lic)
8358 lineHead = lineCurr = NULL;
8362 /* print the allocation information */
8364 printAllocInfo( currFunc, codeOutFile);
8366 /* if debug information required */
8367 if (options.debug && currFunc) {
8368 //jwk if (currFunc) {
8369 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8371 if (IS_STATIC(currFunc->etype))
8372 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8374 emitcode("","G$%s$0$0 ==.",currFunc->name);
8377 /* stack pointer name */
8378 if (options.useXstack)
8384 for (ic = lic ; ic ; ic = ic->next ) {
8386 if ( cln != ic->lineno ) {
8387 if ( options.debug ) {
8389 emitcode("","C$%s$%d$%d$%d ==.",
8390 ic->filename,ic->lineno,
8391 ic->level,ic->block);
8394 emitcode(";","%s %d",ic->filename,ic->lineno);
8397 /* if the result is marked as
8398 spilt and rematerializable or code for
8399 this has already been generated then
8401 if (resultRemat(ic) || ic->generated )
8404 /* depending on the operation */
8423 /* IPOP happens only when trying to restore a
8424 spilt live range, if there is an ifx statement
8425 following this pop then the if statement might
8426 be using some of the registers being popped which
8427 would destory the contents of the register so
8428 we need to check for this condition and handle it */
8430 ic->next->op == IFX &&
8431 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8432 genIfx (ic->next,ic);
8450 genEndFunction (ic);
8470 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8487 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8491 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8498 /* note these two are xlated by algebraic equivalence
8499 during parsing SDCC.y */
8500 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8501 "got '>=' or '<=' shouldn't have come here");
8505 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8517 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8521 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8525 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8552 case GET_VALUE_AT_ADDRESS:
8557 if (POINTER_SET(ic))
8584 addSet(&_G.sendSet,ic);
8589 /* piCode(ic,stdout); */
8595 /* now we are ready to call the
8596 peep hole optimizer */
8597 if (!options.nopeep)
8598 peepHole (&lineHead);
8600 /* now do the actual printing */
8601 printLine (lineHead,codeOutFile);