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 (sym_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];
718 /* a AOP_STR uses DPTR, but DPTR is already in use;
721 fprintf(stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
724 aop = op->aop = sym->aop = newAsmop(AOP_STR);
725 aop->size = getSize(sym->type);
726 for ( i = 0 ; i < fReturnSize_390 ; i++ )
727 aop->aopu.aop_str[i] = fReturn[i];
731 /* else spill location */
732 sym->aop = op->aop = aop =
733 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
734 aop->size = getSize(sym->type);
738 /* must be in a register */
739 sym->aop = op->aop = aop = newAsmop(AOP_REG);
740 aop->size = sym->nRegs;
741 for ( i = 0 ; i < sym->nRegs ;i++)
742 aop->aopu.aop_reg[i] = sym->regs[i];
745 /*-----------------------------------------------------------------*/
746 /* freeAsmop - free up the asmop given to an operand */
747 /*----------------------------------------------------------------*/
748 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
765 /* depending on the asmop type only three cases need work AOP_RO
766 , AOP_R1 && AOP_STK */
771 emitcode ("pop","ar0");
775 bitVectUnSetBit(ic->rUsed,R0_IDX);
781 emitcode ("pop","ar1");
785 bitVectUnSetBit(ic->rUsed,R1_IDX);
791 int stk = aop->aopu.aop_stk + aop->size;
792 bitVectUnSetBit(ic->rUsed,R0_IDX);
793 bitVectUnSetBit(ic->rUsed,R1_IDX);
795 getFreePtr(ic,&aop,FALSE);
797 if (options.stack10bit)
799 /* I'm not sure what to do here yet... */
802 "*** Warning: probably generating bad code for "
803 "10 bit stack mode.\n");
807 emitcode ("mov","a,_bp");
808 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
809 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
811 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
815 emitcode("pop","acc");
816 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
818 emitcode("dec","%s",aop->aopu.aop_ptr->name);
821 freeAsmop(op,NULL,ic,TRUE);
823 emitcode("pop","ar0");
828 emitcode("pop","ar1");
835 /* all other cases just dealloc */
839 OP_SYMBOL(op)->aop = NULL;
840 /* if the symbol has a spill */
842 SPIL_LOC(op)->aop = NULL;
847 /*------------------------------------------------------------------*/
848 /* aopGet - for fetching value of the aop */
850 /* Set canClobberACC if you are aure it is OK to clobber the value */
851 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe,*/
852 /* just less efficient. */
853 /*------------------------------------------------------------------*/
855 static char *aopGet (asmop *aop,
864 /* offset is greater than
866 if (offset > (aop->size - 1) &&
867 aop->type != AOP_LIT)
870 /* depending on type */
875 /* if we need to increment it */
876 while (offset > aop->coff) {
877 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
881 while (offset < aop->coff) {
882 emitcode("dec","%s",aop->aopu.aop_ptr->name);
888 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
889 return (dname ? "acc" : "a");
891 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
892 ALLOC_ATOMIC(rs,strlen(s)+1);
899 if (aop->type == AOP_DPTR2)
903 #ifndef KEVIN_BROKE_IT
907 emitcode("xch", "a, ap");
913 while (offset > aop->coff) {
914 emitcode ("inc","dptr");
918 while (offset < aop->coff) {
919 emitcode("lcall","__decdptr");
926 emitcode("movc","a,@a+dptr");
929 emitcode("movx","a,@dptr");
932 if (aop->type == AOP_DPTR2)
936 #ifndef KEVIN_BROKE_IT
940 emitcode("xch", "a, ap");
945 return (dname ? "acc" : "a");
949 sprintf (s,"#%s",aop->aopu.aop_immd);
952 sprintf(s,"#(%s >> %d)",
958 ALLOC_ATOMIC(rs,strlen(s)+1);
964 sprintf(s,"(%s + %d)",
968 sprintf(s,"%s",aop->aopu.aop_dir);
969 ALLOC_ATOMIC(rs,strlen(s)+1);
975 return aop->aopu.aop_reg[offset]->dname;
977 return aop->aopu.aop_reg[offset]->name;
981 emitcode("mov","c,%s",aop->aopu.aop_dir);
982 emitcode("rlc","a") ;
983 return (dname ? "acc" : "a");
986 if (!offset && dname)
988 return aop->aopu.aop_str[offset];
991 return aopLiteral (aop->aopu.aop_lit,offset);
995 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
999 return aop->aopu.aop_str[offset];
1003 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1004 "aopget got unsupported aop->type");
1007 /*-----------------------------------------------------------------*/
1008 /* aopPut - puts a string for a aop */
1009 /*-----------------------------------------------------------------*/
1010 static void aopPut (asmop *aop, char *s, int offset)
1015 if (aop->size && offset > ( aop->size - 1)) {
1016 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1017 "aopPut got offset > aop->size");
1021 /* will assign value to value */
1022 /* depending on where it is ofcourse */
1023 switch (aop->type) {
1026 sprintf(d,"(%s + %d)",
1027 aop->aopu.aop_dir,offset);
1029 sprintf(d,"%s",aop->aopu.aop_dir);
1032 emitcode("mov","%s,%s",d,s);
1037 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1038 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1040 strcmp(s,"r0") == 0 ||
1041 strcmp(s,"r1") == 0 ||
1042 strcmp(s,"r2") == 0 ||
1043 strcmp(s,"r3") == 0 ||
1044 strcmp(s,"r4") == 0 ||
1045 strcmp(s,"r5") == 0 ||
1046 strcmp(s,"r6") == 0 ||
1047 strcmp(s,"r7") == 0 )
1048 emitcode("mov","%s,%s",
1049 aop->aopu.aop_reg[offset]->dname,s);
1051 emitcode("mov","%s,%s",
1052 aop->aopu.aop_reg[offset]->name,s);
1059 if (aop->type == AOP_DPTR2)
1066 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1067 "aopPut writting to code space");
1071 while (offset > aop->coff) {
1073 emitcode ("inc","dptr");
1076 while (offset < aop->coff) {
1078 emitcode("lcall","__decdptr");
1083 /* if not in accumulater */
1086 emitcode ("movx","@dptr,a");
1088 if (aop->type == AOP_DPTR2)
1096 while (offset > aop->coff) {
1098 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1100 while (offset < aop->coff) {
1102 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1108 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1113 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1115 if (strcmp(s,"r0") == 0 ||
1116 strcmp(s,"r1") == 0 ||
1117 strcmp(s,"r2") == 0 ||
1118 strcmp(s,"r3") == 0 ||
1119 strcmp(s,"r4") == 0 ||
1120 strcmp(s,"r5") == 0 ||
1121 strcmp(s,"r6") == 0 ||
1122 strcmp(s,"r7") == 0 ) {
1124 sprintf(buffer,"a%s",s);
1125 emitcode("mov","@%s,%s",
1126 aop->aopu.aop_ptr->name,buffer);
1128 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1133 if (strcmp(s,"a") == 0)
1134 emitcode("push","acc");
1136 emitcode("push","%s",s);
1141 /* if bit variable */
1142 if (!aop->aopu.aop_dir) {
1143 emitcode("clr","a");
1144 emitcode("rlc","a");
1147 emitcode("clr","%s",aop->aopu.aop_dir);
1150 emitcode("setb","%s",aop->aopu.aop_dir);
1153 emitcode("mov","%s,c",aop->aopu.aop_dir);
1155 lbl = newiTempLabel(NULL);
1157 if (strcmp(s,"a")) {
1160 emitcode("clr","c");
1161 emitcode("jz","%05d$",lbl->key+100);
1162 emitcode("cpl","c");
1163 emitcode("","%05d$:",lbl->key+100);
1164 emitcode("mov","%s,c",aop->aopu.aop_dir);
1171 if (strcmp(aop->aopu.aop_str[offset],s))
1172 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1177 if (!offset && (strcmp(s,"acc") == 0))
1180 if (strcmp(aop->aopu.aop_str[offset],s))
1181 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1185 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1186 "aopPut got unsupported aop->type");
1193 /*-----------------------------------------------------------------*/
1194 /* reAdjustPreg - points a register back to where it should */
1195 /*-----------------------------------------------------------------*/
1196 static void reAdjustPreg (asmop *aop)
1201 if ((size = aop->size) <= 1)
1204 switch (aop->type) {
1208 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1212 if (aop->type == AOP_DPTR2)
1219 emitcode("lcall","__decdptr");
1222 if (aop->type == AOP_DPTR2)
1232 #define AOP(op) op->aop
1233 #define AOP_TYPE(op) AOP(op)->type
1234 #define AOP_SIZE(op) AOP(op)->size
1235 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1236 AOP_TYPE(x) == AOP_R0))
1238 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1239 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1242 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1243 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1244 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1246 /* Workaround for DS80C390 bug: div ab may return bogus results
1247 * if A is accessed in instruction immediately before the div.
1249 * Will be fixed in B4 rev of processor, Dallas claims.
1252 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1253 if (!AOP_NEEDSACC(RIGHT)) \
1255 /* We can load A first, then B, since \
1256 * B (the RIGHT operand) won't clobber A, \
1257 * thus avoiding touching A right before the div. \
1259 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1260 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1262 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1266 /* Just stuff in a nop after loading A. */ \
1267 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1268 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1270 emitcode("nop", "; workaround for DS80C390 div bug."); \
1273 /*-----------------------------------------------------------------*/
1274 /* genNotFloat - generates not for float operations */
1275 /*-----------------------------------------------------------------*/
1276 static void genNotFloat (operand *op, operand *res)
1282 D(emitcode(";", "genNotFloat "););
1284 /* we will put 127 in the first byte of
1286 aopPut(AOP(res),"#127",0);
1287 size = AOP_SIZE(op) - 1;
1290 _startLazyDPSEvaluation();
1291 l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
1295 emitcode("orl","a,%s",
1297 offset++,FALSE,FALSE,FALSE));
1299 _endLazyDPSEvaluation();
1300 tlbl = newiTempLabel(NULL);
1302 tlbl = newiTempLabel(NULL);
1303 aopPut(res->aop,one,1);
1304 emitcode("jz","%05d$",(tlbl->key+100));
1305 aopPut(res->aop,zero,1);
1306 emitcode("","%05d$:",(tlbl->key+100));
1308 size = res->aop->size - 2;
1310 /* put zeros in the rest */
1312 aopPut(res->aop,zero,offset++);
1315 /*-----------------------------------------------------------------*/
1316 /* opIsGptr: returns non-zero if the passed operand is */
1317 /* a generic pointer type. */
1318 /*-----------------------------------------------------------------*/
1319 static int opIsGptr(operand *op)
1321 sym_link *type = operandType(op);
1323 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1330 /*-----------------------------------------------------------------*/
1331 /* getDataSize - get the operand data size */
1332 /*-----------------------------------------------------------------*/
1333 static int getDataSize(operand *op)
1336 size = AOP_SIZE(op);
1337 if (size == GPTRSIZE)
1339 sym_link *type = operandType(op);
1340 if (IS_GENPTR(type))
1342 /* generic pointer; arithmetic operations
1343 * should ignore the high byte (pointer type).
1351 /*-----------------------------------------------------------------*/
1352 /* outAcc - output Acc */
1353 /*-----------------------------------------------------------------*/
1354 static void outAcc(operand *result)
1357 size = getDataSize(result);
1359 aopPut(AOP(result),"a",0);
1362 /* unsigned or positive */
1364 aopPut(AOP(result),zero,offset++);
1369 /*-----------------------------------------------------------------*/
1370 /* outBitC - output a bit C */
1371 /*-----------------------------------------------------------------*/
1372 static void outBitC(operand *result)
1374 /* if the result is bit */
1375 if (AOP_TYPE(result) == AOP_CRY)
1376 aopPut(AOP(result),"c",0);
1378 emitcode("clr","a");
1379 emitcode("rlc","a");
1384 /*-----------------------------------------------------------------*/
1385 /* toBoolean - emit code for orl a,operator(sizeop) */
1386 /*-----------------------------------------------------------------*/
1387 static void toBoolean(operand *oper)
1389 int size = AOP_SIZE(oper) - 1;
1392 /* The generic part of a generic pointer should
1393 * not participate in it's truth value.
1395 * i.e. 0x10000000 is zero.
1399 D(emitcode(";", "toBoolean: generic ptr special case."););
1403 _startLazyDPSEvaluation();
1404 if (AOP_NEEDSACC(oper))
1406 emitcode("push", "b");
1407 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1411 MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1415 if (AOP_NEEDSACC(oper))
1417 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1421 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1424 _endLazyDPSEvaluation();
1426 if (AOP_NEEDSACC(oper))
1428 emitcode("mov", "a,b");
1429 emitcode("pop", "b");
1434 /*-----------------------------------------------------------------*/
1435 /* genNot - generate code for ! operation */
1436 /*-----------------------------------------------------------------*/
1437 static void genNot (iCode *ic)
1440 sym_link *optype = operandType(IC_LEFT(ic));
1442 D(emitcode(";", "genNot "););
1444 /* assign asmOps to operand & result */
1445 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1446 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1448 /* if in bit space then a special case */
1449 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1450 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1451 emitcode("cpl","c");
1452 outBitC(IC_RESULT(ic));
1456 /* if type float then do float */
1457 if (IS_FLOAT(optype)) {
1458 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1462 toBoolean(IC_LEFT(ic));
1464 tlbl = newiTempLabel(NULL);
1465 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1466 emitcode("","%05d$:",tlbl->key+100);
1467 outBitC(IC_RESULT(ic));
1470 /* release the aops */
1471 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1472 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1476 /*-----------------------------------------------------------------*/
1477 /* genCpl - generate code for complement */
1478 /*-----------------------------------------------------------------*/
1479 static void genCpl (iCode *ic)
1484 D(emitcode(";", "genCpl "););
1487 /* assign asmOps to operand & result */
1488 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1489 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1491 /* if both are in bit space then
1493 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1494 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1496 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1497 emitcode("cpl","c");
1498 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1502 size = AOP_SIZE(IC_RESULT(ic));
1503 _startLazyDPSEvaluation();
1505 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1507 emitcode("cpl","a");
1508 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1510 _endLazyDPSEvaluation();
1514 /* release the aops */
1515 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1516 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1519 /*-----------------------------------------------------------------*/
1520 /* genUminusFloat - unary minus for floating points */
1521 /*-----------------------------------------------------------------*/
1522 static void genUminusFloat(operand *op,operand *result)
1524 int size ,offset =0 ;
1526 /* for this we just need to flip the
1527 first it then copy the rest in place */
1528 D(emitcode(";", "genUminusFloat"););
1530 _startLazyDPSEvaluation();
1531 size = AOP_SIZE(op) - 1;
1532 l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1535 emitcode("cpl","acc.7");
1536 aopPut(AOP(result),"a",3);
1540 aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1544 _endLazyDPSEvaluation();
1547 /*-----------------------------------------------------------------*/
1548 /* genUminus - unary minus code generation */
1549 /*-----------------------------------------------------------------*/
1550 static void genUminus (iCode *ic)
1553 sym_link *optype, *rtype;
1555 D(emitcode(";", "genUminus "););
1559 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1560 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1562 /* if both in bit space then special
1564 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1565 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1567 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1568 emitcode("cpl","c");
1569 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1573 optype = operandType(IC_LEFT(ic));
1574 rtype = operandType(IC_RESULT(ic));
1576 /* if float then do float stuff */
1577 if (IS_FLOAT(optype)) {
1578 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1582 /* otherwise subtract from zero */
1583 size = AOP_SIZE(IC_LEFT(ic));
1585 _startLazyDPSEvaluation();
1587 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1588 if (!strcmp(l,"a")) {
1591 emitcode("cpl","a");
1592 emitcode("addc", "a,#0");
1596 emitcode("clr","a");
1597 emitcode("subb","a,%s",l);
1599 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1601 _endLazyDPSEvaluation();
1603 /* if any remaining bytes in the result */
1604 /* we just need to propagate the sign */
1605 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1606 emitcode("rlc","a");
1607 emitcode("subb","a,acc");
1609 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1613 /* release the aops */
1614 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1615 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1618 /*-----------------------------------------------------------------*/
1619 /* saveRegisters - will look for a call and save the registers */
1620 /*-----------------------------------------------------------------*/
1621 static void saveRegisters(iCode *lic)
1629 for (ic = lic ; ic ; ic = ic->next)
1630 if (ic->op == CALL || ic->op == PCALL)
1634 fprintf(stderr,"found parameter push with no function call\n");
1638 /* if the registers have been saved already then
1640 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1643 /* find the registers in use at this time
1644 and push them away to safety */
1645 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1649 if (options.useXstack) {
1650 if (bitVectBitValue(rsave,R0_IDX))
1651 emitcode("mov","b,r0");
1652 emitcode("mov","r0,%s",spname);
1653 for (i = 0 ; i < ds390_nRegs ; i++) {
1654 if (bitVectBitValue(rsave,i)) {
1656 emitcode("mov","a,b");
1658 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1659 emitcode("movx","@r0,a");
1660 emitcode("inc","r0");
1663 emitcode("mov","%s,r0",spname);
1664 if (bitVectBitValue(rsave,R0_IDX))
1665 emitcode("mov","r0,b");
1667 for (i = 0 ; i < ds390_nRegs ; i++) {
1668 if (bitVectBitValue(rsave,i))
1669 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1672 detype = getSpec(operandType(IC_LEFT(ic)));
1674 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1675 IS_ISR(currFunc->etype) &&
1678 saverbank(SPEC_BANK(detype),ic,TRUE);
1681 /*-----------------------------------------------------------------*/
1682 /* unsaveRegisters - pop the pushed registers */
1683 /*-----------------------------------------------------------------*/
1684 static void unsaveRegisters (iCode *ic)
1688 /* find the registers in use at this time
1689 and push them away to safety */
1690 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1693 if (options.useXstack) {
1694 emitcode("mov","r0,%s",spname);
1695 for (i = ds390_nRegs ; i >= 0 ; i--) {
1696 if (bitVectBitValue(rsave,i)) {
1697 emitcode("dec","r0");
1698 emitcode("movx","a,@r0");
1700 emitcode("mov","b,a");
1702 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1706 emitcode("mov","%s,r0",spname);
1707 if (bitVectBitValue(rsave,R0_IDX))
1708 emitcode("mov","r0,b");
1710 for (i = ds390_nRegs ; i >= 0 ; i--) {
1711 if (bitVectBitValue(rsave,i))
1712 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1718 /*-----------------------------------------------------------------*/
1720 /*-----------------------------------------------------------------*/
1721 static void pushSide(operand * oper, int size)
1724 _startLazyDPSEvaluation();
1726 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1727 if (AOP_TYPE(oper) != AOP_REG &&
1728 AOP_TYPE(oper) != AOP_DIR &&
1730 emitcode("mov","a,%s",l);
1731 emitcode("push","acc");
1733 emitcode("push","%s",l);
1735 _endLazyDPSEvaluation();
1738 /*-----------------------------------------------------------------*/
1739 /* assignResultValue - */
1740 /*-----------------------------------------------------------------*/
1741 static void assignResultValue(operand * oper)
1744 int size = AOP_SIZE(oper);
1746 _startLazyDPSEvaluation();
1748 aopPut(AOP(oper),fReturn[offset],offset);
1751 _endLazyDPSEvaluation();
1755 /*-----------------------------------------------------------------*/
1756 /* genXpush - pushes onto the external stack */
1757 /*-----------------------------------------------------------------*/
1758 static void genXpush (iCode *ic)
1760 asmop *aop = newAsmop(0);
1762 int size,offset = 0;
1764 D(emitcode(";", "genXpush "););
1766 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1767 r = getFreePtr(ic,&aop,FALSE);
1770 emitcode("mov","%s,_spx",r->name);
1772 size = AOP_SIZE(IC_LEFT(ic));
1773 _startLazyDPSEvaluation();
1776 char *l = aopGet(AOP(IC_LEFT(ic)),
1777 offset++,FALSE,FALSE,TRUE);
1779 emitcode("movx","@%s,a",r->name);
1780 emitcode("inc","%s",r->name);
1783 _endLazyDPSEvaluation();
1786 emitcode("mov","_spx,%s",r->name);
1788 freeAsmop(NULL,aop,ic,TRUE);
1789 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1792 /*-----------------------------------------------------------------*/
1793 /* genIpush - genrate code for pushing this gets a little complex */
1794 /*-----------------------------------------------------------------*/
1795 static void genIpush (iCode *ic)
1797 int size, offset = 0 ;
1800 D(emitcode(";", "genIpush "););
1803 /* if this is not a parm push : ie. it is spill push
1804 and spill push is always done on the local stack */
1805 if (!ic->parmPush) {
1807 /* and the item is spilt then do nothing */
1808 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1811 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1812 size = AOP_SIZE(IC_LEFT(ic));
1813 /* push it on the stack */
1814 _startLazyDPSEvaluation();
1816 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1821 emitcode("push","%s",l);
1823 _endLazyDPSEvaluation();
1827 /* this is a paramter push: in this case we call
1828 the routine to find the call and save those
1829 registers that need to be saved */
1832 /* if use external stack then call the external
1833 stack pushing routine */
1834 if (options.useXstack) {
1839 /* then do the push */
1840 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1842 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1843 size = AOP_SIZE(IC_LEFT(ic));
1845 _startLazyDPSEvaluation();
1847 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1848 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1849 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1851 emitcode("mov","a,%s",l);
1852 emitcode("push","acc");
1854 emitcode("push","%s",l);
1856 _endLazyDPSEvaluation();
1858 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1861 /*-----------------------------------------------------------------*/
1862 /* genIpop - recover the registers: can happen only for spilling */
1863 /*-----------------------------------------------------------------*/
1864 static void genIpop (iCode *ic)
1868 D(emitcode(";", "genIpop "););
1871 /* if the temp was not pushed then */
1872 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1875 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1876 size = AOP_SIZE(IC_LEFT(ic));
1878 _startLazyDPSEvaluation();
1881 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1884 _endLazyDPSEvaluation();
1886 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1889 /*-----------------------------------------------------------------*/
1890 /* unsaverbank - restores the resgister bank from stack */
1891 /*-----------------------------------------------------------------*/
1892 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1899 if (options.useXstack) {
1901 r = getFreePtr(ic,&aop,FALSE);
1904 emitcode("mov","%s,_spx",r->name);
1905 emitcode("movx","a,@%s",r->name);
1906 emitcode("mov","psw,a");
1907 emitcode("dec","%s",r->name);
1910 emitcode ("pop","psw");
1913 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1914 if (options.useXstack) {
1915 emitcode("movx","a,@%s",r->name);
1916 emitcode("mov","(%s+%d),a",
1917 regs390[i].base,8*bank+regs390[i].offset);
1918 emitcode("dec","%s",r->name);
1921 emitcode("pop","(%s+%d)",
1922 regs390[i].base,8*bank+regs390[i].offset);
1925 if (options.useXstack) {
1927 emitcode("mov","_spx,%s",r->name);
1928 freeAsmop(NULL,aop,ic,TRUE);
1933 /*-----------------------------------------------------------------*/
1934 /* saverbank - saves an entire register bank on the stack */
1935 /*-----------------------------------------------------------------*/
1936 static void saverbank (int bank, iCode *ic, bool pushPsw)
1942 if (options.useXstack) {
1945 r = getFreePtr(ic,&aop,FALSE);
1946 emitcode("mov","%s,_spx",r->name);
1950 for (i = 0 ; i < ds390_nRegs ;i++) {
1951 if (options.useXstack) {
1952 emitcode("inc","%s",r->name);
1953 emitcode("mov","a,(%s+%d)",
1954 regs390[i].base,8*bank+regs390[i].offset);
1955 emitcode("movx","@%s,a",r->name);
1957 emitcode("push","(%s+%d)",
1958 regs390[i].base,8*bank+regs390[i].offset);
1962 if (options.useXstack) {
1963 emitcode("mov","a,psw");
1964 emitcode("movx","@%s,a",r->name);
1965 emitcode("inc","%s",r->name);
1966 emitcode("mov","_spx,%s",r->name);
1967 freeAsmop (NULL,aop,ic,TRUE);
1970 emitcode("push","psw");
1972 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1978 /*-----------------------------------------------------------------*/
1979 /* genCall - generates a call statement */
1980 /*-----------------------------------------------------------------*/
1981 static void genCall (iCode *ic)
1985 D(emitcode(";", "genCall "););
1987 /* if caller saves & we have not saved then */
1991 /* if we are calling a function that is not using
1992 the same register bank then we need to save the
1993 destination registers on the stack */
1994 detype = getSpec(operandType(IC_LEFT(ic)));
1996 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1997 IS_ISR(currFunc->etype) &&
2000 saverbank(SPEC_BANK(detype),ic,TRUE);
2002 /* if send set is not empty the assign */
2006 for (sic = setFirstItem(_G.sendSet) ; sic ;
2007 sic = setNextItem(_G.sendSet))
2009 int size, offset = 0;
2011 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
2012 size = AOP_SIZE(IC_LEFT(sic));
2014 _startLazyDPSEvaluation();
2016 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2017 FALSE, FALSE, TRUE);
2018 if (strcmp(l,fReturn[offset]))
2019 emitcode("mov","%s,%s",
2024 _endLazyDPSEvaluation();
2025 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2030 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2031 OP_SYMBOL(IC_LEFT(ic))->rname :
2032 OP_SYMBOL(IC_LEFT(ic))->name));
2034 /* if we need assign a result value */
2035 if ((IS_ITEMP(IC_RESULT(ic)) &&
2036 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2037 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2038 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2041 /* Not really related to LAZY_DPS_OPT, but don't want
2042 * another testing flag right now...
2044 #define FAR_RETURN_OPT
2045 #ifdef FAR_RETURN_OPT
2046 if (isOperandInFarSpace(IC_RESULT(ic))
2047 && getSize(operandType(IC_RESULT(ic))) <= 2)
2049 int size = getSize(operandType(IC_RESULT(ic)));
2051 /* Special case for 1 or 2 byte return in far space. */
2052 emitcode(";", "Kevin function call abuse #1");
2057 emitcode("mov", "b,%s", fReturn[1]);
2060 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2061 aopPut(AOP(IC_RESULT(ic)),"a",0);
2065 aopPut(AOP(IC_RESULT(ic)),"b",1);
2067 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2073 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2076 assignResultValue(IC_RESULT(ic));
2078 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2081 if (!isOperandInFarSpace(IC_RESULT(ic)))
2084 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2087 assignResultValue(IC_RESULT(ic));
2089 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2093 /* Result is in far space, and requires DPTR to access
2094 * it. Push the result onto the stack and restore from
2097 int size = getSize(operandType(IC_RESULT(ic)));
2098 int offset = size - 1;
2101 emitcode(";", "Kevin function call abuse #1");
2103 /* first push the right side on to the stack */
2104 /* NB: this relies on the fact that "a" is the last
2105 * register in fReturn. If it were not, the MOVA
2106 * would potentially clobber a returned byte in A.
2109 l = fReturn[offset--];
2111 emitcode ("push","acc");
2114 /* now assign DPTR to result */
2115 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2116 size = AOP_SIZE(IC_RESULT(ic));
2117 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
2119 emitcode ("pop","acc");
2120 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
2122 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2127 /* adjust the stack for parameters if
2129 if (IC_LEFT(ic)->parmBytes) {
2131 if (IC_LEFT(ic)->parmBytes > 3) {
2132 emitcode("mov","a,%s",spname);
2133 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2134 emitcode("mov","%s,a",spname);
2136 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2137 emitcode("dec","%s",spname);
2141 /* if register bank was saved then pop them */
2143 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2145 /* if we hade saved some registers then unsave them */
2146 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2147 unsaveRegisters (ic);
2152 /*-----------------------------------------------------------------*/
2153 /* genPcall - generates a call by pointer statement */
2154 /*-----------------------------------------------------------------*/
2155 static void genPcall (iCode *ic)
2158 symbol *rlbl = newiTempLabel(NULL);
2160 D(emitcode(";", "genPcall "););
2163 /* if caller saves & we have not saved then */
2167 /* if we are calling a function that is not using
2168 the same register bank then we need to save the
2169 destination registers on the stack */
2170 detype = getSpec(operandType(IC_LEFT(ic)));
2172 IS_ISR(currFunc->etype) &&
2173 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2174 saverbank(SPEC_BANK(detype),ic,TRUE);
2177 /* push the return address on to the stack */
2178 emitcode("mov","a,#%05d$",(rlbl->key+100));
2179 emitcode("push","acc");
2180 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2181 emitcode("push","acc");
2183 if (options.model == MODEL_FLAT24)
2185 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2186 emitcode("push","acc");
2189 /* now push the calling address */
2190 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2192 pushSide(IC_LEFT(ic), FPTRSIZE);
2194 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2196 /* if send set is not empty the assign */
2200 for (sic = setFirstItem(_G.sendSet) ; sic ;
2201 sic = setNextItem(_G.sendSet))
2203 int size, offset = 0;
2205 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2206 size = AOP_SIZE(IC_LEFT(sic));
2207 _startLazyDPSEvaluation();
2210 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2212 if (strcmp(l,fReturn[offset]))
2214 emitcode("mov","%s,%s",
2220 _endLazyDPSEvaluation();
2221 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2227 emitcode("","%05d$:",(rlbl->key+100));
2230 /* if we need assign a result value */
2231 if ((IS_ITEMP(IC_RESULT(ic)) &&
2232 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2233 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2234 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2237 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2240 assignResultValue(IC_RESULT(ic));
2242 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2245 /* adjust the stack for parameters if
2247 if (IC_LEFT(ic)->parmBytes) {
2249 if (IC_LEFT(ic)->parmBytes > 3) {
2250 emitcode("mov","a,%s",spname);
2251 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2252 emitcode("mov","%s,a",spname);
2254 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2255 emitcode("dec","%s",spname);
2259 /* if register bank was saved then unsave them */
2261 (SPEC_BANK(currFunc->etype) !=
2263 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2265 /* if we hade saved some registers then
2268 unsaveRegisters (ic);
2272 /*-----------------------------------------------------------------*/
2273 /* resultRemat - result is rematerializable */
2274 /*-----------------------------------------------------------------*/
2275 static int resultRemat (iCode *ic)
2277 if (SKIP_IC(ic) || ic->op == IFX)
2280 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2281 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2282 if (sym->remat && !POINTER_SET(ic))
2290 #define STRCASECMP stricmp
2292 #define STRCASECMP strcasecmp
2295 /*-----------------------------------------------------------------*/
2296 /* inExcludeList - return 1 if the string is in exclude Reg list */
2297 /*-----------------------------------------------------------------*/
2298 static bool inExcludeList(char *s)
2302 if (options.excludeRegs[i] &&
2303 STRCASECMP(options.excludeRegs[i],"none") == 0)
2306 for ( i = 0 ; options.excludeRegs[i]; i++) {
2307 if (options.excludeRegs[i] &&
2308 STRCASECMP(s,options.excludeRegs[i]) == 0)
2314 /*-----------------------------------------------------------------*/
2315 /* genFunction - generated code for function entry */
2316 /*-----------------------------------------------------------------*/
2317 static void genFunction (iCode *ic)
2322 D(emitcode(";", "genFunction "););
2325 /* create the function header */
2326 emitcode(";","-----------------------------------------");
2327 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2328 emitcode(";","-----------------------------------------");
2330 emitcode("","%s:",sym->rname);
2331 fetype = getSpec(operandType(IC_LEFT(ic)));
2333 /* if critical function then turn interrupts off */
2334 if (SPEC_CRTCL(fetype))
2335 emitcode("clr","ea");
2337 /* here we need to generate the equates for the
2338 register bank if required */
2339 if (SPEC_BANK(fetype) != rbank) {
2342 rbank = SPEC_BANK(fetype);
2343 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2344 if (strcmp(regs390[i].base,"0") == 0)
2345 emitcode("","%s = 0x%02x",
2347 8*rbank+regs390[i].offset);
2349 emitcode ("","%s = %s + 0x%02x",
2352 8*rbank+regs390[i].offset);
2356 /* if this is an interrupt service routine then
2357 save acc, b, dpl, dph */
2358 if (IS_ISR(sym->etype)) {
2360 if (!inExcludeList("acc"))
2361 emitcode ("push","acc");
2362 if (!inExcludeList("b"))
2363 emitcode ("push","b");
2364 if (!inExcludeList("dpl"))
2365 emitcode ("push","dpl");
2366 if (!inExcludeList("dph"))
2367 emitcode ("push","dph");
2368 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2370 emitcode ("push", "dpx");
2371 /* Make sure we're using standard DPTR */
2372 emitcode ("push", "dps");
2373 emitcode ("mov", "dps, #0x00");
2374 if (options.stack10bit)
2376 /* This ISR could conceivably use DPTR2. Better save it. */
2377 emitcode ("push", "dpl1");
2378 emitcode ("push", "dph1");
2379 emitcode ("push", "dpx1");
2380 emitcode ("push", "ap");
2383 /* if this isr has no bank i.e. is going to
2384 run with bank 0 , then we need to save more
2386 if (!SPEC_BANK(sym->etype)) {
2388 /* if this function does not call any other
2389 function then we can be economical and
2390 save only those registers that are used */
2391 if (! sym->hasFcall) {
2394 /* if any registers used */
2395 if (sym->regsUsed) {
2396 /* save the registers used */
2397 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2398 if (bitVectBitValue(sym->regsUsed,i) ||
2399 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2400 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2405 /* this function has a function call cannot
2406 determines register usage so we will have the
2408 saverbank(0,ic,FALSE);
2412 /* if callee-save to be used for this function
2413 then save the registers being used in this function */
2414 if (sym->calleeSave) {
2417 /* if any registers used */
2418 if (sym->regsUsed) {
2419 /* save the registers used */
2420 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2421 if (bitVectBitValue(sym->regsUsed,i) ||
2422 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2423 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2431 /* set the register bank to the desired value */
2432 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2433 emitcode("push","psw");
2434 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2437 if (IS_RENT(sym->etype) || options.stackAuto) {
2439 if (options.useXstack) {
2440 emitcode("mov","r0,%s",spname);
2441 emitcode("mov","a,_bp");
2442 emitcode("movx","@r0,a");
2443 emitcode("inc","%s",spname);
2447 /* set up the stack */
2448 emitcode ("push","_bp"); /* save the callers stack */
2450 emitcode ("mov","_bp,%s",spname);
2453 /* adjust the stack for the function */
2458 werror(W_STACK_OVERFLOW,sym->name);
2460 if (i > 3 && sym->recvSize < 4) {
2462 emitcode ("mov","a,sp");
2463 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2464 emitcode ("mov","sp,a");
2469 emitcode("inc","sp");
2474 emitcode ("mov","a,_spx");
2475 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2476 emitcode ("mov","_spx,a");
2481 /*-----------------------------------------------------------------*/
2482 /* genEndFunction - generates epilogue for functions */
2483 /*-----------------------------------------------------------------*/
2484 static void genEndFunction (iCode *ic)
2486 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2488 D(emitcode(";", "genEndFunction "););
2490 if (IS_RENT(sym->etype) || options.stackAuto)
2492 emitcode ("mov","%s,_bp",spname);
2495 /* if use external stack but some variables were
2496 added to the local stack then decrement the
2498 if (options.useXstack && sym->stack) {
2499 emitcode("mov","a,sp");
2500 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2501 emitcode("mov","sp,a");
2505 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2506 if (options.useXstack) {
2507 emitcode("mov","r0,%s",spname);
2508 emitcode("movx","a,@r0");
2509 emitcode("mov","_bp,a");
2510 emitcode("dec","%s",spname);
2514 emitcode ("pop","_bp");
2518 /* restore the register bank */
2519 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2520 emitcode ("pop","psw");
2522 if (IS_ISR(sym->etype)) {
2524 /* now we need to restore the registers */
2525 /* if this isr has no bank i.e. is going to
2526 run with bank 0 , then we need to save more
2528 if (!SPEC_BANK(sym->etype)) {
2530 /* if this function does not call any other
2531 function then we can be economical and
2532 save only those registers that are used */
2533 if (! sym->hasFcall) {
2536 /* if any registers used */
2537 if (sym->regsUsed) {
2538 /* save the registers used */
2539 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2540 if (bitVectBitValue(sym->regsUsed,i) ||
2541 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2542 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2547 /* this function has a function call cannot
2548 determines register usage so we will have the
2550 unsaverbank(0,ic,FALSE);
2554 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2556 if (options.stack10bit)
2558 emitcode ("pop", "ap");
2559 emitcode ("pop", "dpx1");
2560 emitcode ("pop", "dph1");
2561 emitcode ("pop", "dpl1");
2563 emitcode ("pop", "dps");
2564 emitcode ("pop", "dpx");
2566 if (!inExcludeList("dph"))
2567 emitcode ("pop","dph");
2568 if (!inExcludeList("dpl"))
2569 emitcode ("pop","dpl");
2570 if (!inExcludeList("b"))
2571 emitcode ("pop","b");
2572 if (!inExcludeList("acc"))
2573 emitcode ("pop","acc");
2575 if (SPEC_CRTCL(sym->etype))
2576 emitcode("setb","ea");
2578 /* if debug then send end of function */
2579 /* if (options.debug && currFunc) { */
2582 emitcode("","C$%s$%d$%d$%d ==.",
2583 ic->filename,currFunc->lastLine,
2584 ic->level,ic->block);
2585 if (IS_STATIC(currFunc->etype))
2586 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2588 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2592 emitcode ("reti","");
2595 if (SPEC_CRTCL(sym->etype))
2596 emitcode("setb","ea");
2598 if (sym->calleeSave) {
2601 /* if any registers used */
2602 if (sym->regsUsed) {
2603 /* save the registers used */
2604 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2605 if (bitVectBitValue(sym->regsUsed,i) ||
2606 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2607 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2613 /* if debug then send end of function */
2616 emitcode("","C$%s$%d$%d$%d ==.",
2617 ic->filename,currFunc->lastLine,
2618 ic->level,ic->block);
2619 if (IS_STATIC(currFunc->etype))
2620 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2622 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2626 emitcode ("ret","");
2631 /*-----------------------------------------------------------------*/
2632 /* genRet - generate code for return statement */
2633 /*-----------------------------------------------------------------*/
2634 static void genRet (iCode *ic)
2636 int size,offset = 0 , pushed = 0;
2638 D(emitcode(";", "genRet "););
2640 /* if we have no return value then
2641 just generate the "ret" */
2645 /* we have something to return then
2646 move the return value into place */
2647 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2648 size = AOP_SIZE(IC_LEFT(ic));
2650 _startLazyDPSEvaluation();
2653 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2654 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2656 emitcode("push","%s",l);
2659 l = aopGet(AOP(IC_LEFT(ic)),offset,
2661 if (strcmp(fReturn[offset],l))
2662 emitcode("mov","%s,%s",fReturn[offset++],l);
2665 _endLazyDPSEvaluation();
2670 if (strcmp(fReturn[pushed],"a"))
2671 emitcode("pop",fReturn[pushed]);
2673 emitcode("pop","acc");
2676 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2679 /* generate a jump to the return label
2680 if the next is not the return statement */
2681 if (!(ic->next && ic->next->op == LABEL &&
2682 IC_LABEL(ic->next) == returnLabel))
2684 emitcode("ljmp","%05d$",(returnLabel->key+100));
2688 /*-----------------------------------------------------------------*/
2689 /* genLabel - generates a label */
2690 /*-----------------------------------------------------------------*/
2691 static void genLabel (iCode *ic)
2693 /* special case never generate */
2694 if (IC_LABEL(ic) == entryLabel)
2697 D(emitcode(";", "genLabel "););
2699 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2702 /*-----------------------------------------------------------------*/
2703 /* genGoto - generates a ljmp */
2704 /*-----------------------------------------------------------------*/
2705 static void genGoto (iCode *ic)
2707 D(emitcode(";", "genGoto "););
2708 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2711 /*-----------------------------------------------------------------*/
2712 /* findLabelBackwards: walks back through the iCode chain looking */
2713 /* for the given label. Returns number of iCode instructions */
2714 /* between that label and given ic. */
2715 /* Returns zero if label not found. */
2716 /*-----------------------------------------------------------------*/
2717 static int findLabelBackwards(iCode *ic, int key)
2726 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2728 /* printf("findLabelBackwards = %d\n", count); */
2736 /*-----------------------------------------------------------------*/
2737 /* genPlusIncr :- does addition with increment if possible */
2738 /*-----------------------------------------------------------------*/
2739 static bool genPlusIncr (iCode *ic)
2741 unsigned int icount ;
2742 unsigned int size = getDataSize(IC_RESULT(ic));
2744 /* will try to generate an increment */
2745 /* if the right side is not a literal
2747 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2750 /* if the literal value of the right hand side
2751 is greater than 4 then it is not worth it */
2752 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2755 /* if increment 16 bits in register */
2757 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2758 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2759 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2766 /* If the next instruction is a goto and the goto target
2767 * is <= 5 instructions previous to this, we can generate
2768 * jumps straight to that target.
2770 if (ic->next && ic->next->op == GOTO
2771 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2772 && labelRange <= 5 )
2774 emitcode(";", "tail increment optimized (range %d)", labelRange);
2775 tlbl = IC_LABEL(ic->next);
2780 tlbl = newiTempLabel(NULL);
2783 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2784 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2785 IS_AOP_PREG(IC_RESULT(ic)))
2786 emitcode("cjne","%s,#0x00,%05d$"
2787 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2790 emitcode("clr","a");
2791 emitcode("cjne","a,%s,%05d$"
2792 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2796 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2799 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2800 IS_AOP_PREG(IC_RESULT(ic)))
2801 emitcode("cjne","%s,#0x00,%05d$"
2802 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2805 emitcode("cjne","a,%s,%05d$"
2806 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2809 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2813 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2814 IS_AOP_PREG(IC_RESULT(ic)))
2815 emitcode("cjne","%s,#0x00,%05d$"
2816 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2819 emitcode("cjne","a,%s,%05d$"
2820 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2823 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2828 emitcode("","%05d$:",tlbl->key+100);
2833 /* if the sizes are greater than 1 then we cannot */
2834 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2835 AOP_SIZE(IC_LEFT(ic)) > 1 )
2838 /* we can if the aops of the left & result match or
2839 if they are in registers and the registers are the
2842 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2843 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2844 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2847 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2848 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2849 aopPut(AOP(IC_RESULT(ic)),"a",0);
2852 _startLazyDPSEvaluation();
2855 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2857 _endLazyDPSEvaluation();
2866 /*-----------------------------------------------------------------*/
2867 /* outBitAcc - output a bit in acc */
2868 /*-----------------------------------------------------------------*/
2869 static void outBitAcc(operand *result)
2871 symbol *tlbl = newiTempLabel(NULL);
2872 /* if the result is a bit */
2873 if (AOP_TYPE(result) == AOP_CRY){
2874 aopPut(AOP(result),"a",0);
2877 emitcode("jz","%05d$",tlbl->key+100);
2878 emitcode("mov","a,%s",one);
2879 emitcode("","%05d$:",tlbl->key+100);
2884 /*-----------------------------------------------------------------*/
2885 /* genPlusBits - generates code for addition of two bits */
2886 /*-----------------------------------------------------------------*/
2887 static void genPlusBits (iCode *ic)
2889 D(emitcode(";", "genPlusBits "););
2890 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2891 symbol *lbl = newiTempLabel(NULL);
2892 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2893 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2894 emitcode("cpl","c");
2895 emitcode("","%05d$:",(lbl->key+100));
2896 outBitC(IC_RESULT(ic));
2899 emitcode("clr","a");
2900 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2901 emitcode("rlc","a");
2902 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2903 emitcode("addc","a,#0x00");
2904 outAcc(IC_RESULT(ic));
2908 static void adjustArithmeticResult(iCode *ic)
2910 if (opIsGptr(IC_RESULT(ic)) &&
2911 opIsGptr(IC_LEFT(ic)) &&
2912 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2914 aopPut(AOP(IC_RESULT(ic)),
2915 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2919 if (opIsGptr(IC_RESULT(ic)) &&
2920 opIsGptr(IC_RIGHT(ic)) &&
2921 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2923 aopPut(AOP(IC_RESULT(ic)),
2924 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2928 if (opIsGptr(IC_RESULT(ic)) &&
2929 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2930 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2931 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2932 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2934 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2935 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2939 #define AOP_OP_3(ic) \
2940 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2941 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2942 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2943 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2944 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2946 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2948 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2951 #define AOP_SET_LOCALS(ic) \
2952 left = IC_LEFT(ic); \
2953 right = IC_RIGHT(ic); \
2954 result = IC_RESULT(ic);
2956 /*-----------------------------------------------------------------*/
2957 /* genPlus - generates code for addition */
2958 /*-----------------------------------------------------------------*/
2959 static void genPlus (iCode *ic)
2961 int size, offset = 0;
2962 bool pushResult = FALSE;
2965 D(emitcode(";", "genPlus "););
2967 /* special cases :- */
2970 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2971 aopOp (IC_LEFT(ic),ic,FALSE,
2972 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
2974 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2975 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2977 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2978 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2984 aopOp (IC_RESULT(ic),ic,TRUE,
2985 ((AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)
2986 || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR)));
2988 /* if literal, literal on the right or
2989 if left requires ACC or right is already
2991 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2992 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2993 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2994 operand *t = IC_RIGHT(ic);
2995 IC_RIGHT(ic) = IC_LEFT(ic);
2999 /* if both left & right are in bit
3001 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3002 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3007 /* if left in bit space & right literal */
3008 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3009 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3010 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3011 /* if result in bit space */
3012 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3013 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
3014 emitcode("cpl","c");
3015 outBitC(IC_RESULT(ic));
3017 size = getDataSize(IC_RESULT(ic));
3018 _startLazyDPSEvaluation();
3020 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3021 emitcode("addc","a,#00");
3022 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3024 _endLazyDPSEvaluation();
3029 /* if I can do an increment instead
3030 of add then GOOD for ME */
3031 if (genPlusIncr (ic) == TRUE)
3035 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3037 _startLazyDPSEvaluation();
3040 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3042 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3044 emitcode("add","a,%s",
3045 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3047 emitcode("addc","a,%s",
3048 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3050 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3052 emitcode("add","a,%s",
3053 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3055 emitcode("addc","a,%s",
3056 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3060 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3064 emitcode("push", "acc");
3068 _endLazyDPSEvaluation();
3072 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3074 size = getDataSize(IC_LEFT(ic));
3075 rSize = getDataSize(IC_RESULT(ic));
3077 /* If the pushed data is bigger than the result,
3078 * simply discard unused bytes. Icky, but works.
3080 * Should we throw a warning here? We're losing data...
3082 while (size > rSize)
3084 D(emitcode(";", "discarding unused result byte."););
3085 emitcode("pop", "acc");
3091 emitcode("clr", "a");
3092 /* Conversly, we haven't pushed enough here.
3093 * just zero-pad, and all is well.
3095 while (size < rSize)
3097 emitcode("push", "acc");
3103 _startLazyDPSEvaluation();
3106 emitcode("pop", "acc");
3107 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3109 _endLazyDPSEvaluation();
3112 adjustArithmeticResult(ic);
3115 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3116 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3117 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3120 /*-----------------------------------------------------------------*/
3121 /* genMinusDec :- does subtraction with deccrement if possible */
3122 /*-----------------------------------------------------------------*/
3123 static bool genMinusDec (iCode *ic)
3125 unsigned int icount ;
3126 unsigned int size = getDataSize(IC_RESULT(ic));
3128 /* will try to generate an increment */
3129 /* if the right side is not a literal
3131 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3134 /* if the literal value of the right hand side
3135 is greater than 4 then it is not worth it */
3136 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3139 /* if decrement 16 bits in register */
3140 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3141 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3142 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3149 /* If the next instruction is a goto and the goto target
3150 * is <= 5 instructions previous to this, we can generate
3151 * jumps straight to that target.
3153 if (ic->next && ic->next->op == GOTO
3154 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3155 && labelRange <= 5 )
3157 emitcode(";", "tail decrement optimized (range %d)", labelRange);
3158 tlbl = IC_LABEL(ic->next);
3163 tlbl = newiTempLabel(NULL);
3167 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3168 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3169 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3170 IS_AOP_PREG(IC_RESULT(ic)))
3171 emitcode("cjne","%s,#0xff,%05d$"
3172 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3175 emitcode("mov","a,#0xff");
3176 emitcode("cjne","a,%s,%05d$"
3177 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3180 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3183 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3184 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3185 IS_AOP_PREG(IC_RESULT(ic)))
3186 emitcode("cjne","%s,#0xff,%05d$"
3187 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3190 emitcode("cjne","a,%s,%05d$"
3191 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3194 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3198 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3199 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3200 IS_AOP_PREG(IC_RESULT(ic)))
3201 emitcode("cjne","%s,#0xff,%05d$"
3202 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3205 emitcode("cjne","a,%s,%05d$"
3206 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3209 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3213 emitcode("","%05d$:",tlbl->key+100);
3218 /* if the sizes are greater than 1 then we cannot */
3219 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3220 AOP_SIZE(IC_LEFT(ic)) > 1 )
3223 /* we can if the aops of the left & result match or
3224 if they are in registers and the registers are the
3227 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3228 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3229 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3231 _startLazyDPSEvaluation();
3234 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3236 _endLazyDPSEvaluation();
3244 /*-----------------------------------------------------------------*/
3245 /* addSign - complete with sign */
3246 /*-----------------------------------------------------------------*/
3247 static void addSign(operand *result, int offset, int sign)
3249 int size = (getDataSize(result) - offset);
3252 emitcode("rlc","a");
3253 emitcode("subb","a,acc");
3255 aopPut(AOP(result),"a",offset++);
3258 aopPut(AOP(result),zero,offset++);
3262 /*-----------------------------------------------------------------*/
3263 /* genMinusBits - generates code for subtraction of two bits */
3264 /*-----------------------------------------------------------------*/
3265 static void genMinusBits (iCode *ic)
3267 symbol *lbl = newiTempLabel(NULL);
3269 D(emitcode(";", "genMinusBits "););
3271 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3272 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3273 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3274 emitcode("cpl","c");
3275 emitcode("","%05d$:",(lbl->key+100));
3276 outBitC(IC_RESULT(ic));
3279 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3280 emitcode("subb","a,acc");
3281 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3282 emitcode("inc","a");
3283 emitcode("","%05d$:",(lbl->key+100));
3284 aopPut(AOP(IC_RESULT(ic)),"a",0);
3285 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3289 /*-----------------------------------------------------------------*/
3290 /* genMinus - generates code for subtraction */
3291 /*-----------------------------------------------------------------*/
3292 static void genMinus (iCode *ic)
3294 int size, offset = 0;
3296 unsigned long lit = 0L;
3297 bool pushResult = FALSE;
3299 D(emitcode(";", "genMinus "););
3301 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3302 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3303 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3304 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3310 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3312 /* special cases :- */
3313 /* if both left & right are in bit space */
3314 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3315 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3320 /* if I can do an decrement instead
3321 of subtract then GOOD for ME */
3322 if (genMinusDec (ic) == TRUE)
3327 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3329 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3333 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3338 /* if literal, add a,#-lit, else normal subb */
3339 _startLazyDPSEvaluation();
3341 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3342 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3343 emitcode("subb","a,%s",
3344 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3346 /* first add without previous c */
3348 emitcode("add","a,#0x%02x",
3349 (unsigned int)(lit & 0x0FFL));
3351 emitcode("addc","a,#0x%02x",
3352 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3357 emitcode("push", "acc");
3361 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3365 _endLazyDPSEvaluation();
3369 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3371 size = getDataSize(IC_LEFT(ic));
3372 rSize = getDataSize(IC_RESULT(ic));
3374 /* If the pushed data is bigger than the result,
3375 * simply discard unused bytes. Icky, but works.
3377 * Should we throw a warning here? We're losing data...
3379 while (size > getDataSize(IC_RESULT(ic)))
3381 emitcode(";", "discarding unused result byte.");
3382 emitcode("pop", "acc");
3388 emitcode("clr", "a");
3389 /* Conversly, we haven't pushed enough here.
3390 * just zero-pad, and all is well.
3392 while (size < rSize)
3394 emitcode("push", "acc");
3402 emitcode("pop", "acc");
3403 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3407 adjustArithmeticResult(ic);
3410 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3411 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3412 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3416 /*-----------------------------------------------------------------*/
3417 /* genMultbits :- multiplication of bits */
3418 /*-----------------------------------------------------------------*/
3419 static void genMultbits (operand *left,
3423 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3424 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3429 /*-----------------------------------------------------------------*/
3430 /* genMultOneByte : 8 bit multiplication & division */
3431 /*-----------------------------------------------------------------*/
3432 static void genMultOneByte (operand *left,
3436 sym_link *opetype = operandType(result);
3441 /* (if two literals, the value is computed before) */
3442 /* if one literal, literal on the right */
3443 if (AOP_TYPE(left) == AOP_LIT){
3449 size = AOP_SIZE(result);
3450 /* signed or unsigned */
3451 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3452 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3454 emitcode("mul","ab");
3455 /* if result size = 1, mul signed = mul unsigned */
3456 aopPut(AOP(result),"a",0);
3458 if (SPEC_USIGN(opetype)){
3459 aopPut(AOP(result),"b",1);
3461 /* for filling the MSBs */
3462 emitcode("clr","a");
3465 emitcode("mov","a,b");
3467 /* adjust the MSB if left or right neg */
3469 /* if one literal */
3470 if (AOP_TYPE(right) == AOP_LIT){
3471 /* AND literal negative */
3472 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3473 /* adjust MSB (c==0 after mul) */
3474 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3478 lbl = newiTempLabel(NULL);
3479 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3480 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3481 emitcode("","%05d$:",(lbl->key+100));
3482 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3483 lbl = newiTempLabel(NULL);
3484 emitcode("jc","%05d$",(lbl->key+100));
3485 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3486 emitcode("","%05d$:",(lbl->key+100));
3489 lbl = newiTempLabel(NULL);
3490 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3491 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3492 emitcode("","%05d$:",(lbl->key+100));
3493 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3494 lbl = newiTempLabel(NULL);
3495 emitcode("jc","%05d$",(lbl->key+100));
3496 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3497 emitcode("","%05d$:",(lbl->key+100));
3499 aopPut(AOP(result),"a",1);
3502 emitcode("rlc","a");
3503 emitcode("subb","a,acc");
3510 aopPut(AOP(result),"a",offset++);
3514 /*-----------------------------------------------------------------*/
3515 /* genMult - generates code for multiplication */
3516 /*-----------------------------------------------------------------*/
3517 static void genMult (iCode *ic)
3519 operand *left = IC_LEFT(ic);
3520 operand *right = IC_RIGHT(ic);
3521 operand *result= IC_RESULT(ic);
3523 D(emitcode(";", "genMult "););
3525 /* assign the amsops */
3528 aopOp (left,ic,FALSE, FALSE);
3529 aopOp (right,ic,FALSE, TRUE);
3530 aopOp (result,ic,TRUE, FALSE);
3533 /* special cases first */
3535 if (AOP_TYPE(left) == AOP_CRY &&
3536 AOP_TYPE(right)== AOP_CRY) {
3537 genMultbits(left,right,result);
3541 /* if both are of size == 1 */
3542 if (AOP_SIZE(left) == 1 &&
3543 AOP_SIZE(right) == 1 ) {
3544 genMultOneByte(left,right,result);
3548 /* should have been converted to function call */
3552 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3553 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3554 freeAsmop(result,NULL,ic,TRUE);
3557 /*-----------------------------------------------------------------*/
3558 /* genDivbits :- division of bits */
3559 /*-----------------------------------------------------------------*/
3560 static void genDivbits (operand *left,
3567 /* the result must be bit */
3568 LOAD_AB_FOR_DIV(left, right, l);
3569 emitcode("div","ab");
3570 emitcode("rrc","a");
3571 aopPut(AOP(result),"c",0);
3574 /*-----------------------------------------------------------------*/
3575 /* genDivOneByte : 8 bit division */
3576 /*-----------------------------------------------------------------*/
3577 static void genDivOneByte (operand *left,
3581 sym_link *opetype = operandType(result);
3586 size = AOP_SIZE(result) - 1;
3588 /* signed or unsigned */
3589 if (SPEC_USIGN(opetype)) {
3590 /* unsigned is easy */
3591 LOAD_AB_FOR_DIV(left, right, l);
3592 emitcode("div","ab");
3593 aopPut(AOP(result),"a",0);
3595 aopPut(AOP(result),zero,offset++);
3599 /* signed is a little bit more difficult */
3601 /* save the signs of the operands */
3602 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3604 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3605 emitcode("push","acc"); /* save it on the stack */
3607 /* now sign adjust for both left & right */
3608 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3610 lbl = newiTempLabel(NULL);
3611 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3612 emitcode("cpl","a");
3613 emitcode("inc","a");
3614 emitcode("","%05d$:",(lbl->key+100));
3615 emitcode("mov","b,a");
3617 /* sign adjust left side */
3618 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3621 lbl = newiTempLabel(NULL);
3622 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3623 emitcode("cpl","a");
3624 emitcode("inc","a");
3625 emitcode("","%05d$:",(lbl->key+100));
3627 /* now the division */
3628 emitcode("nop", "; workaround for DS80C390 div bug.");
3629 emitcode("div","ab");
3630 /* we are interested in the lower order
3632 emitcode("mov","b,a");
3633 lbl = newiTempLabel(NULL);
3634 emitcode("pop","acc");
3635 /* if there was an over flow we don't
3636 adjust the sign of the result */
3637 emitcode("jb","ov,%05d$",(lbl->key+100));
3638 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3640 emitcode("clr","a");
3641 emitcode("subb","a,b");
3642 emitcode("mov","b,a");
3643 emitcode("","%05d$:",(lbl->key+100));
3645 /* now we are done */
3646 aopPut(AOP(result),"b",0);
3648 emitcode("mov","c,b.7");
3649 emitcode("subb","a,acc");
3652 aopPut(AOP(result),"a",offset++);
3656 /*-----------------------------------------------------------------*/
3657 /* genDiv - generates code for division */
3658 /*-----------------------------------------------------------------*/
3659 static void genDiv (iCode *ic)
3661 operand *left = IC_LEFT(ic);
3662 operand *right = IC_RIGHT(ic);
3663 operand *result= IC_RESULT(ic);
3665 D(emitcode(";", "genDiv "););
3667 /* assign the amsops */
3670 aopOp (left,ic,FALSE, FALSE);
3671 aopOp (right,ic,FALSE, TRUE);
3672 aopOp (result,ic,TRUE, FALSE);
3675 /* special cases first */
3677 if (AOP_TYPE(left) == AOP_CRY &&
3678 AOP_TYPE(right)== AOP_CRY) {
3679 genDivbits(left,right,result);
3683 /* if both are of size == 1 */
3684 if (AOP_SIZE(left) == 1 &&
3685 AOP_SIZE(right) == 1 ) {
3686 genDivOneByte(left,right,result);
3690 /* should have been converted to function call */
3693 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3694 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3695 freeAsmop(result,NULL,ic,TRUE);
3698 /*-----------------------------------------------------------------*/
3699 /* genModbits :- modulus of bits */
3700 /*-----------------------------------------------------------------*/
3701 static void genModbits (operand *left,
3708 /* the result must be bit */
3709 LOAD_AB_FOR_DIV(left, right, l);
3710 emitcode("div","ab");
3711 emitcode("mov","a,b");
3712 emitcode("rrc","a");
3713 aopPut(AOP(result),"c",0);
3716 /*-----------------------------------------------------------------*/
3717 /* genModOneByte : 8 bit modulus */
3718 /*-----------------------------------------------------------------*/
3719 static void genModOneByte (operand *left,
3723 sym_link *opetype = operandType(result);
3727 /* signed or unsigned */
3728 if (SPEC_USIGN(opetype)) {
3729 /* unsigned is easy */
3730 LOAD_AB_FOR_DIV(left, right, l);
3731 emitcode("div","ab");
3732 aopPut(AOP(result),"b",0);
3736 /* signed is a little bit more difficult */
3738 /* save the signs of the operands */
3739 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3742 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3743 emitcode("push","acc"); /* save it on the stack */
3745 /* now sign adjust for both left & right */
3746 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3749 lbl = newiTempLabel(NULL);
3750 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3751 emitcode("cpl","a");
3752 emitcode("inc","a");
3753 emitcode("","%05d$:",(lbl->key+100));
3754 emitcode("mov","b,a");
3756 /* sign adjust left side */
3757 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3760 lbl = newiTempLabel(NULL);
3761 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3762 emitcode("cpl","a");
3763 emitcode("inc","a");
3764 emitcode("","%05d$:",(lbl->key+100));
3766 /* now the multiplication */
3767 emitcode("nop", "; workaround for DS80C390 div bug.");
3768 emitcode("div","ab");
3769 /* we are interested in the lower order
3771 lbl = newiTempLabel(NULL);
3772 emitcode("pop","acc");
3773 /* if there was an over flow we don't
3774 adjust the sign of the result */
3775 emitcode("jb","ov,%05d$",(lbl->key+100));
3776 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3778 emitcode("clr","a");
3779 emitcode("subb","a,b");
3780 emitcode("mov","b,a");
3781 emitcode("","%05d$:",(lbl->key+100));
3783 /* now we are done */
3784 aopPut(AOP(result),"b",0);
3788 /*-----------------------------------------------------------------*/
3789 /* genMod - generates code for division */
3790 /*-----------------------------------------------------------------*/
3791 static void genMod (iCode *ic)
3793 operand *left = IC_LEFT(ic);
3794 operand *right = IC_RIGHT(ic);
3795 operand *result= IC_RESULT(ic);
3797 D(emitcode(";", "genMod "););
3799 /* assign the amsops */
3802 aopOp (left,ic,FALSE, FALSE);
3803 aopOp (right,ic,FALSE, TRUE);
3804 aopOp (result,ic,TRUE, FALSE);
3807 /* special cases first */
3809 if (AOP_TYPE(left) == AOP_CRY &&
3810 AOP_TYPE(right)== AOP_CRY) {
3811 genModbits(left,right,result);
3815 /* if both are of size == 1 */
3816 if (AOP_SIZE(left) == 1 &&
3817 AOP_SIZE(right) == 1 ) {
3818 genModOneByte(left,right,result);
3822 /* should have been converted to function call */
3826 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3827 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3828 freeAsmop(result,NULL,ic,TRUE);
3831 /*-----------------------------------------------------------------*/
3832 /* genIfxJump :- will create a jump depending on the ifx */
3833 /*-----------------------------------------------------------------*/
3834 static void genIfxJump (iCode *ic, char *jval)
3837 symbol *tlbl = newiTempLabel(NULL);
3840 D(emitcode(";", "genIfxJump "););
3842 /* if true label then we jump if condition
3844 if ( IC_TRUE(ic) ) {
3846 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3847 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3850 /* false label is present */
3851 jlbl = IC_FALSE(ic) ;
3852 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3853 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3855 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3856 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3858 emitcode(inst,"%05d$",tlbl->key+100);
3859 emitcode("ljmp","%05d$",jlbl->key+100);
3860 emitcode("","%05d$:",tlbl->key+100);
3862 /* mark the icode as generated */
3866 /*-----------------------------------------------------------------*/
3867 /* genCmp :- greater or less than comparison */
3868 /*-----------------------------------------------------------------*/
3869 static void genCmp (operand *left,operand *right,
3870 operand *result, iCode *ifx, int sign)
3872 int size, offset = 0 ;
3873 unsigned long lit = 0L;
3874 bool swappedOps = FALSE;
3876 D(emitcode(";", "genCmp"););
3879 /* If left if lit and right isn't, swap 'em. */
3880 if (AOP_TYPE(left) == AOP_LIT &&
3881 AOP_TYPE(right) != AOP_LIT)
3883 operand *tmp = left;
3886 D(emitcode(";", "kevin literal hack"););
3887 swappedOps = !swappedOps;
3890 if (AOP_NEEDSACC(right))
3892 if (AOP_NEEDSACC(left))
3894 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3895 "both CMP operands need ACC!");
3900 operand *tmp = left;
3903 D(emitcode(";", "kevin ACC hack"););
3904 swappedOps = !swappedOps;
3909 /* if left & right are bit variables */
3910 if (AOP_TYPE(left) == AOP_CRY &&
3911 AOP_TYPE(right) == AOP_CRY ) {
3912 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3913 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3915 /* subtract right from left if at the
3916 end the carry flag is set then we know that
3917 left is greater than right */
3918 size = max(AOP_SIZE(left),AOP_SIZE(right));
3920 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3921 if((size == 1) && !sign &&
3922 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3923 symbol *lbl = newiTempLabel(NULL);
3924 emitcode("cjne","%s,%s,%05d$",
3925 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3926 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3928 emitcode("","%05d$:",lbl->key+100);
3930 if(AOP_TYPE(right) == AOP_LIT){
3931 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3932 /* optimize if(x < 0) or if(x >= 0) */
3938 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3939 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3940 genIfxJump (ifx,"acc.7");
3944 emitcode("rlc","a");
3952 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3953 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3954 emitcode(";", "genCmp #2");
3955 if (sign && (size == 0))
3957 emitcode(";", "genCmp #3");
3958 emitcode("xrl","a,#0x80");
3959 if (AOP_TYPE(right) == AOP_LIT)
3961 unsigned long lit = (unsigned long)
3962 floatFromVal(AOP(right)->aopu.aop_lit);
3963 emitcode(";", "genCmp #3.1");
3964 emitcode("subb","a,#0x%02x",
3965 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3969 emitcode(";", "genCmp #3.2");
3970 if (AOP_NEEDSACC(right))
3972 emitcode("push", "acc");
3974 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3975 FALSE,FALSE,FALSE));
3976 emitcode("xrl","b,#0x80");
3977 if (AOP_NEEDSACC(right))
3979 emitcode("pop", "acc");
3981 emitcode("subb","a,b");
3988 emitcode(";", "genCmp #4");
3989 if (AOP_NEEDSACC(right))
3992 emitcode(";", "genCmp #4.1");
3993 emitcode("xch", "a, b");
3994 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3995 emitcode("xch", "a, b");
4000 emitcode(";", "genCmp #4.2");
4001 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
4004 emitcode("subb","a,%s",s);
4013 D(emitcode(";","kevHack: flip carry."););
4014 emitcode("cpl", "c");
4017 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4020 /* if the result is used in the next
4021 ifx conditional branch then generate
4022 code a little differently */
4024 genIfxJump (ifx,"c");
4027 /* leave the result in acc */
4031 /*-----------------------------------------------------------------*/
4032 /* genCmpGt :- greater than comparison */
4033 /*-----------------------------------------------------------------*/
4034 static void genCmpGt (iCode *ic, iCode *ifx)
4036 operand *left, *right, *result;
4037 sym_link *letype , *retype;
4040 D(emitcode(";", "genCmpGt "););
4043 right= IC_RIGHT(ic);
4044 result = IC_RESULT(ic);
4046 letype = getSpec(operandType(left));
4047 retype =getSpec(operandType(right));
4048 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4049 /* assign the amsops */
4052 aopOp (left,ic,FALSE, TRUE);
4053 aopOp (right,ic,FALSE, FALSE);
4054 aopOp (result,ic,TRUE, FALSE);
4057 genCmp(right, left, result, ifx, sign);
4059 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4060 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4061 freeAsmop(result,NULL,ic,TRUE);
4064 /*-----------------------------------------------------------------*/
4065 /* genCmpLt - less than comparisons */
4066 /*-----------------------------------------------------------------*/
4067 static void genCmpLt (iCode *ic, iCode *ifx)
4069 operand *left, *right, *result;
4070 sym_link *letype , *retype;
4073 D(emitcode(";", "genCmpLt "););
4076 right= IC_RIGHT(ic);
4077 result = IC_RESULT(ic);
4079 letype = getSpec(operandType(left));
4080 retype =getSpec(operandType(right));
4081 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4083 /* assign the amsops */
4086 aopOp (left,ic,FALSE, FALSE);
4087 aopOp (right,ic,FALSE, TRUE);
4088 aopOp (result,ic,TRUE, FALSE);
4091 genCmp(left, right, result, ifx, sign);
4093 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4094 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4095 freeAsmop(result,NULL,ic,TRUE);
4098 /*-----------------------------------------------------------------*/
4099 /* gencjneshort - compare and jump if not equal */
4100 /*-----------------------------------------------------------------*/
4101 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4103 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4105 unsigned long lit = 0L;
4107 D(emitcode(";", "gencjneshort"););
4109 /* if the left side is a literal or
4110 if the right is in a pointer register and left
4112 if ((AOP_TYPE(left) == AOP_LIT) ||
4113 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4119 if(AOP_TYPE(right) == AOP_LIT)
4120 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4122 if (opIsGptr(left) || opIsGptr(right))
4124 /* We are comparing a generic pointer to something.
4125 * Exclude the generic type byte from the comparison.
4128 D(emitcode(";", "cjneshort: generic ptr special case.");)
4132 /* if the right side is a literal then anything goes */
4133 if (AOP_TYPE(right) == AOP_LIT &&
4134 AOP_TYPE(left) != AOP_DIR ) {
4136 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4138 emitcode("cjne","a,%s,%05d$",
4139 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4145 /* if the right side is in a register or in direct space or
4146 if the left is a pointer register & right is not */
4147 else if (AOP_TYPE(right) == AOP_REG ||
4148 AOP_TYPE(right) == AOP_DIR ||
4149 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4150 (IS_AOP_PREG(left) && !IS_AOP_PREG(right)))
4154 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4155 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4156 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4157 emitcode("jnz","%05d$",lbl->key+100);
4159 emitcode("cjne","a,%s,%05d$",
4160 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4165 /* right is a pointer reg need both a & b */
4167 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4169 emitcode("mov","b,%s",l);
4170 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4171 emitcode("cjne","a,b,%05d$",lbl->key+100);
4177 /*-----------------------------------------------------------------*/
4178 /* gencjne - compare and jump if not equal */
4179 /*-----------------------------------------------------------------*/
4180 static void gencjne(operand *left, operand *right, symbol *lbl)
4182 symbol *tlbl = newiTempLabel(NULL);
4184 D(emitcode(";", "gencjne"););
4186 gencjneshort(left, right, lbl);
4188 emitcode("mov","a,%s",one);
4189 emitcode("sjmp","%05d$",tlbl->key+100);
4190 emitcode("","%05d$:",lbl->key+100);
4191 emitcode("clr","a");
4192 emitcode("","%05d$:",tlbl->key+100);
4195 /*-----------------------------------------------------------------*/
4196 /* genCmpEq - generates code for equal to */
4197 /*-----------------------------------------------------------------*/
4198 static void genCmpEq (iCode *ic, iCode *ifx)
4200 operand *left, *right, *result;
4202 D(emitcode(";", "genCmpEq "););
4207 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4208 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4209 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4212 /* if literal, literal on the right or
4213 if the right is in a pointer register and left
4215 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4216 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4217 operand *t = IC_RIGHT(ic);
4218 IC_RIGHT(ic) = IC_LEFT(ic);
4222 if(ifx && !AOP_SIZE(result)){
4224 /* if they are both bit variables */
4225 if (AOP_TYPE(left) == AOP_CRY &&
4226 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4227 if(AOP_TYPE(right) == AOP_LIT){
4228 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4230 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4231 emitcode("cpl","c");
4232 } else if(lit == 1L) {
4233 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4235 emitcode("clr","c");
4237 /* AOP_TYPE(right) == AOP_CRY */
4239 symbol *lbl = newiTempLabel(NULL);
4240 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4241 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4242 emitcode("cpl","c");
4243 emitcode("","%05d$:",(lbl->key+100));
4245 /* if true label then we jump if condition
4247 tlbl = newiTempLabel(NULL);
4248 if ( IC_TRUE(ifx) ) {
4249 emitcode("jnc","%05d$",tlbl->key+100);
4250 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4252 emitcode("jc","%05d$",tlbl->key+100);
4253 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4255 emitcode("","%05d$:",tlbl->key+100);
4257 tlbl = newiTempLabel(NULL);
4258 gencjneshort(left, right, tlbl);
4259 if ( IC_TRUE(ifx) ) {
4260 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4261 emitcode("","%05d$:",tlbl->key+100);
4263 symbol *lbl = newiTempLabel(NULL);
4264 emitcode("sjmp","%05d$",lbl->key+100);
4265 emitcode("","%05d$:",tlbl->key+100);
4266 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4267 emitcode("","%05d$:",lbl->key+100);
4270 /* mark the icode as generated */
4275 /* if they are both bit variables */
4276 if (AOP_TYPE(left) == AOP_CRY &&
4277 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4278 if(AOP_TYPE(right) == AOP_LIT){
4279 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4281 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4282 emitcode("cpl","c");
4283 } else if(lit == 1L) {
4284 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4286 emitcode("clr","c");
4288 /* AOP_TYPE(right) == AOP_CRY */
4290 symbol *lbl = newiTempLabel(NULL);
4291 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4292 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4293 emitcode("cpl","c");
4294 emitcode("","%05d$:",(lbl->key+100));
4297 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4302 genIfxJump (ifx,"c");
4305 /* if the result is used in an arithmetic operation
4306 then put the result in place */
4309 gencjne(left,right,newiTempLabel(NULL));
4310 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4311 aopPut(AOP(result),"a",0);
4315 genIfxJump (ifx,"a");
4318 /* if the result is used in an arithmetic operation
4319 then put the result in place */
4320 if (AOP_TYPE(result) != AOP_CRY)
4322 /* leave the result in acc */
4326 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4327 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4328 freeAsmop(result,NULL,ic,TRUE);
4331 /*-----------------------------------------------------------------*/
4332 /* ifxForOp - returns the icode containing the ifx for operand */
4333 /*-----------------------------------------------------------------*/
4334 static iCode *ifxForOp ( operand *op, iCode *ic )
4336 /* if true symbol then needs to be assigned */
4337 if (IS_TRUE_SYMOP(op))
4340 /* if this has register type condition and
4341 the next instruction is ifx with the same operand
4342 and live to of the operand is upto the ifx only then */
4344 ic->next->op == IFX &&
4345 IC_COND(ic->next)->key == op->key &&
4346 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4351 /*-----------------------------------------------------------------*/
4352 /* genAndOp - for && operation */
4353 /*-----------------------------------------------------------------*/
4354 static void genAndOp (iCode *ic)
4356 operand *left,*right, *result;
4359 D(emitcode(";", "genAndOp "););
4361 /* note here that && operations that are in an
4362 if statement are taken away by backPatchLabels
4363 only those used in arthmetic operations remain */
4367 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4368 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4369 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4372 /* if both are bit variables */
4373 if (AOP_TYPE(left) == AOP_CRY &&
4374 AOP_TYPE(right) == AOP_CRY ) {
4375 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4376 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4379 tlbl = newiTempLabel(NULL);
4381 emitcode("jz","%05d$",tlbl->key+100);
4383 emitcode("","%05d$:",tlbl->key+100);
4387 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4388 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4389 freeAsmop(result,NULL,ic,TRUE);
4393 /*-----------------------------------------------------------------*/
4394 /* genOrOp - for || operation */
4395 /*-----------------------------------------------------------------*/
4396 static void genOrOp (iCode *ic)
4398 operand *left,*right, *result;
4401 D(emitcode(";", "genOrOp "););
4403 /* note here that || operations that are in an
4404 if statement are taken away by backPatchLabels
4405 only those used in arthmetic operations remain */
4409 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4410 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4411 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4414 /* if both are bit variables */
4415 if (AOP_TYPE(left) == AOP_CRY &&
4416 AOP_TYPE(right) == AOP_CRY ) {
4417 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4418 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4421 tlbl = newiTempLabel(NULL);
4423 emitcode("jnz","%05d$",tlbl->key+100);
4425 emitcode("","%05d$:",tlbl->key+100);
4429 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4430 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4431 freeAsmop(result,NULL,ic,TRUE);
4434 /*-----------------------------------------------------------------*/
4435 /* isLiteralBit - test if lit == 2^n */
4436 /*-----------------------------------------------------------------*/
4437 static int isLiteralBit(unsigned long lit)
4439 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4440 0x100L,0x200L,0x400L,0x800L,
4441 0x1000L,0x2000L,0x4000L,0x8000L,
4442 0x10000L,0x20000L,0x40000L,0x80000L,
4443 0x100000L,0x200000L,0x400000L,0x800000L,
4444 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4445 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4448 for(idx = 0; idx < 32; idx++)
4454 /*-----------------------------------------------------------------*/
4455 /* continueIfTrue - */
4456 /*-----------------------------------------------------------------*/
4457 static void continueIfTrue (iCode *ic)
4460 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4464 /*-----------------------------------------------------------------*/
4466 /*-----------------------------------------------------------------*/
4467 static void jumpIfTrue (iCode *ic)
4470 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4474 /*-----------------------------------------------------------------*/
4475 /* jmpTrueOrFalse - */
4476 /*-----------------------------------------------------------------*/
4477 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4479 // ugly but optimized by peephole
4481 symbol *nlbl = newiTempLabel(NULL);
4482 emitcode("sjmp","%05d$",nlbl->key+100);
4483 emitcode("","%05d$:",tlbl->key+100);
4484 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4485 emitcode("","%05d$:",nlbl->key+100);
4488 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4489 emitcode("","%05d$:",tlbl->key+100);
4494 /*-----------------------------------------------------------------*/
4495 /* genAnd - code for and */
4496 /*-----------------------------------------------------------------*/
4497 static void genAnd (iCode *ic, iCode *ifx)
4499 operand *left, *right, *result;
4501 unsigned long lit = 0L;
4505 D(emitcode(";", "genAnd "););
4510 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4511 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4512 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4516 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4518 AOP_TYPE(left), AOP_TYPE(right));
4519 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4521 AOP_SIZE(left), AOP_SIZE(right));
4524 /* if left is a literal & right is not then exchange them */
4525 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4526 AOP_NEEDSACC(left)) {
4527 operand *tmp = right ;
4532 /* if result = right then exchange them */
4533 if(sameRegs(AOP(result),AOP(right))){
4534 operand *tmp = right ;
4539 /* if right is bit then exchange them */
4540 if (AOP_TYPE(right) == AOP_CRY &&
4541 AOP_TYPE(left) != AOP_CRY){
4542 operand *tmp = right ;
4546 if(AOP_TYPE(right) == AOP_LIT)
4547 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4549 size = AOP_SIZE(result);
4552 // result = bit & yy;
4553 if (AOP_TYPE(left) == AOP_CRY){
4554 // c = bit & literal;
4555 if(AOP_TYPE(right) == AOP_LIT){
4557 if(size && sameRegs(AOP(result),AOP(left)))
4560 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4563 if(size && (AOP_TYPE(result) == AOP_CRY)){
4564 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4567 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4571 emitcode("clr","c");
4574 if (AOP_TYPE(right) == AOP_CRY){
4576 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4577 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4580 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4582 emitcode("rrc","a");
4583 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4591 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4592 genIfxJump(ifx, "c");
4596 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4597 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4598 if((AOP_TYPE(right) == AOP_LIT) &&
4599 (AOP_TYPE(result) == AOP_CRY) &&
4600 (AOP_TYPE(left) != AOP_CRY)){
4601 int posbit = isLiteralBit(lit);
4605 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4608 emitcode("mov","c,acc.%d",posbit&0x07);
4612 sprintf(buffer,"acc.%d",posbit&0x07);
4613 genIfxJump(ifx, buffer);
4618 symbol *tlbl = newiTempLabel(NULL);
4619 int sizel = AOP_SIZE(left);
4621 emitcode("setb","c");
4623 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4624 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4626 if((posbit = isLiteralBit(bytelit)) != 0)
4627 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4629 if(bytelit != 0x0FFL)
4630 emitcode("anl","a,%s",
4631 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4632 emitcode("jnz","%05d$",tlbl->key+100);
4637 // bit = left & literal
4639 emitcode("clr","c");
4640 emitcode("","%05d$:",tlbl->key+100);
4642 // if(left & literal)
4645 jmpTrueOrFalse(ifx, tlbl);
4653 /* if left is same as result */
4654 if(sameRegs(AOP(result),AOP(left))){
4655 for(;size--; offset++) {
4656 if(AOP_TYPE(right) == AOP_LIT){
4657 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4661 aopPut(AOP(result),zero,offset);
4663 if (IS_AOP_PREG(result)) {
4664 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4665 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4666 aopPut(AOP(result),"a",offset);
4668 emitcode("anl","%s,%s",
4669 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4670 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4672 if (AOP_TYPE(left) == AOP_ACC)
4673 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4675 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4676 if (IS_AOP_PREG(result)) {
4677 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4678 aopPut(AOP(result),"a",offset);
4681 emitcode("anl","%s,a",
4682 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4687 // left & result in different registers
4688 if(AOP_TYPE(result) == AOP_CRY){
4690 // if(size), result in bit
4691 // if(!size && ifx), conditional oper: if(left & right)
4692 symbol *tlbl = newiTempLabel(NULL);
4693 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4695 emitcode("setb","c");
4697 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4698 emitcode("anl","a,%s",
4699 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4700 emitcode("jnz","%05d$",tlbl->key+100);
4705 emitcode("","%05d$:",tlbl->key+100);
4708 jmpTrueOrFalse(ifx, tlbl);
4710 for(;(size--);offset++) {
4712 // result = left & right
4713 if(AOP_TYPE(right) == AOP_LIT){
4714 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4716 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4719 } else if(bytelit == 0){
4720 aopPut(AOP(result),zero,offset);
4724 // faster than result <- left, anl result,right
4725 // and better if result is SFR
4726 if (AOP_TYPE(left) == AOP_ACC)
4727 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4729 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4730 emitcode("anl","a,%s",
4731 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4733 aopPut(AOP(result),"a",offset);
4739 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4740 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4741 freeAsmop(result,NULL,ic,TRUE);
4744 /*-----------------------------------------------------------------*/
4745 /* genOr - code for or */
4746 /*-----------------------------------------------------------------*/
4747 static void genOr (iCode *ic, iCode *ifx)
4749 operand *left, *right, *result;
4751 unsigned long lit = 0L;
4753 D(emitcode(";", "genOr "););
4758 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4759 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4760 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4764 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4766 AOP_TYPE(left), AOP_TYPE(right));
4767 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4769 AOP_SIZE(left), AOP_SIZE(right));
4772 /* if left is a literal & right is not then exchange them */
4773 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4774 AOP_NEEDSACC(left)) {
4775 operand *tmp = right ;
4780 /* if result = right then exchange them */
4781 if(sameRegs(AOP(result),AOP(right))){
4782 operand *tmp = right ;
4787 /* if right is bit then exchange them */
4788 if (AOP_TYPE(right) == AOP_CRY &&
4789 AOP_TYPE(left) != AOP_CRY){
4790 operand *tmp = right ;
4794 if(AOP_TYPE(right) == AOP_LIT)
4795 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4797 size = AOP_SIZE(result);
4801 if (AOP_TYPE(left) == AOP_CRY){
4802 if(AOP_TYPE(right) == AOP_LIT){
4803 // c = bit & literal;
4805 // lit != 0 => result = 1
4806 if(AOP_TYPE(result) == AOP_CRY){
4808 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4810 continueIfTrue(ifx);
4813 emitcode("setb","c");
4815 // lit == 0 => result = left
4816 if(size && sameRegs(AOP(result),AOP(left)))
4818 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4821 if (AOP_TYPE(right) == AOP_CRY){
4823 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4824 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4828 symbol *tlbl = newiTempLabel(NULL);
4829 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4830 emitcode("setb","c");
4831 emitcode("jb","%s,%05d$",
4832 AOP(left)->aopu.aop_dir,tlbl->key+100);
4834 emitcode("jnz","%05d$",tlbl->key+100);
4835 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4836 jmpTrueOrFalse(ifx, tlbl);
4840 emitcode("","%05d$:",tlbl->key+100);
4849 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4850 genIfxJump(ifx, "c");
4854 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4855 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4856 if((AOP_TYPE(right) == AOP_LIT) &&
4857 (AOP_TYPE(result) == AOP_CRY) &&
4858 (AOP_TYPE(left) != AOP_CRY)){
4862 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4864 continueIfTrue(ifx);
4867 // lit = 0, result = boolean(left)
4869 emitcode("setb","c");
4872 symbol *tlbl = newiTempLabel(NULL);
4873 emitcode("jnz","%05d$",tlbl->key+100);
4875 emitcode("","%05d$:",tlbl->key+100);
4877 genIfxJump (ifx,"a");
4885 /* if left is same as result */
4886 if(sameRegs(AOP(result),AOP(left))){
4887 for(;size--; offset++) {
4888 if(AOP_TYPE(right) == AOP_LIT){
4889 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4892 if (IS_AOP_PREG(left)) {
4893 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4894 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4895 aopPut(AOP(result),"a",offset);
4897 emitcode("orl","%s,%s",
4898 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4899 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4901 if (AOP_TYPE(left) == AOP_ACC)
4902 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4904 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4905 if (IS_AOP_PREG(left)) {
4906 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4907 aopPut(AOP(result),"a",offset);
4909 emitcode("orl","%s,a",
4910 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4915 // left & result in different registers
4916 if(AOP_TYPE(result) == AOP_CRY){
4918 // if(size), result in bit
4919 // if(!size && ifx), conditional oper: if(left | right)
4920 symbol *tlbl = newiTempLabel(NULL);
4921 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4923 emitcode("setb","c");
4925 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4926 emitcode("orl","a,%s",
4927 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4928 emitcode("jnz","%05d$",tlbl->key+100);
4933 emitcode("","%05d$:",tlbl->key+100);
4936 jmpTrueOrFalse(ifx, tlbl);
4937 } else for(;(size--);offset++){
4939 // result = left & right
4940 if(AOP_TYPE(right) == AOP_LIT){
4941 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4943 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4948 // faster than result <- left, anl result,right
4949 // and better if result is SFR
4950 if (AOP_TYPE(left) == AOP_ACC)
4951 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4953 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4954 emitcode("orl","a,%s",
4955 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4957 aopPut(AOP(result),"a",offset);
4962 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4963 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4964 freeAsmop(result,NULL,ic,TRUE);
4967 /*-----------------------------------------------------------------*/
4968 /* genXor - code for xclusive or */
4969 /*-----------------------------------------------------------------*/
4970 static void genXor (iCode *ic, iCode *ifx)
4972 operand *left, *right, *result;
4974 unsigned long lit = 0L;
4976 D(emitcode(";", "genXor "););
4981 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4982 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4983 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4987 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4989 AOP_TYPE(left), AOP_TYPE(right));
4990 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4992 AOP_SIZE(left), AOP_SIZE(right));
4995 /* if left is a literal & right is not ||
4996 if left needs acc & right does not */
4997 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4998 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4999 operand *tmp = right ;
5004 /* if result = right then exchange them */
5005 if(sameRegs(AOP(result),AOP(right))){
5006 operand *tmp = right ;
5011 /* if right is bit then exchange them */
5012 if (AOP_TYPE(right) == AOP_CRY &&
5013 AOP_TYPE(left) != AOP_CRY){
5014 operand *tmp = right ;
5018 if(AOP_TYPE(right) == AOP_LIT)
5019 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5021 size = AOP_SIZE(result);
5025 if (AOP_TYPE(left) == AOP_CRY){
5026 if(AOP_TYPE(right) == AOP_LIT){
5027 // c = bit & literal;
5029 // lit>>1 != 0 => result = 1
5030 if(AOP_TYPE(result) == AOP_CRY){
5032 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5034 continueIfTrue(ifx);
5037 emitcode("setb","c");
5041 // lit == 0, result = left
5042 if(size && sameRegs(AOP(result),AOP(left)))
5044 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5046 // lit == 1, result = not(left)
5047 if(size && sameRegs(AOP(result),AOP(left))){
5048 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5051 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5052 emitcode("cpl","c");
5059 symbol *tlbl = newiTempLabel(NULL);
5060 if (AOP_TYPE(right) == AOP_CRY){
5062 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5065 int sizer = AOP_SIZE(right);
5067 // if val>>1 != 0, result = 1
5068 emitcode("setb","c");
5070 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5072 // test the msb of the lsb
5073 emitcode("anl","a,#0xfe");
5074 emitcode("jnz","%05d$",tlbl->key+100);
5078 emitcode("rrc","a");
5080 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5081 emitcode("cpl","c");
5082 emitcode("","%05d$:",(tlbl->key+100));
5089 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5090 genIfxJump(ifx, "c");
5094 if(sameRegs(AOP(result),AOP(left))){
5095 /* if left is same as result */
5096 for(;size--; offset++) {
5097 if(AOP_TYPE(right) == AOP_LIT){
5098 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5101 if (IS_AOP_PREG(left)) {
5102 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5103 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5104 aopPut(AOP(result),"a",offset);
5106 emitcode("xrl","%s,%s",
5107 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5108 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5110 if (AOP_TYPE(left) == AOP_ACC)
5111 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5113 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5114 if (IS_AOP_PREG(left)) {
5115 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5116 aopPut(AOP(result),"a",offset);
5118 emitcode("xrl","%s,a",
5119 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5124 // left & result in different registers
5125 if(AOP_TYPE(result) == AOP_CRY){
5127 // if(size), result in bit
5128 // if(!size && ifx), conditional oper: if(left ^ right)
5129 symbol *tlbl = newiTempLabel(NULL);
5130 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5132 emitcode("setb","c");
5134 if((AOP_TYPE(right) == AOP_LIT) &&
5135 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5136 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5138 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5139 emitcode("xrl","a,%s",
5140 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5142 emitcode("jnz","%05d$",tlbl->key+100);
5147 emitcode("","%05d$:",tlbl->key+100);
5150 jmpTrueOrFalse(ifx, tlbl);
5151 } else for(;(size--);offset++){
5153 // result = left & right
5154 if(AOP_TYPE(right) == AOP_LIT){
5155 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
5157 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5162 // faster than result <- left, anl result,right
5163 // and better if result is SFR
5164 if (AOP_TYPE(left) == AOP_ACC)
5165 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5167 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5168 emitcode("xrl","a,%s",
5169 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5171 aopPut(AOP(result),"a",offset);
5176 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5177 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5178 freeAsmop(result,NULL,ic,TRUE);
5181 /*-----------------------------------------------------------------*/
5182 /* genInline - write the inline code out */
5183 /*-----------------------------------------------------------------*/
5184 static void genInline (iCode *ic)
5186 char buffer[MAX_INLINEASM];
5190 D(emitcode(";", "genInline "););
5192 _G.inLine += (!options.asmpeep);
5193 strcpy(buffer,IC_INLINE(ic));
5195 /* emit each line as a code */
5214 /* emitcode("",buffer); */
5215 _G.inLine -= (!options.asmpeep);
5218 /*-----------------------------------------------------------------*/
5219 /* genRRC - rotate right with carry */
5220 /*-----------------------------------------------------------------*/
5221 static void genRRC (iCode *ic)
5223 operand *left , *result ;
5224 int size, offset = 0;
5227 D(emitcode(";", "genRRC "););
5229 /* rotate right with carry */
5231 result=IC_RESULT(ic);
5232 aopOp (left,ic,FALSE, FALSE);
5233 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5235 /* move it to the result */
5236 size = AOP_SIZE(result);
5240 _startLazyDPSEvaluation();
5242 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5244 emitcode("rrc","a");
5245 if (AOP_SIZE(result) > 1)
5246 aopPut(AOP(result),"a",offset--);
5248 _endLazyDPSEvaluation();
5250 /* now we need to put the carry into the
5251 highest order byte of the result */
5252 if (AOP_SIZE(result) > 1) {
5253 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5256 emitcode("mov","acc.7,c");
5257 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5258 freeAsmop(left,NULL,ic,TRUE);
5259 freeAsmop(result,NULL,ic,TRUE);
5262 /*-----------------------------------------------------------------*/
5263 /* genRLC - generate code for rotate left with carry */
5264 /*-----------------------------------------------------------------*/
5265 static void genRLC (iCode *ic)
5267 operand *left , *result ;
5268 int size, offset = 0;
5271 D(emitcode(";", "genRLC "););
5273 /* rotate right with carry */
5275 result=IC_RESULT(ic);
5276 aopOp (left,ic,FALSE, FALSE);
5277 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5279 /* move it to the result */
5280 size = AOP_SIZE(result);
5283 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5285 emitcode("add","a,acc");
5286 if (AOP_SIZE(result) > 1)
5288 aopPut(AOP(result),"a",offset++);
5291 _startLazyDPSEvaluation();
5293 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5295 emitcode("rlc","a");
5296 if (AOP_SIZE(result) > 1)
5297 aopPut(AOP(result),"a",offset++);
5299 _endLazyDPSEvaluation();
5301 /* now we need to put the carry into the
5302 highest order byte of the result */
5303 if (AOP_SIZE(result) > 1) {
5304 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5307 emitcode("mov","acc.0,c");
5308 aopPut(AOP(result),"a",0);
5309 freeAsmop(left,NULL,ic,TRUE);
5310 freeAsmop(result,NULL,ic,TRUE);
5313 /*-----------------------------------------------------------------*/
5314 /* genGetHbit - generates code get highest order bit */
5315 /*-----------------------------------------------------------------*/
5316 static void genGetHbit (iCode *ic)
5318 operand *left, *result;
5320 result=IC_RESULT(ic);
5321 aopOp (left,ic,FALSE, FALSE);
5322 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5324 D(emitcode(";", "genGetHbit "););
5326 /* get the highest order byte into a */
5327 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5328 if(AOP_TYPE(result) == AOP_CRY){
5329 emitcode("rlc","a");
5334 emitcode("anl","a,#0x01");
5339 freeAsmop(left,NULL,ic,TRUE);
5340 freeAsmop(result,NULL,ic,TRUE);
5343 /*-----------------------------------------------------------------*/
5344 /* AccRol - rotate left accumulator by known count */
5345 /*-----------------------------------------------------------------*/
5346 static void AccRol (int shCount)
5348 shCount &= 0x0007; // shCount : 0..7
5360 emitcode("swap","a");
5364 emitcode("swap","a");
5367 emitcode("swap","a");
5380 /*-----------------------------------------------------------------*/
5381 /* AccLsh - left shift accumulator by known count */
5382 /*-----------------------------------------------------------------*/
5383 static void AccLsh (int shCount)
5387 emitcode("add","a,acc");
5390 emitcode("add","a,acc");
5391 emitcode("add","a,acc");
5393 /* rotate left accumulator */
5395 /* and kill the lower order bits */
5396 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5401 /*-----------------------------------------------------------------*/
5402 /* AccRsh - right shift accumulator by known count */
5403 /*-----------------------------------------------------------------*/
5404 static void AccRsh (int shCount)
5409 emitcode("rrc","a");
5411 /* rotate right accumulator */
5412 AccRol(8 - shCount);
5413 /* and kill the higher order bits */
5414 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5421 /*-----------------------------------------------------------------*/
5422 /* AccSRsh - signed right shift accumulator by known count */
5423 /*-----------------------------------------------------------------*/
5424 static void AccSRsh (int shCount)
5429 emitcode("mov","c,acc.7");
5430 emitcode("rrc","a");
5431 } else if(shCount == 2){
5432 emitcode("mov","c,acc.7");
5433 emitcode("rrc","a");
5434 emitcode("mov","c,acc.7");
5435 emitcode("rrc","a");
5437 tlbl = newiTempLabel(NULL);
5438 /* rotate right accumulator */
5439 AccRol(8 - shCount);
5440 /* and kill the higher order bits */
5441 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5442 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5443 emitcode("orl","a,#0x%02x",
5444 (unsigned char)~SRMask[shCount]);
5445 emitcode("","%05d$:",tlbl->key+100);
5453 /*-----------------------------------------------------------------*/
5454 /* shiftR1Left2Result - shift right one byte from left to result */
5455 /*-----------------------------------------------------------------*/
5456 static void shiftR1Left2Result (operand *left, int offl,
5457 operand *result, int offr,
5458 int shCount, int sign)
5460 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5461 /* shift right accumulator */
5466 aopPut(AOP(result),"a",offr);
5472 /*-----------------------------------------------------------------*/
5473 /* shiftL1Left2Result - shift left one byte from left to result */
5474 /*-----------------------------------------------------------------*/
5475 static void shiftL1Left2Result (operand *left, int offl,
5476 operand *result, int offr, int shCount)
5479 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5481 /* shift left accumulator */
5483 aopPut(AOP(result),"a",offr);
5489 /*-----------------------------------------------------------------*/
5490 /* movLeft2Result - move byte from left to result */
5491 /*-----------------------------------------------------------------*/
5492 static void movLeft2Result (operand *left, int offl,
5493 operand *result, int offr, int sign)
5496 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5497 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5499 if (*l == '@' && (IS_AOP_PREG(result))) {
5500 emitcode("mov","a,%s",l);
5501 aopPut(AOP(result),"a",offr);
5504 aopPut(AOP(result),l,offr);
5506 /* MSB sign in acc.7 ! */
5507 if(getDataSize(left) == offl+1){
5508 emitcode("mov","a,%s",l);
5509 aopPut(AOP(result),"a",offr);
5519 /*-----------------------------------------------------------------*/
5520 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5521 /*-----------------------------------------------------------------*/
5522 static void AccAXRrl1 (char *x)
5524 emitcode("rrc","a");
5525 emitcode("xch","a,%s", x);
5526 emitcode("rrc","a");
5527 emitcode("xch","a,%s", x);
5533 /*-----------------------------------------------------------------*/
5534 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5535 /*-----------------------------------------------------------------*/
5536 static void AccAXLrl1 (char *x)
5538 emitcode("xch","a,%s",x);
5539 emitcode("rlc","a");
5540 emitcode("xch","a,%s",x);
5541 emitcode("rlc","a");
5547 /*-----------------------------------------------------------------*/
5548 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5549 /*-----------------------------------------------------------------*/
5550 static void AccAXLsh1 (char *x)
5552 emitcode("xch","a,%s",x);
5553 emitcode("add","a,acc");
5554 emitcode("xch","a,%s",x);
5555 emitcode("rlc","a");
5561 /*-----------------------------------------------------------------*/
5562 /* AccAXLsh - left shift a:x by known count (0..7) */
5563 /*-----------------------------------------------------------------*/
5564 static void AccAXLsh (char *x, int shCount)
5578 case 5 : // AAAAABBB:CCCCCDDD
5579 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5580 emitcode("anl","a,#0x%02x",
5581 SLMask[shCount]); // BBB00000:CCCCCDDD
5582 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5583 AccRol(shCount); // DDDCCCCC:BBB00000
5584 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5585 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5586 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5587 emitcode("anl","a,#0x%02x",
5588 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5589 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5590 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5592 case 6 : // AAAAAABB:CCCCCCDD
5593 emitcode("anl","a,#0x%02x",
5594 SRMask[shCount]); // 000000BB:CCCCCCDD
5595 emitcode("mov","c,acc.0"); // c = B
5596 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5597 AccAXRrl1(x); // BCCCCCCD:D000000B
5598 AccAXRrl1(x); // BBCCCCCC:DD000000
5600 case 7 : // a:x <<= 7
5601 emitcode("anl","a,#0x%02x",
5602 SRMask[shCount]); // 0000000B:CCCCCCCD
5603 emitcode("mov","c,acc.0"); // c = B
5604 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5605 AccAXRrl1(x); // BCCCCCCC:D0000000
5615 /*-----------------------------------------------------------------*/
5616 /* AccAXRsh - right shift a:x known count (0..7) */
5617 /*-----------------------------------------------------------------*/
5618 static void AccAXRsh (char *x, int shCount)
5625 AccAXRrl1(x); // 0->a:x
5629 AccAXRrl1(x); // 0->a:x
5631 AccAXRrl1(x); // 0->a:x
5635 case 5 : // AAAAABBB:CCCCCDDD = a:x
5636 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5637 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5638 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5639 emitcode("anl","a,#0x%02x",
5640 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5641 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5642 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5643 emitcode("anl","a,#0x%02x",
5644 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5645 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5646 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5647 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5649 case 6 : // AABBBBBB:CCDDDDDD
5650 emitcode("mov","c,acc.7");
5651 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5652 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5653 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5654 emitcode("anl","a,#0x%02x",
5655 SRMask[shCount]); // 000000AA:BBBBBBCC
5657 case 7 : // ABBBBBBB:CDDDDDDD
5658 emitcode("mov","c,acc.7"); // c = A
5659 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5660 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5661 emitcode("anl","a,#0x%02x",
5662 SRMask[shCount]); // 0000000A:BBBBBBBC
5672 /*-----------------------------------------------------------------*/
5673 /* AccAXRshS - right shift signed a:x known count (0..7) */
5674 /*-----------------------------------------------------------------*/
5675 static void AccAXRshS (char *x, int shCount)
5682 emitcode("mov","c,acc.7");
5683 AccAXRrl1(x); // s->a:x
5686 emitcode("mov","c,acc.7");
5687 AccAXRrl1(x); // s->a:x
5688 emitcode("mov","c,acc.7");
5689 AccAXRrl1(x); // s->a:x
5693 case 5 : // AAAAABBB:CCCCCDDD = a:x
5694 tlbl = newiTempLabel(NULL);
5695 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5696 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5697 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5698 emitcode("anl","a,#0x%02x",
5699 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5700 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5701 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5702 emitcode("anl","a,#0x%02x",
5703 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5704 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5705 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5706 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5707 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5708 emitcode("orl","a,#0x%02x",
5709 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5710 emitcode("","%05d$:",tlbl->key+100);
5711 break; // SSSSAAAA:BBBCCCCC
5712 case 6 : // AABBBBBB:CCDDDDDD
5713 tlbl = newiTempLabel(NULL);
5714 emitcode("mov","c,acc.7");
5715 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5716 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5717 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5718 emitcode("anl","a,#0x%02x",
5719 SRMask[shCount]); // 000000AA:BBBBBBCC
5720 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5721 emitcode("orl","a,#0x%02x",
5722 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5723 emitcode("","%05d$:",tlbl->key+100);
5725 case 7 : // ABBBBBBB:CDDDDDDD
5726 tlbl = newiTempLabel(NULL);
5727 emitcode("mov","c,acc.7"); // c = A
5728 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5729 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5730 emitcode("anl","a,#0x%02x",
5731 SRMask[shCount]); // 0000000A:BBBBBBBC
5732 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5733 emitcode("orl","a,#0x%02x",
5734 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5735 emitcode("","%05d$:",tlbl->key+100);
5745 /*-----------------------------------------------------------------*/
5746 /* shiftL2Left2Result - shift left two bytes from left to result */
5747 /*-----------------------------------------------------------------*/
5748 static void shiftL2Left2Result (operand *left, int offl,
5749 operand *result, int offr, int shCount)
5751 if(sameRegs(AOP(result), AOP(left)) &&
5752 ((offl + MSB16) == offr)){
5753 /* don't crash result[offr] */
5754 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5755 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5757 movLeft2Result(left,offl, result, offr, 0);
5758 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5760 /* ax << shCount (x = lsb(result))*/
5761 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5762 aopPut(AOP(result),"a",offr+MSB16);
5768 /*-----------------------------------------------------------------*/
5769 /* shiftR2Left2Result - shift right two bytes from left to result */
5770 /*-----------------------------------------------------------------*/
5771 static void shiftR2Left2Result (operand *left, int offl,
5772 operand *result, int offr,
5773 int shCount, int sign)
5775 if(sameRegs(AOP(result), AOP(left)) &&
5776 ((offl + MSB16) == offr)){
5777 /* don't crash result[offr] */
5778 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5779 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5781 movLeft2Result(left,offl, result, offr, 0);
5782 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5784 /* a:x >> shCount (x = lsb(result))*/
5786 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5788 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5789 if(getDataSize(result) > 1)
5790 aopPut(AOP(result),"a",offr+MSB16);
5796 /*-----------------------------------------------------------------*/
5797 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5798 /*-----------------------------------------------------------------*/
5799 static void shiftLLeftOrResult (operand *left, int offl,
5800 operand *result, int offr, int shCount)
5802 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5803 /* shift left accumulator */
5805 /* or with result */
5806 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5807 /* back to result */
5808 aopPut(AOP(result),"a",offr);
5814 /*-----------------------------------------------------------------*/
5815 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5816 /*-----------------------------------------------------------------*/
5817 static void shiftRLeftOrResult (operand *left, int offl,
5818 operand *result, int offr, int shCount)
5820 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5821 /* shift right accumulator */
5823 /* or with result */
5824 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5825 /* back to result */
5826 aopPut(AOP(result),"a",offr);
5832 /*-----------------------------------------------------------------*/
5833 /* genlshOne - left shift a one byte quantity by known count */
5834 /*-----------------------------------------------------------------*/
5835 static void genlshOne (operand *result, operand *left, int shCount)
5837 D(emitcode(";", "genlshOne "););
5838 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5844 /*-----------------------------------------------------------------*/
5845 /* genlshTwo - left shift two bytes by known amount != 0 */
5846 /*-----------------------------------------------------------------*/
5847 static void genlshTwo (operand *result,operand *left, int shCount)
5851 D(emitcode(";", "genlshTwo "););
5853 size = getDataSize(result);
5855 /* if shCount >= 8 */
5861 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5863 movLeft2Result(left, LSB, result, MSB16, 0);
5865 aopPut(AOP(result),zero,LSB);
5868 /* 1 <= shCount <= 7 */
5871 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5873 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5880 /*-----------------------------------------------------------------*/
5881 /* shiftLLong - shift left one long from left to result */
5882 /* offl = LSB or MSB16 */
5883 /*-----------------------------------------------------------------*/
5884 static void shiftLLong (operand *left, operand *result, int offr )
5887 int size = AOP_SIZE(result);
5889 if(size >= LSB+offr){
5890 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5892 emitcode("add","a,acc");
5893 if (sameRegs(AOP(left),AOP(result)) &&
5894 size >= MSB16+offr && offr != LSB )
5895 emitcode("xch","a,%s",
5896 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5898 aopPut(AOP(result),"a",LSB+offr);
5901 if(size >= MSB16+offr){
5902 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5903 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5906 emitcode("rlc","a");
5907 if (sameRegs(AOP(left),AOP(result)) &&
5908 size >= MSB24+offr && offr != LSB)
5909 emitcode("xch","a,%s",
5910 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5912 aopPut(AOP(result),"a",MSB16+offr);
5915 if(size >= MSB24+offr){
5916 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5917 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5920 emitcode("rlc","a");
5921 if (sameRegs(AOP(left),AOP(result)) &&
5922 size >= MSB32+offr && offr != LSB )
5923 emitcode("xch","a,%s",
5924 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5926 aopPut(AOP(result),"a",MSB24+offr);
5929 if(size > MSB32+offr){
5930 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5931 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5934 emitcode("rlc","a");
5935 aopPut(AOP(result),"a",MSB32+offr);
5938 aopPut(AOP(result),zero,LSB);
5944 /*-----------------------------------------------------------------*/
5945 /* genlshFour - shift four byte by a known amount != 0 */
5946 /*-----------------------------------------------------------------*/
5947 static void genlshFour (operand *result, operand *left, int shCount)
5951 D(emitcode(";", "genlshFour "););
5953 size = AOP_SIZE(result);
5955 /* if shifting more that 3 bytes */
5956 if (shCount >= 24 ) {
5959 /* lowest order of left goes to the highest
5960 order of the destination */
5961 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5963 movLeft2Result(left, LSB, result, MSB32, 0);
5964 aopPut(AOP(result),zero,LSB);
5965 aopPut(AOP(result),zero,MSB16);
5966 aopPut(AOP(result),zero,MSB32);
5970 /* more than two bytes */
5971 else if ( shCount >= 16 ) {
5972 /* lower order two bytes goes to higher order two bytes */
5974 /* if some more remaining */
5976 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5978 movLeft2Result(left, MSB16, result, MSB32, 0);
5979 movLeft2Result(left, LSB, result, MSB24, 0);
5981 aopPut(AOP(result),zero,MSB16);
5982 aopPut(AOP(result),zero,LSB);
5986 /* if more than 1 byte */
5987 else if ( shCount >= 8 ) {
5988 /* lower order three bytes goes to higher order three bytes */
5992 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5994 movLeft2Result(left, LSB, result, MSB16, 0);
5996 else{ /* size = 4 */
5998 movLeft2Result(left, MSB24, result, MSB32, 0);
5999 movLeft2Result(left, MSB16, result, MSB24, 0);
6000 movLeft2Result(left, LSB, result, MSB16, 0);
6001 aopPut(AOP(result),zero,LSB);
6003 else if(shCount == 1)
6004 shiftLLong(left, result, MSB16);
6006 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6007 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6008 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6009 aopPut(AOP(result),zero,LSB);
6014 /* 1 <= shCount <= 7 */
6015 else if(shCount <= 2){
6016 shiftLLong(left, result, LSB);
6018 shiftLLong(result, result, LSB);
6020 /* 3 <= shCount <= 7, optimize */
6022 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6023 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6024 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6031 /*-----------------------------------------------------------------*/
6032 /* genLeftShiftLiteral - left shifting by known count */
6033 /*-----------------------------------------------------------------*/
6034 static void genLeftShiftLiteral (operand *left,
6039 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6042 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
6044 freeAsmop(right,NULL,ic,TRUE);
6046 aopOp(left,ic,FALSE, FALSE);
6047 aopOp(result,ic,FALSE, TRUE);
6049 size = getSize(operandType(result));
6052 emitcode("; shift left ","result %d, left %d",size,
6056 /* I suppose that the left size >= result size */
6059 movLeft2Result(left, size, result, size, 0);
6063 else if(shCount >= (size * 8))
6065 aopPut(AOP(result),zero,size);
6069 genlshOne (result,left,shCount);
6073 case 3: /* bug: this is for generic pointers, I bet. */
6074 genlshTwo (result,left,shCount);
6078 genlshFour (result,left,shCount);
6082 freeAsmop(left,NULL,ic,TRUE);
6083 freeAsmop(result,NULL,ic,TRUE);
6087 /*-----------------------------------------------------------------*/
6088 /* genLeftShift - generates code for left shifting */
6089 /*-----------------------------------------------------------------*/
6090 static void genLeftShift (iCode *ic)
6092 operand *left,*right, *result;
6095 symbol *tlbl , *tlbl1;
6097 D(emitcode(";", "genLeftShift "););
6099 right = IC_RIGHT(ic);
6101 result = IC_RESULT(ic);
6103 aopOp(right,ic,FALSE, FALSE);
6106 /* if the shift count is known then do it
6107 as efficiently as possible */
6108 if (AOP_TYPE(right) == AOP_LIT) {
6109 genLeftShiftLiteral (left,right,result,ic);
6114 /* shift count is unknown then we have to form
6115 a loop get the loop count in B : Note: we take
6116 only the lower order byte since shifting
6117 more that 32 bits make no sense anyway, ( the
6118 largest size of an object can be only 32 bits ) */
6120 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6121 emitcode("inc","b");
6122 freeAsmop (right,NULL,ic,TRUE);
6123 aopOp(left,ic,FALSE, FALSE);
6124 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6126 /* now move the left to the result if they are not the
6128 if (!sameRegs(AOP(left),AOP(result)) &&
6129 AOP_SIZE(result) > 1) {
6131 size = AOP_SIZE(result);
6133 _startLazyDPSEvaluation();
6135 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6136 if (*l == '@' && (IS_AOP_PREG(result))) {
6138 emitcode("mov","a,%s",l);
6139 aopPut(AOP(result),"a",offset);
6141 aopPut(AOP(result),l,offset);
6144 _endLazyDPSEvaluation();
6147 tlbl = newiTempLabel(NULL);
6148 size = AOP_SIZE(result);
6150 tlbl1 = newiTempLabel(NULL);
6152 /* if it is only one byte then */
6154 symbol *tlbl1 = newiTempLabel(NULL);
6156 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6158 emitcode("sjmp","%05d$",tlbl1->key+100);
6159 emitcode("","%05d$:",tlbl->key+100);
6160 emitcode("add","a,acc");
6161 emitcode("","%05d$:",tlbl1->key+100);
6162 emitcode("djnz","b,%05d$",tlbl->key+100);
6163 aopPut(AOP(result),"a",0);
6167 reAdjustPreg(AOP(result));
6169 emitcode("sjmp","%05d$",tlbl1->key+100);
6170 emitcode("","%05d$:",tlbl->key+100);
6171 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6173 emitcode("add","a,acc");
6174 aopPut(AOP(result),"a",offset++);
6175 _startLazyDPSEvaluation();
6177 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6179 emitcode("rlc","a");
6180 aopPut(AOP(result),"a",offset++);
6182 _endLazyDPSEvaluation();
6183 reAdjustPreg(AOP(result));
6185 emitcode("","%05d$:",tlbl1->key+100);
6186 emitcode("djnz","b,%05d$",tlbl->key+100);
6188 freeAsmop(left,NULL,ic,TRUE);
6189 freeAsmop(result,NULL,ic,TRUE);
6194 /*-----------------------------------------------------------------*/
6195 /* genrshOne - right shift a one byte quantity by known count */
6196 /*-----------------------------------------------------------------*/
6197 static void genrshOne (operand *result, operand *left,
6198 int shCount, int sign)
6200 D(emitcode(";", "genrshOne"););
6201 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6207 /*-----------------------------------------------------------------*/
6208 /* genrshTwo - right shift two bytes by known amount != 0 */
6209 /*-----------------------------------------------------------------*/
6210 static void genrshTwo (operand *result,operand *left,
6211 int shCount, int sign)
6213 D(emitcode(";", "genrshTwo"););
6215 /* if shCount >= 8 */
6219 shiftR1Left2Result(left, MSB16, result, LSB,
6222 movLeft2Result(left, MSB16, result, LSB, sign);
6223 addSign(result, MSB16, sign);
6226 /* 1 <= shCount <= 7 */
6228 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6234 /*-----------------------------------------------------------------*/
6235 /* shiftRLong - shift right one long from left to result */
6236 /* offl = LSB or MSB16 */
6237 /*-----------------------------------------------------------------*/
6238 static void shiftRLong (operand *left, int offl,
6239 operand *result, int sign)
6242 emitcode("clr","c");
6243 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6245 emitcode("mov","c,acc.7");
6246 emitcode("rrc","a");
6247 aopPut(AOP(result),"a",MSB32-offl);
6249 /* add sign of "a" */
6250 addSign(result, MSB32, sign);
6252 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6253 emitcode("rrc","a");
6254 aopPut(AOP(result),"a",MSB24-offl);
6256 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6257 emitcode("rrc","a");
6258 aopPut(AOP(result),"a",MSB16-offl);
6261 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6262 emitcode("rrc","a");
6263 aopPut(AOP(result),"a",LSB);
6270 /*-----------------------------------------------------------------*/
6271 /* genrshFour - shift four byte by a known amount != 0 */
6272 /*-----------------------------------------------------------------*/
6273 static void genrshFour (operand *result, operand *left,
6274 int shCount, int sign)
6276 D(emitcode(";", "genrshFour"););
6278 /* if shifting more that 3 bytes */
6279 if(shCount >= 24 ) {
6282 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6284 movLeft2Result(left, MSB32, result, LSB, sign);
6285 addSign(result, MSB16, sign);
6287 else if(shCount >= 16){
6290 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6292 movLeft2Result(left, MSB24, result, LSB, 0);
6293 movLeft2Result(left, MSB32, result, MSB16, sign);
6295 addSign(result, MSB24, sign);
6297 else if(shCount >= 8){
6300 shiftRLong(left, MSB16, result, sign);
6301 else if(shCount == 0){
6302 movLeft2Result(left, MSB16, result, LSB, 0);
6303 movLeft2Result(left, MSB24, result, MSB16, 0);
6304 movLeft2Result(left, MSB32, result, MSB24, sign);
6305 addSign(result, MSB32, sign);
6308 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6309 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6310 /* the last shift is signed */
6311 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6312 addSign(result, MSB32, sign);
6315 else{ /* 1 <= shCount <= 7 */
6317 shiftRLong(left, LSB, result, sign);
6319 shiftRLong(result, LSB, result, sign);
6322 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6323 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6324 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6332 /*-----------------------------------------------------------------*/
6333 /* genRightShiftLiteral - right shifting by known count */
6334 /*-----------------------------------------------------------------*/
6335 static void genRightShiftLiteral (operand *left,
6341 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6344 D(emitcode(";", "genRightShiftLiteral"););
6346 freeAsmop(right,NULL,ic,TRUE);
6348 aopOp(left,ic,FALSE, FALSE);
6349 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6352 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6356 size = getDataSize(left);
6357 /* test the LEFT size !!! */
6359 /* I suppose that the left size >= result size */
6361 size = getDataSize(result);
6363 movLeft2Result(left, size, result, size, 0);
6366 else if(shCount >= (size * 8)){
6368 /* get sign in acc.7 */
6369 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6370 addSign(result, LSB, sign);
6374 genrshOne (result,left,shCount,sign);
6378 genrshTwo (result,left,shCount,sign);
6382 genrshFour (result,left,shCount,sign);
6388 freeAsmop(left,NULL,ic,TRUE);
6389 freeAsmop(result,NULL,ic,TRUE);
6394 /*-----------------------------------------------------------------*/
6395 /* genSignedRightShift - right shift of signed number */
6396 /*-----------------------------------------------------------------*/
6397 static void genSignedRightShift (iCode *ic)
6399 operand *right, *left, *result;
6402 symbol *tlbl, *tlbl1 ;
6404 D(emitcode(";", "genSignedRightShift "););
6406 /* we do it the hard way put the shift count in b
6407 and loop thru preserving the sign */
6409 right = IC_RIGHT(ic);
6411 result = IC_RESULT(ic);
6413 aopOp(right,ic,FALSE, FALSE);
6416 if ( AOP_TYPE(right) == AOP_LIT) {
6417 genRightShiftLiteral (left,right,result,ic,1);
6421 /* shift count is unknown then we have to form
6422 a loop get the loop count in B : Note: we take
6423 only the lower order byte since shifting
6424 more that 32 bits make no sense anyway, ( the
6425 largest size of an object can be only 32 bits ) */
6427 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6428 emitcode("inc","b");
6429 freeAsmop (right,NULL,ic,TRUE);
6430 aopOp(left,ic,FALSE, FALSE);
6431 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6433 /* now move the left to the result if they are not the
6435 if (!sameRegs(AOP(left),AOP(result)) &&
6436 AOP_SIZE(result) > 1) {
6438 size = AOP_SIZE(result);
6440 _startLazyDPSEvaluation();
6442 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6443 if (*l == '@' && IS_AOP_PREG(result)) {
6445 emitcode("mov","a,%s",l);
6446 aopPut(AOP(result),"a",offset);
6448 aopPut(AOP(result),l,offset);
6451 _endLazyDPSEvaluation();
6454 /* mov the highest order bit to OVR */
6455 tlbl = newiTempLabel(NULL);
6456 tlbl1= newiTempLabel(NULL);
6458 size = AOP_SIZE(result);
6460 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6461 emitcode("rlc","a");
6462 emitcode("mov","ov,c");
6463 /* if it is only one byte then */
6465 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6467 emitcode("sjmp","%05d$",tlbl1->key+100);
6468 emitcode("","%05d$:",tlbl->key+100);
6469 emitcode("mov","c,ov");
6470 emitcode("rrc","a");
6471 emitcode("","%05d$:",tlbl1->key+100);
6472 emitcode("djnz","b,%05d$",tlbl->key+100);
6473 aopPut(AOP(result),"a",0);
6477 reAdjustPreg(AOP(result));
6478 emitcode("sjmp","%05d$",tlbl1->key+100);
6479 emitcode("","%05d$:",tlbl->key+100);
6480 emitcode("mov","c,ov");
6481 _startLazyDPSEvaluation();
6483 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6485 emitcode("rrc","a");
6486 aopPut(AOP(result),"a",offset--);
6488 _endLazyDPSEvaluation();
6489 reAdjustPreg(AOP(result));
6490 emitcode("","%05d$:",tlbl1->key+100);
6491 emitcode("djnz","b,%05d$",tlbl->key+100);
6494 freeAsmop(left,NULL,ic,TRUE);
6495 freeAsmop(result,NULL,ic,TRUE);
6498 /*-----------------------------------------------------------------*/
6499 /* genRightShift - generate code for right shifting */
6500 /*-----------------------------------------------------------------*/
6501 static void genRightShift (iCode *ic)
6503 operand *right, *left, *result;
6507 symbol *tlbl, *tlbl1 ;
6509 D(emitcode(";", "genRightShift "););
6511 /* if signed then we do it the hard way preserve the
6512 sign bit moving it inwards */
6513 retype = getSpec(operandType(IC_RESULT(ic)));
6515 if (!SPEC_USIGN(retype)) {
6516 genSignedRightShift (ic);
6520 /* signed & unsigned types are treated the same : i.e. the
6521 signed is NOT propagated inwards : quoting from the
6522 ANSI - standard : "for E1 >> E2, is equivalent to division
6523 by 2**E2 if unsigned or if it has a non-negative value,
6524 otherwise the result is implementation defined ", MY definition
6525 is that the sign does not get propagated */
6527 right = IC_RIGHT(ic);
6529 result = IC_RESULT(ic);
6531 aopOp(right,ic,FALSE, FALSE);
6534 /* if the shift count is known then do it
6535 as efficiently as possible */
6536 if (AOP_TYPE(right) == AOP_LIT) {
6537 genRightShiftLiteral (left,right,result,ic, 0);
6542 /* shift count is unknown then we have to form
6543 a loop get the loop count in B : Note: we take
6544 only the lower order byte since shifting
6545 more that 32 bits make no sense anyway, ( the
6546 largest size of an object can be only 32 bits ) */
6548 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6549 emitcode("inc","b");
6550 freeAsmop (right,NULL,ic,TRUE);
6551 aopOp(left,ic,FALSE, FALSE);
6552 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6554 /* now move the left to the result if they are not the
6556 if (!sameRegs(AOP(left),AOP(result)) &&
6557 AOP_SIZE(result) > 1) {
6559 size = AOP_SIZE(result);
6561 _startLazyDPSEvaluation();
6563 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6564 if (*l == '@' && IS_AOP_PREG(result)) {
6566 emitcode("mov","a,%s",l);
6567 aopPut(AOP(result),"a",offset);
6569 aopPut(AOP(result),l,offset);
6572 _endLazyDPSEvaluation();
6575 tlbl = newiTempLabel(NULL);
6576 tlbl1= newiTempLabel(NULL);
6577 size = AOP_SIZE(result);
6580 /* if it is only one byte then */
6582 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6584 emitcode("sjmp","%05d$",tlbl1->key+100);
6585 emitcode("","%05d$:",tlbl->key+100);
6587 emitcode("rrc","a");
6588 emitcode("","%05d$:",tlbl1->key+100);
6589 emitcode("djnz","b,%05d$",tlbl->key+100);
6590 aopPut(AOP(result),"a",0);
6594 reAdjustPreg(AOP(result));
6595 emitcode("sjmp","%05d$",tlbl1->key+100);
6596 emitcode("","%05d$:",tlbl->key+100);
6598 _startLazyDPSEvaluation();
6600 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6602 emitcode("rrc","a");
6603 aopPut(AOP(result),"a",offset--);
6605 _endLazyDPSEvaluation();
6606 reAdjustPreg(AOP(result));
6608 emitcode("","%05d$:",tlbl1->key+100);
6609 emitcode("djnz","b,%05d$",tlbl->key+100);
6612 freeAsmop(left,NULL,ic,TRUE);
6613 freeAsmop(result,NULL,ic,TRUE);
6616 /*-----------------------------------------------------------------*/
6617 /* genUnpackBits - generates code for unpacking bits */
6618 /*-----------------------------------------------------------------*/
6619 static void genUnpackBits (operand *result, char *rname, int ptype)
6626 D(emitcode(";", "genUnpackBits "););
6628 etype = getSpec(operandType(result));
6630 /* read the first byte */
6635 emitcode("mov","a,@%s",rname);
6639 emitcode("movx","a,@%s",rname);
6643 emitcode("movx","a,@dptr");
6647 emitcode("clr","a");
6648 emitcode("movc","a","@a+dptr");
6652 emitcode("lcall","__gptrget");
6656 /* if we have bitdisplacement then it fits */
6657 /* into this byte completely or if length is */
6658 /* less than a byte */
6659 if ((shCnt = SPEC_BSTR(etype)) ||
6660 (SPEC_BLEN(etype) <= 8)) {
6662 /* shift right acc */
6665 emitcode("anl","a,#0x%02x",
6666 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6667 aopPut(AOP(result),"a",offset);
6671 /* bit field did not fit in a byte */
6672 rlen = SPEC_BLEN(etype) - 8;
6673 aopPut(AOP(result),"a",offset++);
6680 emitcode("inc","%s",rname);
6681 emitcode("mov","a,@%s",rname);
6685 emitcode("inc","%s",rname);
6686 emitcode("movx","a,@%s",rname);
6690 emitcode("inc","dptr");
6691 emitcode("movx","a,@dptr");
6695 emitcode("clr","a");
6696 emitcode("inc","dptr");
6697 emitcode("movc","a","@a+dptr");
6701 emitcode("inc","dptr");
6702 emitcode("lcall","__gptrget");
6707 /* if we are done */
6711 aopPut(AOP(result),"a",offset++);
6716 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6717 aopPut(AOP(result),"a",offset);
6724 /*-----------------------------------------------------------------*/
6725 /* genDataPointerGet - generates code when ptr offset is known */
6726 /*-----------------------------------------------------------------*/
6727 static void genDataPointerGet (operand *left,
6733 int size , offset = 0;
6734 aopOp(result,ic,TRUE, FALSE);
6736 /* get the string representation of the name */
6737 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6738 size = AOP_SIZE(result);
6739 _startLazyDPSEvaluation();
6742 sprintf(buffer,"(%s + %d)",l+1,offset);
6744 sprintf(buffer,"%s",l+1);
6745 aopPut(AOP(result),buffer,offset++);
6747 _endLazyDPSEvaluation();
6749 freeAsmop(left,NULL,ic,TRUE);
6750 freeAsmop(result,NULL,ic,TRUE);
6753 /*-----------------------------------------------------------------*/
6754 /* genNearPointerGet - emitcode for near pointer fetch */
6755 /*-----------------------------------------------------------------*/
6756 static void genNearPointerGet (operand *left,
6763 sym_link *rtype, *retype, *letype;
6764 sym_link *ltype = operandType(left);
6767 rtype = operandType(result);
6768 retype= getSpec(rtype);
6769 letype= getSpec(ltype);
6771 aopOp(left,ic,FALSE, FALSE);
6773 /* if left is rematerialisable and
6774 result is not bit variable type and
6775 the left is pointer to data space i.e
6776 lower 128 bytes of space */
6777 if (AOP_TYPE(left) == AOP_IMMD &&
6778 !IS_BITVAR(retype) &&
6779 !IS_BITVAR(letype) &&
6780 DCL_TYPE(ltype) == POINTER) {
6781 genDataPointerGet (left,result,ic);
6785 /* if the value is already in a pointer register
6786 then don't need anything more */
6787 if (!AOP_INPREG(AOP(left))) {
6788 /* otherwise get a free pointer register */
6790 preg = getFreePtr(ic,&aop,FALSE);
6791 emitcode("mov","%s,%s",
6793 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6794 rname = preg->name ;
6796 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6798 freeAsmop(left,NULL,ic,TRUE);
6799 aopOp (result,ic,FALSE, FALSE);
6801 /* if bitfield then unpack the bits */
6802 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6803 genUnpackBits (result,rname,POINTER);
6805 /* we have can just get the values */
6806 int size = AOP_SIZE(result);
6810 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6812 emitcode("mov","a,@%s",rname);
6813 aopPut(AOP(result),"a",offset);
6815 sprintf(buffer,"@%s",rname);
6816 aopPut(AOP(result),buffer,offset);
6820 emitcode("inc","%s",rname);
6824 /* now some housekeeping stuff */
6826 /* we had to allocate for this iCode */
6827 freeAsmop(NULL,aop,ic,TRUE);
6829 /* we did not allocate which means left
6830 already in a pointer register, then
6831 if size > 0 && this could be used again
6832 we have to point it back to where it
6834 if (AOP_SIZE(result) > 1 &&
6835 !OP_SYMBOL(left)->remat &&
6836 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6838 int size = AOP_SIZE(result) - 1;
6840 emitcode("dec","%s",rname);
6845 freeAsmop(result,NULL,ic,TRUE);
6849 /*-----------------------------------------------------------------*/
6850 /* genPagedPointerGet - emitcode for paged pointer fetch */
6851 /*-----------------------------------------------------------------*/
6852 static void genPagedPointerGet (operand *left,
6859 sym_link *rtype, *retype, *letype;
6861 rtype = operandType(result);
6862 retype= getSpec(rtype);
6863 letype= getSpec(operandType(left));
6864 aopOp(left,ic,FALSE, FALSE);
6866 /* if the value is already in a pointer register
6867 then don't need anything more */
6868 if (!AOP_INPREG(AOP(left))) {
6869 /* otherwise get a free pointer register */
6871 preg = getFreePtr(ic,&aop,FALSE);
6872 emitcode("mov","%s,%s",
6874 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6875 rname = preg->name ;
6877 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6879 freeAsmop(left,NULL,ic,TRUE);
6880 aopOp (result,ic,FALSE, FALSE);
6882 /* if bitfield then unpack the bits */
6883 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6884 genUnpackBits (result,rname,PPOINTER);
6886 /* we have can just get the values */
6887 int size = AOP_SIZE(result);
6892 emitcode("movx","a,@%s",rname);
6893 aopPut(AOP(result),"a",offset);
6898 emitcode("inc","%s",rname);
6902 /* now some housekeeping stuff */
6904 /* we had to allocate for this iCode */
6905 freeAsmop(NULL,aop,ic,TRUE);
6907 /* we did not allocate which means left
6908 already in a pointer register, then
6909 if size > 0 && this could be used again
6910 we have to point it back to where it
6912 if (AOP_SIZE(result) > 1 &&
6913 !OP_SYMBOL(left)->remat &&
6914 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6916 int size = AOP_SIZE(result) - 1;
6918 emitcode("dec","%s",rname);
6923 freeAsmop(result,NULL,ic,TRUE);
6928 /*-----------------------------------------------------------------*/
6929 /* genFarPointerGet - gget value from far space */
6930 /*-----------------------------------------------------------------*/
6931 static void genFarPointerGet (operand *left,
6932 operand *result, iCode *ic)
6935 sym_link *retype = getSpec(operandType(result));
6936 sym_link *letype = getSpec(operandType(left));
6937 D(emitcode(";", "genFarPointerGet"););
6939 aopOp(left,ic,FALSE, FALSE);
6941 /* if the operand is already in dptr
6942 then we do nothing else we move the value to dptr */
6943 if (AOP_TYPE(left) != AOP_STR) {
6944 /* if this is remateriazable */
6945 if (AOP_TYPE(left) == AOP_IMMD)
6947 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6951 /* we need to get it byte by byte */
6952 _startLazyDPSEvaluation();
6953 if (AOP_TYPE(left) != AOP_DPTR)
6955 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6956 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6957 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6961 /* We need to generate a load to DPTR indirect through DPTR. */
6962 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6963 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6964 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6965 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6966 emitcode("pop", "dph");
6967 emitcode("pop", "dpl");
6969 _endLazyDPSEvaluation();
6972 /* so dptr know contains the address */
6973 freeAsmop(left,NULL,ic,TRUE);
6974 aopOp(result,ic,FALSE, TRUE);
6976 /* if bit then unpack */
6977 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6978 genUnpackBits(result,"dptr",FPOINTER);
6980 size = AOP_SIZE(result);
6983 _startLazyDPSEvaluation();
6989 emitcode("movx","a,@dptr");
6991 emitcode("inc","dptr");
6993 aopPut(AOP(result),"a",offset++);
6995 _endLazyDPSEvaluation();
6998 freeAsmop(result,NULL,ic,TRUE);
7001 /*-----------------------------------------------------------------*/
7002 /* emitcodePointerGet - gget value from code space */
7003 /*-----------------------------------------------------------------*/
7004 static void emitcodePointerGet (operand *left,
7005 operand *result, iCode *ic)
7008 sym_link *retype = getSpec(operandType(result));
7010 aopOp(left,ic,FALSE, FALSE);
7012 /* if the operand is already in dptr
7013 then we do nothing else we move the value to dptr */
7014 if (AOP_TYPE(left) != AOP_STR) {
7015 /* if this is remateriazable */
7016 if (AOP_TYPE(left) == AOP_IMMD)
7018 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7021 { /* we need to get it byte by byte */
7022 _startLazyDPSEvaluation();
7023 if (AOP_TYPE(left) != AOP_DPTR)
7025 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7026 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7027 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7031 /* We need to generate a load to DPTR indirect through DPTR. */
7032 D(emitcode(";", "gencodePointerGet -- indirection special case."););
7033 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7034 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7035 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7036 emitcode("pop", "dph");
7037 emitcode("pop", "dpl");
7039 _endLazyDPSEvaluation();
7042 /* so dptr know contains the address */
7043 freeAsmop(left,NULL,ic,TRUE);
7044 aopOp(result,ic,FALSE, TRUE);
7046 /* if bit then unpack */
7047 if (IS_BITVAR(retype))
7048 genUnpackBits(result,"dptr",CPOINTER);
7050 size = AOP_SIZE(result);
7053 _startLazyDPSEvaluation();
7059 emitcode("clr","a");
7060 emitcode("movc","a,@a+dptr");
7062 emitcode("inc","dptr");
7063 aopPut(AOP(result),"a",offset++);
7065 _endLazyDPSEvaluation();
7068 freeAsmop(result,NULL,ic,TRUE);
7071 /*-----------------------------------------------------------------*/
7072 /* genGenPointerGet - gget value from generic pointer space */
7073 /*-----------------------------------------------------------------*/
7074 static void genGenPointerGet (operand *left,
7075 operand *result, iCode *ic)
7078 sym_link *retype = getSpec(operandType(result));
7079 sym_link *letype = getSpec(operandType(left));
7081 aopOp(left,ic,FALSE, TRUE);
7083 /* if the operand is already in dptr
7084 then we do nothing else we move the value to dptr */
7085 if (AOP_TYPE(left) != AOP_STR) {
7086 /* if this is remateriazable */
7087 if (AOP_TYPE(left) == AOP_IMMD) {
7088 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7089 emitcode("mov","b,#%d",pointerCode(retype));
7091 else { /* we need to get it byte by byte */
7092 _startLazyDPSEvaluation();
7093 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7094 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7095 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7096 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7097 _endLazyDPSEvaluation();
7100 /* so dptr know contains the address */
7101 freeAsmop(left,NULL,ic,TRUE);
7102 aopOp(result,ic,FALSE, TRUE);
7104 /* if bit then unpack */
7105 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7106 genUnpackBits(result,"dptr",GPOINTER);
7108 size = AOP_SIZE(result);
7112 emitcode("lcall","__gptrget");
7113 aopPut(AOP(result),"a",offset++);
7115 emitcode("inc","dptr");
7119 freeAsmop(result,NULL,ic,TRUE);
7122 /*-----------------------------------------------------------------*/
7123 /* genPointerGet - generate code for pointer get */
7124 /*-----------------------------------------------------------------*/
7125 static void genPointerGet (iCode *ic)
7127 operand *left, *result ;
7128 sym_link *type, *etype;
7131 D(emitcode(";", "genPointerGet "););
7134 result = IC_RESULT(ic) ;
7136 /* depending on the type of pointer we need to
7137 move it to the correct pointer register */
7138 type = operandType(left);
7139 etype = getSpec(type);
7140 /* if left is of type of pointer then it is simple */
7141 if (IS_PTR(type) && !IS_FUNC(type->next))
7142 p_type = DCL_TYPE(type);
7144 /* we have to go by the storage class */
7145 p_type = PTR_TYPE(SPEC_OCLS(etype));
7148 /* now that we have the pointer type we assign
7149 the pointer values */
7154 genNearPointerGet (left,result,ic);
7158 genPagedPointerGet(left,result,ic);
7162 genFarPointerGet (left,result,ic);
7166 emitcodePointerGet (left,result,ic);
7170 genGenPointerGet (left,result,ic);
7176 /*-----------------------------------------------------------------*/
7177 /* genPackBits - generates code for packed bit storage */
7178 /*-----------------------------------------------------------------*/
7179 static void genPackBits (sym_link *etype ,
7181 char *rname, int p_type)
7189 blen = SPEC_BLEN(etype);
7190 bstr = SPEC_BSTR(etype);
7192 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7195 /* if the bit lenth is less than or */
7196 /* it exactly fits a byte then */
7197 if (SPEC_BLEN(etype) <= 8 ) {
7198 shCount = SPEC_BSTR(etype) ;
7200 /* shift left acc */
7203 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7208 emitcode ("mov","b,a");
7209 emitcode("mov","a,@%s",rname);
7213 emitcode ("mov","b,a");
7214 emitcode("movx","a,@dptr");
7218 emitcode ("push","b");
7219 emitcode ("push","acc");
7220 emitcode ("lcall","__gptrget");
7221 emitcode ("pop","b");
7225 emitcode ("anl","a,#0x%02x",(unsigned char)
7226 ((unsigned char)(0xFF << (blen+bstr)) |
7227 (unsigned char)(0xFF >> (8-bstr)) ) );
7228 emitcode ("orl","a,b");
7229 if (p_type == GPOINTER)
7230 emitcode("pop","b");
7236 emitcode("mov","@%s,a",rname);
7240 emitcode("movx","@dptr,a");
7244 emitcode("lcall","__gptrput");
7249 if ( SPEC_BLEN(etype) <= 8 )
7252 emitcode("inc","%s",rname);
7253 rLen = SPEC_BLEN(etype) ;
7255 /* now generate for lengths greater than one byte */
7258 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7268 emitcode("mov","@%s,a",rname);
7270 emitcode("mov","@%s,%s",rname,l);
7275 emitcode("movx","@dptr,a");
7280 emitcode("lcall","__gptrput");
7283 emitcode ("inc","%s",rname);
7288 /* last last was not complete */
7290 /* save the byte & read byte */
7293 emitcode ("mov","b,a");
7294 emitcode("mov","a,@%s",rname);
7298 emitcode ("mov","b,a");
7299 emitcode("movx","a,@dptr");
7303 emitcode ("push","b");
7304 emitcode ("push","acc");
7305 emitcode ("lcall","__gptrget");
7306 emitcode ("pop","b");
7310 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << rLen) );
7311 emitcode ("orl","a,b");
7314 if (p_type == GPOINTER)
7315 emitcode("pop","b");
7320 emitcode("mov","@%s,a",rname);
7324 emitcode("movx","@dptr,a");
7328 emitcode("lcall","__gptrput");
7332 /*-----------------------------------------------------------------*/
7333 /* genDataPointerSet - remat pointer to data space */
7334 /*-----------------------------------------------------------------*/
7335 static void genDataPointerSet(operand *right,
7339 int size, offset = 0 ;
7340 char *l, buffer[256];
7342 aopOp(right,ic,FALSE, FALSE);
7344 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7345 size = AOP_SIZE(right);
7348 sprintf(buffer,"(%s + %d)",l+1,offset);
7350 sprintf(buffer,"%s",l+1);
7351 emitcode("mov","%s,%s",buffer,
7352 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7355 freeAsmop(right,NULL,ic,TRUE);
7356 freeAsmop(result,NULL,ic,TRUE);
7359 /*-----------------------------------------------------------------*/
7360 /* genNearPointerSet - emitcode for near pointer put */
7361 /*-----------------------------------------------------------------*/
7362 static void genNearPointerSet (operand *right,
7369 sym_link *retype, *letype;
7370 sym_link *ptype = operandType(result);
7372 retype= getSpec(operandType(right));
7373 letype= getSpec(ptype);
7375 aopOp(result,ic,FALSE, FALSE);
7377 /* if the result is rematerializable &
7378 in data space & not a bit variable */
7379 if (AOP_TYPE(result) == AOP_IMMD &&
7380 DCL_TYPE(ptype) == POINTER &&
7381 !IS_BITVAR(retype) &&
7382 !IS_BITVAR(letype)) {
7383 genDataPointerSet (right,result,ic);
7387 /* if the value is already in a pointer register
7388 then don't need anything more */
7389 if (!AOP_INPREG(AOP(result))) {
7390 /* otherwise get a free pointer register */
7392 preg = getFreePtr(ic,&aop,FALSE);
7393 emitcode("mov","%s,%s",
7395 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7396 rname = preg->name ;
7398 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7400 freeAsmop(result,NULL,ic,TRUE);
7401 aopOp (right,ic,FALSE, FALSE);
7403 /* if bitfield then unpack the bits */
7404 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7405 genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
7407 /* we have can just get the values */
7408 int size = AOP_SIZE(right);
7412 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7415 emitcode("mov","@%s,a",rname);
7417 emitcode("mov","@%s,%s",rname,l);
7419 emitcode("inc","%s",rname);
7424 /* now some housekeeping stuff */
7426 /* we had to allocate for this iCode */
7427 freeAsmop(NULL,aop,ic,TRUE);
7429 /* we did not allocate which means left
7430 already in a pointer register, then
7431 if size > 0 && this could be used again
7432 we have to point it back to where it
7434 if (AOP_SIZE(right) > 1 &&
7435 !OP_SYMBOL(result)->remat &&
7436 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7438 int size = AOP_SIZE(right) - 1;
7440 emitcode("dec","%s",rname);
7445 freeAsmop(right,NULL,ic,TRUE);
7450 /*-----------------------------------------------------------------*/
7451 /* genPagedPointerSet - emitcode for Paged pointer put */
7452 /*-----------------------------------------------------------------*/
7453 static void genPagedPointerSet (operand *right,
7460 sym_link *retype, *letype;
7462 retype= getSpec(operandType(right));
7463 letype= getSpec(operandType(result));
7465 aopOp(result,ic,FALSE, FALSE);
7467 /* if the value is already in a pointer register
7468 then don't need anything more */
7469 if (!AOP_INPREG(AOP(result))) {
7470 /* otherwise get a free pointer register */
7472 preg = getFreePtr(ic,&aop,FALSE);
7473 emitcode("mov","%s,%s",
7475 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7476 rname = preg->name ;
7478 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7480 freeAsmop(result,NULL,ic,TRUE);
7481 aopOp (right,ic,FALSE, FALSE);
7483 /* if bitfield then unpack the bits */
7484 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7485 genPackBits ((IS_BITVAR(retype) ? retype : letype) ,right,rname,PPOINTER);
7487 /* we have can just get the values */
7488 int size = AOP_SIZE(right);
7492 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7495 emitcode("movx","@%s,a",rname);
7498 emitcode("inc","%s",rname);
7504 /* now some housekeeping stuff */
7506 /* we had to allocate for this iCode */
7507 freeAsmop(NULL,aop,ic,TRUE);
7509 /* we did not allocate which means left
7510 already in a pointer register, then
7511 if size > 0 && this could be used again
7512 we have to point it back to where it
7514 if (AOP_SIZE(right) > 1 &&
7515 !OP_SYMBOL(result)->remat &&
7516 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7518 int size = AOP_SIZE(right) - 1;
7520 emitcode("dec","%s",rname);
7525 freeAsmop(right,NULL,ic,TRUE);
7530 /*-----------------------------------------------------------------*/
7531 /* genFarPointerSet - set value from far space */
7532 /*-----------------------------------------------------------------*/
7533 static void genFarPointerSet (operand *right,
7534 operand *result, iCode *ic)
7537 sym_link *retype = getSpec(operandType(right));
7538 sym_link *letype = getSpec(operandType(result));
7540 aopOp(result,ic,FALSE, FALSE);
7542 /* if the operand is already in dptr
7543 then we do nothing else we move the value to dptr */
7544 if (AOP_TYPE(result) != AOP_STR) {
7545 /* if this is remateriazable */
7546 if (AOP_TYPE(result) == AOP_IMMD)
7547 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7550 /* we need to get it byte by byte */
7551 _startLazyDPSEvaluation();
7552 if (AOP_TYPE(result) != AOP_DPTR)
7554 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7555 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7556 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7560 /* We need to generate a load to DPTR indirect through DPTR. */
7561 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7562 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7563 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7564 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7565 emitcode("pop", "dph");
7566 emitcode("pop", "dpl");
7568 _endLazyDPSEvaluation();
7571 /* so dptr know contains the address */
7572 freeAsmop(result,NULL,ic,TRUE);
7573 aopOp(right,ic,FALSE, TRUE);
7575 /* if bit then unpack */
7576 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7577 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",FPOINTER);
7579 size = AOP_SIZE(right);
7582 _startLazyDPSEvaluation();
7584 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7590 emitcode("movx","@dptr,a");
7592 emitcode("inc","dptr");
7594 _endLazyDPSEvaluation();
7597 freeAsmop(right,NULL,ic,TRUE);
7600 /*-----------------------------------------------------------------*/
7601 /* genGenPointerSet - set value from generic pointer space */
7602 /*-----------------------------------------------------------------*/
7603 static void genGenPointerSet (operand *right,
7604 operand *result, iCode *ic)
7607 sym_link *retype = getSpec(operandType(right));
7608 sym_link *letype = getSpec(operandType(result));
7610 aopOp(result,ic,FALSE, TRUE);
7612 /* if the operand is already in dptr
7613 then we do nothing else we move the value to dptr */
7614 if (AOP_TYPE(result) != AOP_STR) {
7615 _startLazyDPSEvaluation();
7616 /* if this is remateriazable */
7617 if (AOP_TYPE(result) == AOP_IMMD) {
7618 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7619 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7621 else { /* we need to get it byte by byte */
7622 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7623 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7624 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7625 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7627 _endLazyDPSEvaluation();
7629 /* so dptr know contains the address */
7630 freeAsmop(result,NULL,ic,TRUE);
7631 aopOp(right,ic,FALSE, TRUE);
7633 /* if bit then unpack */
7634 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7635 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",GPOINTER);
7637 size = AOP_SIZE(right);
7640 _startLazyDPSEvaluation();
7642 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7648 emitcode("lcall","__gptrput");
7650 emitcode("inc","dptr");
7652 _endLazyDPSEvaluation();
7655 freeAsmop(right,NULL,ic,TRUE);
7658 /*-----------------------------------------------------------------*/
7659 /* genPointerSet - stores the value into a pointer location */
7660 /*-----------------------------------------------------------------*/
7661 static void genPointerSet (iCode *ic)
7663 operand *right, *result ;
7664 sym_link *type, *etype;
7667 D(emitcode(";", "genPointerSet "););
7669 right = IC_RIGHT(ic);
7670 result = IC_RESULT(ic) ;
7672 /* depending on the type of pointer we need to
7673 move it to the correct pointer register */
7674 type = operandType(result);
7675 etype = getSpec(type);
7676 /* if left is of type of pointer then it is simple */
7677 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7678 p_type = DCL_TYPE(type);
7681 /* we have to go by the storage class */
7682 p_type = PTR_TYPE(SPEC_OCLS(etype));
7685 /* now that we have the pointer type we assign
7686 the pointer values */
7691 genNearPointerSet (right,result,ic);
7695 genPagedPointerSet (right,result,ic);
7699 genFarPointerSet (right,result,ic);
7703 genGenPointerSet (right,result,ic);
7709 /*-----------------------------------------------------------------*/
7710 /* genIfx - generate code for Ifx statement */
7711 /*-----------------------------------------------------------------*/
7712 static void genIfx (iCode *ic, iCode *popIc)
7714 operand *cond = IC_COND(ic);
7717 D(emitcode(";", "genIfx "););
7719 aopOp(cond,ic,FALSE, FALSE);
7721 /* get the value into acc */
7722 if (AOP_TYPE(cond) != AOP_CRY)
7726 /* the result is now in the accumulator */
7727 freeAsmop(cond,NULL,ic,TRUE);
7729 /* if there was something to be popped then do it */
7733 /* if the condition is a bit variable */
7734 if (isbit && IS_ITEMP(cond) &&
7736 genIfxJump(ic,SPIL_LOC(cond)->rname);
7738 if (isbit && !IS_ITEMP(cond))
7739 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7746 /*-----------------------------------------------------------------*/
7747 /* genAddrOf - generates code for address of */
7748 /*-----------------------------------------------------------------*/
7749 static void genAddrOf (iCode *ic)
7751 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7754 D(emitcode(";", "genAddrOf "););
7756 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7758 /* if the operand is on the stack then we
7759 need to get the stack offset of this
7762 /* if it has an offset then we need to compute
7765 emitcode("mov","a,_bp");
7766 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7767 aopPut(AOP(IC_RESULT(ic)),"a",0);
7769 /* we can just move _bp */
7770 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7772 /* fill the result with zero */
7773 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7776 if (options.stack10bit && size < (FPTRSIZE - 1))
7779 "*** warning: pointer to stack var truncated.\n");
7786 if (options.stack10bit && offset == 2)
7788 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7792 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7799 /* object not on stack then we need the name */
7800 size = AOP_SIZE(IC_RESULT(ic));
7804 char s[SDCC_NAME_MAX];
7806 sprintf(s,"#(%s >> %d)",
7810 sprintf(s,"#%s",sym->rname);
7811 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7815 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7819 /*-----------------------------------------------------------------*/
7820 /* genFarFarAssign - assignment when both are in far space */
7821 /*-----------------------------------------------------------------*/
7822 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7824 int size = AOP_SIZE(right);
7831 /* This is a net loss for size == 1, but a big gain
7834 D(emitcode(";", "genFarFarAssign (improved)"););
7836 aopOp(result,ic,TRUE, TRUE);
7838 _startLazyDPSEvaluation();
7842 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7846 _endLazyDPSEvaluation();
7847 freeAsmop(result,NULL,ic,FALSE);
7848 freeAsmop(right,NULL,ic,FALSE);
7853 D(emitcode(";", "genFarFarAssign "););
7855 /* first push the right side on to the stack */
7856 _startLazyDPSEvaluation();
7858 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7860 emitcode ("push","acc");
7863 freeAsmop(right,NULL,ic,FALSE);
7864 /* now assign DPTR to result */
7865 aopOp(result,ic,FALSE, FALSE);
7866 size = AOP_SIZE(result);
7868 emitcode ("pop","acc");
7869 aopPut(AOP(result),"a",--offset);
7871 freeAsmop(result,NULL,ic,FALSE);
7872 _endLazyDPSEvaluation();
7876 /*-----------------------------------------------------------------*/
7877 /* genAssign - generate code for assignment */
7878 /*-----------------------------------------------------------------*/
7879 static void genAssign (iCode *ic)
7881 operand *result, *right;
7883 unsigned long lit = 0L;
7885 D(emitcode(";", "genAssign "););
7887 result = IC_RESULT(ic);
7888 right = IC_RIGHT(ic) ;
7890 /* if they are the same */
7891 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7894 aopOp(right,ic,FALSE, FALSE);
7896 emitcode(";", "genAssign: resultIsFar = %s",
7897 isOperandInFarSpace(result) ?
7900 /* special case both in far space */
7901 if ((AOP_TYPE(right) == AOP_DPTR ||
7902 AOP_TYPE(right) == AOP_DPTR2) &&
7903 /* IS_TRUE_SYMOP(result) && */
7904 isOperandInFarSpace(result)) {
7906 genFarFarAssign (result,right,ic);
7910 aopOp(result,ic,TRUE, FALSE);
7912 /* if they are the same registers */
7913 if (sameRegs(AOP(right),AOP(result)))
7916 /* if the result is a bit */
7917 if (AOP_TYPE(result) == AOP_CRY) {
7919 /* if the right size is a literal then
7920 we know what the value is */
7921 if (AOP_TYPE(right) == AOP_LIT) {
7922 if (((int) operandLitValue(right)))
7923 aopPut(AOP(result),one,0);
7925 aopPut(AOP(result),zero,0);
7929 /* the right is also a bit variable */
7930 if (AOP_TYPE(right) == AOP_CRY) {
7931 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7932 aopPut(AOP(result),"c",0);
7938 aopPut(AOP(result),"a",0);
7942 /* bit variables done */
7944 size = AOP_SIZE(result);
7946 if(AOP_TYPE(right) == AOP_LIT)
7947 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7950 (AOP_TYPE(result) != AOP_REG) &&
7951 (AOP_TYPE(right) == AOP_LIT) &&
7952 !IS_FLOAT(operandType(right))
7953 #ifndef LAZY_DPS_OPT
7959 D(emitcode(";", "Kevin's better literal load code"););
7960 _startLazyDPSEvaluation();
7961 while (size && ((unsigned int)(lit >> (offset*8)) != 0))
7964 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
7969 /* And now fill the rest with zeros. */
7972 emitcode("clr","a");
7976 aopPut(AOP(result), "a", offset++);
7978 _endLazyDPSEvaluation();
7980 emitcode("clr","a");
7982 _startLazyDPSEvaluation();
7985 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7986 aopPut(AOP(result),"a",size);
7989 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
7992 _endLazyDPSEvaluation();
7997 _startLazyDPSEvaluation();
8001 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8005 _endLazyDPSEvaluation();
8009 freeAsmop (right,NULL,ic,FALSE);
8010 freeAsmop (result,NULL,ic,TRUE);
8013 /*-----------------------------------------------------------------*/
8014 /* genJumpTab - generates code for jump table */
8015 /*-----------------------------------------------------------------*/
8016 static void genJumpTab (iCode *ic)
8021 D(emitcode(";", "genJumpTab "););
8023 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
8024 /* get the condition into accumulator */
8025 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
8027 /* multiply by four! */
8028 emitcode("add","a,acc");
8029 emitcode("add","a,acc");
8030 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8032 jtab = newiTempLabel(NULL);
8033 emitcode("mov","dptr,#%05d$",jtab->key+100);
8034 emitcode("jmp","@a+dptr");
8035 emitcode("","%05d$:",jtab->key+100);
8036 /* now generate the jump labels */
8037 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8038 jtab = setNextItem(IC_JTLABELS(ic)))
8039 emitcode("ljmp","%05d$",jtab->key+100);
8043 /*-----------------------------------------------------------------*/
8044 /* genCast - gen code for casting */
8045 /*-----------------------------------------------------------------*/
8046 static void genCast (iCode *ic)
8048 operand *result = IC_RESULT(ic);
8049 sym_link *ctype = operandType(IC_LEFT(ic));
8050 sym_link *rtype = operandType(IC_RIGHT(ic));
8051 operand *right = IC_RIGHT(ic);
8054 D(emitcode(";", "genCast "););
8056 /* if they are equivalent then do nothing */
8057 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8060 aopOp(right,ic,FALSE, FALSE) ;
8061 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
8063 /* if the result is a bit */
8064 if (AOP_TYPE(result) == AOP_CRY) {
8065 /* if the right size is a literal then
8066 we know what the value is */
8067 if (AOP_TYPE(right) == AOP_LIT) {
8068 if (((int) operandLitValue(right)))
8069 aopPut(AOP(result),one,0);
8071 aopPut(AOP(result),zero,0);
8076 /* the right is also a bit variable */
8077 if (AOP_TYPE(right) == AOP_CRY) {
8078 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8079 aopPut(AOP(result),"c",0);
8085 aopPut(AOP(result),"a",0);
8089 /* if they are the same size : or less */
8090 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8092 /* if they are in the same place */
8093 if (sameRegs(AOP(right),AOP(result)))
8096 /* if they in different places then copy */
8097 size = AOP_SIZE(result);
8099 _startLazyDPSEvaluation();
8102 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8106 _endLazyDPSEvaluation();
8111 /* if the result is of type pointer */
8112 if (IS_PTR(ctype)) {
8115 sym_link *type = operandType(right);
8117 /* pointer to generic pointer */
8118 if (IS_GENPTR(ctype)) {
8123 p_type = DCL_TYPE(type);
8127 #if OLD_CAST_BEHAVIOR
8128 /* KV: we are converting a non-pointer type to
8129 * a generic pointer. This (ifdef'd out) code
8130 * says that the resulting generic pointer
8131 * should have the same class as the storage
8132 * location of the non-pointer variable.
8134 * For example, converting an int (which happens
8135 * to be stored in DATA space) to a pointer results
8136 * in a DATA generic pointer; if the original int
8137 * in XDATA space, so will be the resulting pointer.
8139 * I don't like that behavior, and thus this change:
8140 * all such conversions will be forced to XDATA and
8141 * throw a warning. If you want some non-XDATA
8142 * type, or you want to suppress the warning, you
8143 * must go through an intermediate cast, like so:
8145 * char _generic *gp = (char _xdata *)(intVar);
8147 sym_link *etype = getSpec(type);
8149 /* we have to go by the storage class */
8150 if (SPEC_OCLS(etype) != generic)
8152 p_type = PTR_TYPE(SPEC_OCLS(etype));
8157 /* Converting unknown class (i.e. register variable)
8158 * to generic pointer. This is not good, but
8159 * we'll make a guess (and throw a warning).
8162 werror(W_INT_TO_GEN_PTR_CAST);
8166 /* the first two bytes are known */
8167 size = GPTRSIZE - 1;
8169 _startLazyDPSEvaluation();
8172 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8176 _endLazyDPSEvaluation();
8178 /* the last byte depending on type */
8195 /* this should never happen */
8196 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8197 "got unknown pointer type");
8200 aopPut(AOP(result),l, GPTRSIZE - 1);
8204 /* just copy the pointers */
8205 size = AOP_SIZE(result);
8207 _startLazyDPSEvaluation();
8210 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8214 _endLazyDPSEvaluation();
8218 /* so we now know that the size of destination is greater
8219 than the size of the source */
8220 /* we move to result for the size of source */
8221 size = AOP_SIZE(right);
8223 _startLazyDPSEvaluation();
8226 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8230 _endLazyDPSEvaluation();
8232 /* now depending on the sign of the source && destination */
8233 size = AOP_SIZE(result) - AOP_SIZE(right);
8234 /* if unsigned or not an integral type */
8235 /* also, if the source is a bit, we don't need to sign extend, because
8236 * it can't possibly have set the sign bit.
8238 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype) || AOP_TYPE(right) == AOP_CRY)
8242 aopPut(AOP(result),zero,offset++);
8247 /* we need to extend the sign :{ */
8248 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8251 emitcode("rlc","a");
8252 emitcode("subb","a,acc");
8254 aopPut(AOP(result),"a",offset++);
8257 /* we are done hurray !!!! */
8260 freeAsmop(right,NULL,ic,TRUE);
8261 freeAsmop(result,NULL,ic,TRUE);
8265 /*-----------------------------------------------------------------*/
8266 /* genDjnz - generate decrement & jump if not zero instrucion */
8267 /*-----------------------------------------------------------------*/
8268 static int genDjnz (iCode *ic, iCode *ifx)
8274 /* if the if condition has a false label
8275 then we cannot save */
8279 /* if the minus is not of the form
8281 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8282 !IS_OP_LITERAL(IC_RIGHT(ic)))
8285 if (operandLitValue(IC_RIGHT(ic)) != 1)
8288 /* if the size of this greater than one then no
8290 if (getSize(operandType(IC_RESULT(ic))) > 1)
8293 /* otherwise we can save BIG */
8294 lbl = newiTempLabel(NULL);
8295 lbl1= newiTempLabel(NULL);
8297 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8299 if (IS_AOP_PREG(IC_RESULT(ic))) {
8300 emitcode("dec","%s",
8301 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8302 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8303 emitcode("jnz","%05d$",lbl->key+100);
8305 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8308 emitcode ("sjmp","%05d$",lbl1->key+100);
8309 emitcode ("","%05d$:",lbl->key+100);
8310 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8311 emitcode ("","%05d$:",lbl1->key+100);
8313 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8318 /*-----------------------------------------------------------------*/
8319 /* genReceive - generate code for a receive iCode */
8320 /*-----------------------------------------------------------------*/
8321 static void genReceive (iCode *ic)
8324 D(emitcode(";", "genReceive "););
8326 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8327 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8328 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8329 int size = getSize(operandType(IC_RESULT(ic)));
8330 int offset = fReturnSize_390 - size;
8332 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8333 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8336 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8337 size = AOP_SIZE(IC_RESULT(ic));
8340 emitcode ("pop","acc");
8341 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8346 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8348 assignResultValue(IC_RESULT(ic));
8351 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8354 /*-----------------------------------------------------------------*/
8355 /* gen390Code - generate code for Dallas 390 based controllers */
8356 /*-----------------------------------------------------------------*/
8357 void gen390Code (iCode *lic)
8362 lineHead = lineCurr = NULL;
8366 /* print the allocation information */
8368 printAllocInfo( currFunc, codeOutFile);
8370 /* if debug information required */
8371 if (options.debug && currFunc) {
8372 //jwk if (currFunc) {
8373 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8375 if (IS_STATIC(currFunc->etype))
8376 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8378 emitcode("","G$%s$0$0 ==.",currFunc->name);
8381 /* stack pointer name */
8382 if (options.useXstack)
8388 for (ic = lic ; ic ; ic = ic->next ) {
8390 if ( cln != ic->lineno ) {
8391 if ( options.debug ) {
8393 emitcode("","C$%s$%d$%d$%d ==.",
8394 ic->filename,ic->lineno,
8395 ic->level,ic->block);
8398 emitcode(";","%s %d",ic->filename,ic->lineno);
8401 /* if the result is marked as
8402 spilt and rematerializable or code for
8403 this has already been generated then
8405 if (resultRemat(ic) || ic->generated )
8408 /* depending on the operation */
8427 /* IPOP happens only when trying to restore a
8428 spilt live range, if there is an ifx statement
8429 following this pop then the if statement might
8430 be using some of the registers being popped which
8431 would destory the contents of the register so
8432 we need to check for this condition and handle it */
8434 ic->next->op == IFX &&
8435 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8436 genIfx (ic->next,ic);
8454 genEndFunction (ic);
8474 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8491 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8495 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8502 /* note these two are xlated by algebraic equivalence
8503 during parsing SDCC.y */
8504 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8505 "got '>=' or '<=' shouldn't have come here");
8509 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8521 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8525 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8529 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8556 case GET_VALUE_AT_ADDRESS:
8561 if (POINTER_SET(ic))
8588 addSet(&_G.sendSet,ic);
8593 /* piCode(ic,stdout); */
8599 /* now we are ready to call the
8600 peep hole optimizer */
8601 if (!options.nopeep)
8602 peepHole (&lineHead);
8604 /* now do the actual printing */
8605 printLine (lineHead,codeOutFile);