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>
46 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
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);
1360 aopPut(AOP(result),"a",0);
1363 /* unsigned or positive */
1365 aopPut(AOP(result),zero,offset++);
1370 /*-----------------------------------------------------------------*/
1371 /* outBitC - output a bit C */
1372 /*-----------------------------------------------------------------*/
1373 static void outBitC(operand *result)
1375 /* if the result is bit */
1376 if (AOP_TYPE(result) == AOP_CRY)
1378 aopPut(AOP(result),"c",0);
1382 emitcode("clr","a");
1383 emitcode("rlc","a");
1388 /*-----------------------------------------------------------------*/
1389 /* toBoolean - emit code for orl a,operator(sizeop) */
1390 /*-----------------------------------------------------------------*/
1391 static void toBoolean(operand *oper)
1393 int size = AOP_SIZE(oper) - 1;
1396 /* The generic part of a generic pointer should
1397 * not participate in it's truth value.
1399 * i.e. 0x10000000 is zero.
1403 D(emitcode(";", "toBoolean: generic ptr special case."););
1407 _startLazyDPSEvaluation();
1408 if (AOP_NEEDSACC(oper))
1410 emitcode("push", "b");
1411 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1415 MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1419 if (AOP_NEEDSACC(oper))
1421 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1425 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1428 _endLazyDPSEvaluation();
1430 if (AOP_NEEDSACC(oper))
1432 emitcode("mov", "a,b");
1433 emitcode("pop", "b");
1438 /*-----------------------------------------------------------------*/
1439 /* genNot - generate code for ! operation */
1440 /*-----------------------------------------------------------------*/
1441 static void genNot (iCode *ic)
1444 sym_link *optype = operandType(IC_LEFT(ic));
1446 D(emitcode(";", "genNot "););
1448 /* assign asmOps to operand & result */
1449 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1450 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1452 /* if in bit space then a special case */
1453 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1454 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1455 emitcode("cpl","c");
1456 outBitC(IC_RESULT(ic));
1460 /* if type float then do float */
1461 if (IS_FLOAT(optype)) {
1462 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1466 toBoolean(IC_LEFT(ic));
1468 tlbl = newiTempLabel(NULL);
1469 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1470 emitcode("","%05d$:",tlbl->key+100);
1471 outBitC(IC_RESULT(ic));
1474 /* release the aops */
1475 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1476 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1480 /*-----------------------------------------------------------------*/
1481 /* genCpl - generate code for complement */
1482 /*-----------------------------------------------------------------*/
1483 static void genCpl (iCode *ic)
1488 D(emitcode(";", "genCpl "););
1491 /* assign asmOps to operand & result */
1492 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1493 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1495 /* if both are in bit space then
1497 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1498 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1500 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1501 emitcode("cpl","c");
1502 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1506 size = AOP_SIZE(IC_RESULT(ic));
1507 _startLazyDPSEvaluation();
1509 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1511 emitcode("cpl","a");
1512 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1514 _endLazyDPSEvaluation();
1518 /* release the aops */
1519 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1520 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1523 /*-----------------------------------------------------------------*/
1524 /* genUminusFloat - unary minus for floating points */
1525 /*-----------------------------------------------------------------*/
1526 static void genUminusFloat(operand *op,operand *result)
1528 int size ,offset =0 ;
1530 /* for this we just need to flip the
1531 first it then copy the rest in place */
1532 D(emitcode(";", "genUminusFloat"););
1534 _startLazyDPSEvaluation();
1535 size = AOP_SIZE(op) - 1;
1536 l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1539 emitcode("cpl","acc.7");
1540 aopPut(AOP(result),"a",3);
1544 aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1548 _endLazyDPSEvaluation();
1551 /*-----------------------------------------------------------------*/
1552 /* genUminus - unary minus code generation */
1553 /*-----------------------------------------------------------------*/
1554 static void genUminus (iCode *ic)
1557 sym_link *optype, *rtype;
1559 D(emitcode(";", "genUminus "););
1563 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1564 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1566 /* if both in bit space then special
1568 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1569 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1571 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1572 emitcode("cpl","c");
1573 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1577 optype = operandType(IC_LEFT(ic));
1578 rtype = operandType(IC_RESULT(ic));
1580 /* if float then do float stuff */
1581 if (IS_FLOAT(optype)) {
1582 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1586 /* otherwise subtract from zero */
1587 size = AOP_SIZE(IC_LEFT(ic));
1589 _startLazyDPSEvaluation();
1591 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1592 if (!strcmp(l,"a")) {
1595 emitcode("cpl","a");
1596 emitcode("addc", "a,#0");
1600 emitcode("clr","a");
1601 emitcode("subb","a,%s",l);
1603 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1605 _endLazyDPSEvaluation();
1607 /* if any remaining bytes in the result */
1608 /* we just need to propagate the sign */
1609 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1610 emitcode("rlc","a");
1611 emitcode("subb","a,acc");
1613 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1617 /* release the aops */
1618 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1619 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1622 /*-----------------------------------------------------------------*/
1623 /* saveRegisters - will look for a call and save the registers */
1624 /*-----------------------------------------------------------------*/
1625 static void saveRegisters(iCode *lic)
1633 for (ic = lic ; ic ; ic = ic->next)
1634 if (ic->op == CALL || ic->op == PCALL)
1638 fprintf(stderr,"found parameter push with no function call\n");
1642 /* if the registers have been saved already then
1644 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1647 /* find the registers in use at this time
1648 and push them away to safety */
1649 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1653 if (options.useXstack) {
1654 if (bitVectBitValue(rsave,R0_IDX))
1655 emitcode("mov","b,r0");
1656 emitcode("mov","r0,%s",spname);
1657 for (i = 0 ; i < ds390_nRegs ; i++) {
1658 if (bitVectBitValue(rsave,i)) {
1660 emitcode("mov","a,b");
1662 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1663 emitcode("movx","@r0,a");
1664 emitcode("inc","r0");
1667 emitcode("mov","%s,r0",spname);
1668 if (bitVectBitValue(rsave,R0_IDX))
1669 emitcode("mov","r0,b");
1671 for (i = 0 ; i < ds390_nRegs ; i++) {
1672 if (bitVectBitValue(rsave,i))
1673 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1676 detype = getSpec(operandType(IC_LEFT(ic)));
1678 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1679 IS_ISR(currFunc->etype) &&
1682 saverbank(SPEC_BANK(detype),ic,TRUE);
1685 /*-----------------------------------------------------------------*/
1686 /* unsaveRegisters - pop the pushed registers */
1687 /*-----------------------------------------------------------------*/
1688 static void unsaveRegisters (iCode *ic)
1692 /* find the registers in use at this time
1693 and push them away to safety */
1694 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1697 if (options.useXstack) {
1698 emitcode("mov","r0,%s",spname);
1699 for (i = ds390_nRegs ; i >= 0 ; i--) {
1700 if (bitVectBitValue(rsave,i)) {
1701 emitcode("dec","r0");
1702 emitcode("movx","a,@r0");
1704 emitcode("mov","b,a");
1706 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1710 emitcode("mov","%s,r0",spname);
1711 if (bitVectBitValue(rsave,R0_IDX))
1712 emitcode("mov","r0,b");
1714 for (i = ds390_nRegs ; i >= 0 ; i--) {
1715 if (bitVectBitValue(rsave,i))
1716 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1722 /*-----------------------------------------------------------------*/
1724 /*-----------------------------------------------------------------*/
1725 static void pushSide(operand * oper, int size)
1728 _startLazyDPSEvaluation();
1730 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1731 if (AOP_TYPE(oper) != AOP_REG &&
1732 AOP_TYPE(oper) != AOP_DIR &&
1734 emitcode("mov","a,%s",l);
1735 emitcode("push","acc");
1737 emitcode("push","%s",l);
1739 _endLazyDPSEvaluation();
1742 /*-----------------------------------------------------------------*/
1743 /* assignResultValue - */
1744 /*-----------------------------------------------------------------*/
1745 static void assignResultValue(operand * oper)
1748 int size = AOP_SIZE(oper);
1750 _startLazyDPSEvaluation();
1752 aopPut(AOP(oper),fReturn[offset],offset);
1755 _endLazyDPSEvaluation();
1759 /*-----------------------------------------------------------------*/
1760 /* genXpush - pushes onto the external stack */
1761 /*-----------------------------------------------------------------*/
1762 static void genXpush (iCode *ic)
1764 asmop *aop = newAsmop(0);
1766 int size,offset = 0;
1768 D(emitcode(";", "genXpush "););
1770 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1771 r = getFreePtr(ic,&aop,FALSE);
1774 emitcode("mov","%s,_spx",r->name);
1776 size = AOP_SIZE(IC_LEFT(ic));
1777 _startLazyDPSEvaluation();
1780 char *l = aopGet(AOP(IC_LEFT(ic)),
1781 offset++,FALSE,FALSE,TRUE);
1783 emitcode("movx","@%s,a",r->name);
1784 emitcode("inc","%s",r->name);
1787 _endLazyDPSEvaluation();
1790 emitcode("mov","_spx,%s",r->name);
1792 freeAsmop(NULL,aop,ic,TRUE);
1793 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1796 /*-----------------------------------------------------------------*/
1797 /* genIpush - genrate code for pushing this gets a little complex */
1798 /*-----------------------------------------------------------------*/
1799 static void genIpush (iCode *ic)
1801 int size, offset = 0 ;
1804 D(emitcode(";", "genIpush "););
1807 /* if this is not a parm push : ie. it is spill push
1808 and spill push is always done on the local stack */
1809 if (!ic->parmPush) {
1811 /* and the item is spilt then do nothing */
1812 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1815 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1816 size = AOP_SIZE(IC_LEFT(ic));
1817 /* push it on the stack */
1818 _startLazyDPSEvaluation();
1820 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1825 emitcode("push","%s",l);
1827 _endLazyDPSEvaluation();
1831 /* this is a paramter push: in this case we call
1832 the routine to find the call and save those
1833 registers that need to be saved */
1836 /* if use external stack then call the external
1837 stack pushing routine */
1838 if (options.useXstack) {
1843 /* then do the push */
1844 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1846 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1847 size = AOP_SIZE(IC_LEFT(ic));
1849 _startLazyDPSEvaluation();
1851 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1852 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1853 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1855 emitcode("mov","a,%s",l);
1856 emitcode("push","acc");
1858 emitcode("push","%s",l);
1860 _endLazyDPSEvaluation();
1862 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1865 /*-----------------------------------------------------------------*/
1866 /* genIpop - recover the registers: can happen only for spilling */
1867 /*-----------------------------------------------------------------*/
1868 static void genIpop (iCode *ic)
1872 D(emitcode(";", "genIpop "););
1875 /* if the temp was not pushed then */
1876 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1879 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1880 size = AOP_SIZE(IC_LEFT(ic));
1882 _startLazyDPSEvaluation();
1885 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1888 _endLazyDPSEvaluation();
1890 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1893 /*-----------------------------------------------------------------*/
1894 /* unsaverbank - restores the resgister bank from stack */
1895 /*-----------------------------------------------------------------*/
1896 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1903 if (options.useXstack) {
1905 r = getFreePtr(ic,&aop,FALSE);
1908 emitcode("mov","%s,_spx",r->name);
1909 emitcode("movx","a,@%s",r->name);
1910 emitcode("mov","psw,a");
1911 emitcode("dec","%s",r->name);
1914 emitcode ("pop","psw");
1917 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1918 if (options.useXstack) {
1919 emitcode("movx","a,@%s",r->name);
1920 emitcode("mov","(%s+%d),a",
1921 regs390[i].base,8*bank+regs390[i].offset);
1922 emitcode("dec","%s",r->name);
1925 emitcode("pop","(%s+%d)",
1926 regs390[i].base,8*bank+regs390[i].offset);
1929 if (options.useXstack) {
1931 emitcode("mov","_spx,%s",r->name);
1932 freeAsmop(NULL,aop,ic,TRUE);
1937 /*-----------------------------------------------------------------*/
1938 /* saverbank - saves an entire register bank on the stack */
1939 /*-----------------------------------------------------------------*/
1940 static void saverbank (int bank, iCode *ic, bool pushPsw)
1946 if (options.useXstack) {
1949 r = getFreePtr(ic,&aop,FALSE);
1950 emitcode("mov","%s,_spx",r->name);
1954 for (i = 0 ; i < ds390_nRegs ;i++) {
1955 if (options.useXstack) {
1956 emitcode("inc","%s",r->name);
1957 emitcode("mov","a,(%s+%d)",
1958 regs390[i].base,8*bank+regs390[i].offset);
1959 emitcode("movx","@%s,a",r->name);
1961 emitcode("push","(%s+%d)",
1962 regs390[i].base,8*bank+regs390[i].offset);
1966 if (options.useXstack) {
1967 emitcode("mov","a,psw");
1968 emitcode("movx","@%s,a",r->name);
1969 emitcode("inc","%s",r->name);
1970 emitcode("mov","_spx,%s",r->name);
1971 freeAsmop (NULL,aop,ic,TRUE);
1974 emitcode("push","psw");
1976 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1982 /*-----------------------------------------------------------------*/
1983 /* genCall - generates a call statement */
1984 /*-----------------------------------------------------------------*/
1985 static void genCall (iCode *ic)
1989 D(emitcode(";", "genCall "););
1991 /* if caller saves & we have not saved then */
1995 /* if we are calling a function that is not using
1996 the same register bank then we need to save the
1997 destination registers on the stack */
1998 detype = getSpec(operandType(IC_LEFT(ic)));
2000 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2001 IS_ISR(currFunc->etype) &&
2004 saverbank(SPEC_BANK(detype),ic,TRUE);
2006 /* if send set is not empty the assign */
2010 for (sic = setFirstItem(_G.sendSet) ; sic ;
2011 sic = setNextItem(_G.sendSet))
2013 int size, offset = 0;
2015 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
2016 size = AOP_SIZE(IC_LEFT(sic));
2018 _startLazyDPSEvaluation();
2020 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2021 FALSE, FALSE, TRUE);
2022 if (strcmp(l,fReturn[offset]))
2023 emitcode("mov","%s,%s",
2028 _endLazyDPSEvaluation();
2029 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2034 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2035 OP_SYMBOL(IC_LEFT(ic))->rname :
2036 OP_SYMBOL(IC_LEFT(ic))->name));
2038 /* if we need assign a result value */
2039 if ((IS_ITEMP(IC_RESULT(ic)) &&
2040 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2041 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2042 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2045 /* Not really related to LAZY_DPS_OPT, but don't want
2046 * another testing flag right now...
2048 #define FAR_RETURN_OPT
2049 #ifdef FAR_RETURN_OPT
2050 if (isOperandInFarSpace(IC_RESULT(ic))
2051 && getSize(operandType(IC_RESULT(ic))) <= 2)
2053 int size = getSize(operandType(IC_RESULT(ic)));
2055 /* Special case for 1 or 2 byte return in far space. */
2056 emitcode(";", "Kevin function call abuse #1");
2061 emitcode("mov", "b,%s", fReturn[1]);
2064 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2065 aopPut(AOP(IC_RESULT(ic)),"a",0);
2069 aopPut(AOP(IC_RESULT(ic)),"b",1);
2071 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2077 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2080 assignResultValue(IC_RESULT(ic));
2082 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2085 if (!isOperandInFarSpace(IC_RESULT(ic)))
2088 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2091 assignResultValue(IC_RESULT(ic));
2093 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2097 /* Result is in far space, and requires DPTR to access
2098 * it. Push the result onto the stack and restore from
2101 int size = getSize(operandType(IC_RESULT(ic)));
2102 int offset = size - 1;
2105 emitcode(";", "Kevin function call abuse #1");
2107 /* first push the right side on to the stack */
2108 /* NB: this relies on the fact that "a" is the last
2109 * register in fReturn. If it were not, the MOVA
2110 * would potentially clobber a returned byte in A.
2113 l = fReturn[offset--];
2115 emitcode ("push","acc");
2118 /* now assign DPTR to result */
2119 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2120 size = AOP_SIZE(IC_RESULT(ic));
2121 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
2123 emitcode ("pop","acc");
2124 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
2126 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2131 /* adjust the stack for parameters if
2133 if (IC_LEFT(ic)->parmBytes) {
2135 if (IC_LEFT(ic)->parmBytes > 3) {
2136 emitcode("mov","a,%s",spname);
2137 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2138 emitcode("mov","%s,a",spname);
2140 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2141 emitcode("dec","%s",spname);
2145 /* if register bank was saved then pop them */
2147 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2149 /* if we hade saved some registers then unsave them */
2150 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2151 unsaveRegisters (ic);
2156 /*-----------------------------------------------------------------*/
2157 /* genPcall - generates a call by pointer statement */
2158 /*-----------------------------------------------------------------*/
2159 static void genPcall (iCode *ic)
2162 symbol *rlbl = newiTempLabel(NULL);
2164 D(emitcode(";", "genPcall "););
2167 /* if caller saves & we have not saved then */
2171 /* if we are calling a function that is not using
2172 the same register bank then we need to save the
2173 destination registers on the stack */
2174 detype = getSpec(operandType(IC_LEFT(ic)));
2176 IS_ISR(currFunc->etype) &&
2177 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2178 saverbank(SPEC_BANK(detype),ic,TRUE);
2181 /* push the return address on to the stack */
2182 emitcode("mov","a,#%05d$",(rlbl->key+100));
2183 emitcode("push","acc");
2184 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2185 emitcode("push","acc");
2187 if (options.model == MODEL_FLAT24)
2189 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2190 emitcode("push","acc");
2193 /* now push the calling address */
2194 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2196 pushSide(IC_LEFT(ic), FPTRSIZE);
2198 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2200 /* if send set is not empty the assign */
2204 for (sic = setFirstItem(_G.sendSet) ; sic ;
2205 sic = setNextItem(_G.sendSet))
2207 int size, offset = 0;
2209 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2210 size = AOP_SIZE(IC_LEFT(sic));
2211 _startLazyDPSEvaluation();
2214 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2216 if (strcmp(l,fReturn[offset]))
2218 emitcode("mov","%s,%s",
2224 _endLazyDPSEvaluation();
2225 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2231 emitcode("","%05d$:",(rlbl->key+100));
2234 /* if we need assign a result value */
2235 if ((IS_ITEMP(IC_RESULT(ic)) &&
2236 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2237 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2238 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2241 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2244 assignResultValue(IC_RESULT(ic));
2246 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2249 /* adjust the stack for parameters if
2251 if (IC_LEFT(ic)->parmBytes) {
2253 if (IC_LEFT(ic)->parmBytes > 3) {
2254 emitcode("mov","a,%s",spname);
2255 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2256 emitcode("mov","%s,a",spname);
2258 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2259 emitcode("dec","%s",spname);
2263 /* if register bank was saved then unsave them */
2265 (SPEC_BANK(currFunc->etype) !=
2267 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2269 /* if we hade saved some registers then
2272 unsaveRegisters (ic);
2276 /*-----------------------------------------------------------------*/
2277 /* resultRemat - result is rematerializable */
2278 /*-----------------------------------------------------------------*/
2279 static int resultRemat (iCode *ic)
2281 if (SKIP_IC(ic) || ic->op == IFX)
2284 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2285 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2286 if (sym->remat && !POINTER_SET(ic))
2293 #if defined(__BORLANDC__) || defined(_MSC_VER)
2294 #define STRCASECMP stricmp
2296 #define STRCASECMP strcasecmp
2299 /*-----------------------------------------------------------------*/
2300 /* inExcludeList - return 1 if the string is in exclude Reg list */
2301 /*-----------------------------------------------------------------*/
2302 static bool inExcludeList(char *s)
2306 if (options.excludeRegs[i] &&
2307 STRCASECMP(options.excludeRegs[i],"none") == 0)
2310 for ( i = 0 ; options.excludeRegs[i]; i++) {
2311 if (options.excludeRegs[i] &&
2312 STRCASECMP(s,options.excludeRegs[i]) == 0)
2318 /*-----------------------------------------------------------------*/
2319 /* genFunction - generated code for function entry */
2320 /*-----------------------------------------------------------------*/
2321 static void genFunction (iCode *ic)
2326 D(emitcode(";", "genFunction "););
2329 /* create the function header */
2330 emitcode(";","-----------------------------------------");
2331 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2332 emitcode(";","-----------------------------------------");
2334 emitcode("","%s:",sym->rname);
2335 fetype = getSpec(operandType(IC_LEFT(ic)));
2337 /* if critical function then turn interrupts off */
2338 if (SPEC_CRTCL(fetype))
2339 emitcode("clr","ea");
2341 /* here we need to generate the equates for the
2342 register bank if required */
2343 if (SPEC_BANK(fetype) != rbank) {
2346 rbank = SPEC_BANK(fetype);
2347 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2348 if (strcmp(regs390[i].base,"0") == 0)
2349 emitcode("","%s = 0x%02x",
2351 8*rbank+regs390[i].offset);
2353 emitcode ("","%s = %s + 0x%02x",
2356 8*rbank+regs390[i].offset);
2360 /* if this is an interrupt service routine then
2361 save acc, b, dpl, dph */
2362 if (IS_ISR(sym->etype)) {
2364 if (!inExcludeList("acc"))
2365 emitcode ("push","acc");
2366 if (!inExcludeList("b"))
2367 emitcode ("push","b");
2368 if (!inExcludeList("dpl"))
2369 emitcode ("push","dpl");
2370 if (!inExcludeList("dph"))
2371 emitcode ("push","dph");
2372 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2374 emitcode ("push", "dpx");
2375 /* Make sure we're using standard DPTR */
2376 emitcode ("push", "dps");
2377 emitcode ("mov", "dps, #0x00");
2378 if (options.stack10bit)
2380 /* This ISR could conceivably use DPTR2. Better save it. */
2381 emitcode ("push", "dpl1");
2382 emitcode ("push", "dph1");
2383 emitcode ("push", "dpx1");
2384 emitcode ("push", "ap");
2387 /* if this isr has no bank i.e. is going to
2388 run with bank 0 , then we need to save more
2390 if (!SPEC_BANK(sym->etype)) {
2392 /* if this function does not call any other
2393 function then we can be economical and
2394 save only those registers that are used */
2395 if (! sym->hasFcall) {
2398 /* if any registers used */
2399 if (sym->regsUsed) {
2400 /* save the registers used */
2401 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2402 if (bitVectBitValue(sym->regsUsed,i) ||
2403 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2404 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2409 /* this function has a function call cannot
2410 determines register usage so we will have the
2412 saverbank(0,ic,FALSE);
2416 /* if callee-save to be used for this function
2417 then save the registers being used in this function */
2418 if (sym->calleeSave) {
2421 /* if any registers used */
2422 if (sym->regsUsed) {
2423 /* save the registers used */
2424 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2425 if (bitVectBitValue(sym->regsUsed,i) ||
2426 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2427 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2435 /* set the register bank to the desired value */
2436 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2437 emitcode("push","psw");
2438 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2441 if (IS_RENT(sym->etype) || options.stackAuto) {
2443 if (options.useXstack) {
2444 emitcode("mov","r0,%s",spname);
2445 emitcode("mov","a,_bp");
2446 emitcode("movx","@r0,a");
2447 emitcode("inc","%s",spname);
2451 /* set up the stack */
2452 emitcode ("push","_bp"); /* save the callers stack */
2454 emitcode ("mov","_bp,%s",spname);
2457 /* adjust the stack for the function */
2462 werror(W_STACK_OVERFLOW,sym->name);
2464 if (i > 3 && sym->recvSize < 4) {
2466 emitcode ("mov","a,sp");
2467 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2468 emitcode ("mov","sp,a");
2473 emitcode("inc","sp");
2478 emitcode ("mov","a,_spx");
2479 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2480 emitcode ("mov","_spx,a");
2485 /*-----------------------------------------------------------------*/
2486 /* genEndFunction - generates epilogue for functions */
2487 /*-----------------------------------------------------------------*/
2488 static void genEndFunction (iCode *ic)
2490 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2492 D(emitcode(";", "genEndFunction "););
2494 if (IS_RENT(sym->etype) || options.stackAuto)
2496 emitcode ("mov","%s,_bp",spname);
2499 /* if use external stack but some variables were
2500 added to the local stack then decrement the
2502 if (options.useXstack && sym->stack) {
2503 emitcode("mov","a,sp");
2504 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2505 emitcode("mov","sp,a");
2509 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2510 if (options.useXstack) {
2511 emitcode("mov","r0,%s",spname);
2512 emitcode("movx","a,@r0");
2513 emitcode("mov","_bp,a");
2514 emitcode("dec","%s",spname);
2518 emitcode ("pop","_bp");
2522 /* restore the register bank */
2523 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2524 emitcode ("pop","psw");
2526 if (IS_ISR(sym->etype)) {
2528 /* now we need to restore the registers */
2529 /* if this isr has no bank i.e. is going to
2530 run with bank 0 , then we need to save more
2532 if (!SPEC_BANK(sym->etype)) {
2534 /* if this function does not call any other
2535 function then we can be economical and
2536 save only those registers that are used */
2537 if (! sym->hasFcall) {
2540 /* if any registers used */
2541 if (sym->regsUsed) {
2542 /* save the registers used */
2543 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2544 if (bitVectBitValue(sym->regsUsed,i) ||
2545 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2546 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2551 /* this function has a function call cannot
2552 determines register usage so we will have the
2554 unsaverbank(0,ic,FALSE);
2558 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2560 if (options.stack10bit)
2562 emitcode ("pop", "ap");
2563 emitcode ("pop", "dpx1");
2564 emitcode ("pop", "dph1");
2565 emitcode ("pop", "dpl1");
2567 emitcode ("pop", "dps");
2568 emitcode ("pop", "dpx");
2570 if (!inExcludeList("dph"))
2571 emitcode ("pop","dph");
2572 if (!inExcludeList("dpl"))
2573 emitcode ("pop","dpl");
2574 if (!inExcludeList("b"))
2575 emitcode ("pop","b");
2576 if (!inExcludeList("acc"))
2577 emitcode ("pop","acc");
2579 if (SPEC_CRTCL(sym->etype))
2580 emitcode("setb","ea");
2582 /* if debug then send end of function */
2583 /* if (options.debug && currFunc) { */
2586 emitcode("","C$%s$%d$%d$%d ==.",
2587 ic->filename,currFunc->lastLine,
2588 ic->level,ic->block);
2589 if (IS_STATIC(currFunc->etype))
2590 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2592 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2596 emitcode ("reti","");
2599 if (SPEC_CRTCL(sym->etype))
2600 emitcode("setb","ea");
2602 if (sym->calleeSave) {
2605 /* if any registers used */
2606 if (sym->regsUsed) {
2607 /* save the registers used */
2608 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2609 if (bitVectBitValue(sym->regsUsed,i) ||
2610 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2611 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2617 /* if debug then send end of function */
2620 emitcode("","C$%s$%d$%d$%d ==.",
2621 ic->filename,currFunc->lastLine,
2622 ic->level,ic->block);
2623 if (IS_STATIC(currFunc->etype))
2624 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2626 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2630 emitcode ("ret","");
2635 /*-----------------------------------------------------------------*/
2636 /* genRet - generate code for return statement */
2637 /*-----------------------------------------------------------------*/
2638 static void genRet (iCode *ic)
2640 int size,offset = 0 , pushed = 0;
2642 D(emitcode(";", "genRet "););
2644 /* if we have no return value then
2645 just generate the "ret" */
2649 /* we have something to return then
2650 move the return value into place */
2651 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2652 size = AOP_SIZE(IC_LEFT(ic));
2654 _startLazyDPSEvaluation();
2657 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2658 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2660 emitcode("push","%s",l);
2663 l = aopGet(AOP(IC_LEFT(ic)),offset,
2665 if (strcmp(fReturn[offset],l))
2666 emitcode("mov","%s,%s",fReturn[offset++],l);
2669 _endLazyDPSEvaluation();
2674 if (strcmp(fReturn[pushed],"a"))
2675 emitcode("pop",fReturn[pushed]);
2677 emitcode("pop","acc");
2680 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2683 /* generate a jump to the return label
2684 if the next is not the return statement */
2685 if (!(ic->next && ic->next->op == LABEL &&
2686 IC_LABEL(ic->next) == returnLabel))
2688 emitcode("ljmp","%05d$",(returnLabel->key+100));
2692 /*-----------------------------------------------------------------*/
2693 /* genLabel - generates a label */
2694 /*-----------------------------------------------------------------*/
2695 static void genLabel (iCode *ic)
2697 /* special case never generate */
2698 if (IC_LABEL(ic) == entryLabel)
2701 D(emitcode(";", "genLabel "););
2703 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2706 /*-----------------------------------------------------------------*/
2707 /* genGoto - generates a ljmp */
2708 /*-----------------------------------------------------------------*/
2709 static void genGoto (iCode *ic)
2711 D(emitcode(";", "genGoto "););
2712 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2715 /*-----------------------------------------------------------------*/
2716 /* findLabelBackwards: walks back through the iCode chain looking */
2717 /* for the given label. Returns number of iCode instructions */
2718 /* between that label and given ic. */
2719 /* Returns zero if label not found. */
2720 /*-----------------------------------------------------------------*/
2721 static int findLabelBackwards(iCode *ic, int key)
2730 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2732 /* printf("findLabelBackwards = %d\n", count); */
2740 /*-----------------------------------------------------------------*/
2741 /* genPlusIncr :- does addition with increment if possible */
2742 /*-----------------------------------------------------------------*/
2743 static bool genPlusIncr (iCode *ic)
2745 unsigned int icount ;
2746 unsigned int size = getDataSize(IC_RESULT(ic));
2748 /* will try to generate an increment */
2749 /* if the right side is not a literal
2751 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2754 /* if the literal value of the right hand side
2755 is greater than 4 then it is not worth it */
2756 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2759 /* if increment 16 bits in register */
2761 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2762 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2763 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2770 /* If the next instruction is a goto and the goto target
2771 * is <= 5 instructions previous to this, we can generate
2772 * jumps straight to that target.
2774 if (ic->next && ic->next->op == GOTO
2775 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2776 && labelRange <= 5 )
2778 emitcode(";", "tail increment optimized (range %d)", labelRange);
2779 tlbl = IC_LABEL(ic->next);
2784 tlbl = newiTempLabel(NULL);
2787 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2788 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2789 IS_AOP_PREG(IC_RESULT(ic)))
2790 emitcode("cjne","%s,#0x00,%05d$"
2791 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2794 emitcode("clr","a");
2795 emitcode("cjne","a,%s,%05d$"
2796 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2800 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2803 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2804 IS_AOP_PREG(IC_RESULT(ic)))
2805 emitcode("cjne","%s,#0x00,%05d$"
2806 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2809 emitcode("cjne","a,%s,%05d$"
2810 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2813 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2817 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2818 IS_AOP_PREG(IC_RESULT(ic)))
2819 emitcode("cjne","%s,#0x00,%05d$"
2820 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2823 emitcode("cjne","a,%s,%05d$"
2824 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2827 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2832 emitcode("","%05d$:",tlbl->key+100);
2837 /* if the sizes are greater than 1 then we cannot */
2838 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2839 AOP_SIZE(IC_LEFT(ic)) > 1 )
2842 /* we can if the aops of the left & result match or
2843 if they are in registers and the registers are the
2846 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2847 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2848 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2851 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2852 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2853 aopPut(AOP(IC_RESULT(ic)),"a",0);
2856 _startLazyDPSEvaluation();
2859 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2861 _endLazyDPSEvaluation();
2870 /*-----------------------------------------------------------------*/
2871 /* outBitAcc - output a bit in acc */
2872 /*-----------------------------------------------------------------*/
2873 static void outBitAcc(operand *result)
2875 symbol *tlbl = newiTempLabel(NULL);
2876 /* if the result is a bit */
2877 if (AOP_TYPE(result) == AOP_CRY){
2878 aopPut(AOP(result),"a",0);
2881 emitcode("jz","%05d$",tlbl->key+100);
2882 emitcode("mov","a,%s",one);
2883 emitcode("","%05d$:",tlbl->key+100);
2888 /*-----------------------------------------------------------------*/
2889 /* genPlusBits - generates code for addition of two bits */
2890 /*-----------------------------------------------------------------*/
2891 static void genPlusBits (iCode *ic)
2893 D(emitcode(";", "genPlusBits "););
2894 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2895 symbol *lbl = newiTempLabel(NULL);
2896 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2897 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2898 emitcode("cpl","c");
2899 emitcode("","%05d$:",(lbl->key+100));
2900 outBitC(IC_RESULT(ic));
2903 emitcode("clr","a");
2904 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2905 emitcode("rlc","a");
2906 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2907 emitcode("addc","a,#0x00");
2908 outAcc(IC_RESULT(ic));
2912 static void adjustArithmeticResult(iCode *ic)
2914 if (opIsGptr(IC_RESULT(ic)) &&
2915 opIsGptr(IC_LEFT(ic)) &&
2916 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2918 aopPut(AOP(IC_RESULT(ic)),
2919 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2923 if (opIsGptr(IC_RESULT(ic)) &&
2924 opIsGptr(IC_RIGHT(ic)) &&
2925 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2927 aopPut(AOP(IC_RESULT(ic)),
2928 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2932 if (opIsGptr(IC_RESULT(ic)) &&
2933 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2934 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2935 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2936 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2938 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2939 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2944 #define AOP_OP_3(ic) \
2945 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2946 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2947 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2948 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2949 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2951 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2953 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2956 #define AOP_OP_3(ic) \
2957 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2958 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2959 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
2960 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2961 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2962 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2964 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2966 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2969 #define AOP_OP_3_NOFATAL(ic, rc) \
2970 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2971 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2972 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
2973 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2974 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2975 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2978 freeAsmop(IC_RESULT(ic), NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); \
2985 #define AOP_OP_2(ic) \
2986 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2987 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
2992 #define AOP_SET_LOCALS(ic) \
2993 left = IC_LEFT(ic); \
2994 right = IC_RIGHT(ic); \
2995 result = IC_RESULT(ic);
2997 /*-----------------------------------------------------------------*/
2998 /* genPlus - generates code for addition */
2999 /*-----------------------------------------------------------------*/
3000 static void genPlus (iCode *ic)
3002 int size, offset = 0;
3003 bool pushResult = FALSE;
3006 D(emitcode(";", "genPlus "););
3008 /* special cases :- */
3011 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
3012 aopOp (IC_LEFT(ic),ic,FALSE,
3013 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3014 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
3015 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
3021 aopOp (IC_RESULT(ic),ic,TRUE,
3022 ((AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)
3023 || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR)));
3026 AOP_OP_3_NOFATAL(ic, pushResult);
3031 /* if literal, literal on the right or
3032 if left requires ACC or right is already
3034 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)
3035 || ((AOP_NEEDSACC(IC_LEFT(ic))) && !(AOP_NEEDSACC(IC_RIGHT(ic))))
3036 || AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC )
3038 operand *t = IC_RIGHT(ic);
3039 IC_RIGHT(ic) = IC_LEFT(ic);
3041 emitcode(";", "Swapped plus args.");
3044 /* if both left & right are in bit
3046 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3047 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3052 /* if left in bit space & right literal */
3053 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3054 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3055 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3056 /* if result in bit space */
3057 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3058 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
3059 emitcode("cpl","c");
3060 outBitC(IC_RESULT(ic));
3062 size = getDataSize(IC_RESULT(ic));
3063 _startLazyDPSEvaluation();
3065 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3066 emitcode("addc","a,#00");
3067 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3069 _endLazyDPSEvaluation();
3074 /* if I can do an increment instead
3075 of add then GOOD for ME */
3076 if (genPlusIncr (ic) == TRUE)
3078 emitcode(";", "did genPlusIncr");
3083 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3085 _startLazyDPSEvaluation();
3088 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3090 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3092 emitcode("add","a,%s",
3093 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3095 emitcode("addc","a,%s",
3096 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3098 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3100 emitcode("add","a,%s",
3101 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3103 emitcode("addc","a,%s",
3104 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3108 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3112 emitcode("push", "acc");
3116 _endLazyDPSEvaluation();
3120 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3122 size = getDataSize(IC_LEFT(ic));
3123 rSize = getDataSize(IC_RESULT(ic));
3125 /* If the pushed data is bigger than the result,
3126 * simply discard unused bytes. Icky, but works.
3128 * Should we throw a warning here? We're losing data...
3130 while (size > rSize)
3132 D(emitcode(";", "discarding unused result byte."););
3133 emitcode("pop", "acc");
3139 emitcode("clr", "a");
3140 /* Conversly, we haven't pushed enough here.
3141 * just zero-pad, and all is well.
3143 while (size < rSize)
3145 emitcode("push", "acc");
3151 _startLazyDPSEvaluation();
3154 emitcode("pop", "acc");
3155 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3157 _endLazyDPSEvaluation();
3160 adjustArithmeticResult(ic);
3163 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3164 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3165 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3168 /*-----------------------------------------------------------------*/
3169 /* genMinusDec :- does subtraction with deccrement if possible */
3170 /*-----------------------------------------------------------------*/
3171 static bool genMinusDec (iCode *ic)
3173 unsigned int icount ;
3174 unsigned int size = getDataSize(IC_RESULT(ic));
3176 /* will try to generate an increment */
3177 /* if the right side is not a literal
3179 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3182 /* if the literal value of the right hand side
3183 is greater than 4 then it is not worth it */
3184 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3187 /* if decrement 16 bits in register */
3188 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3189 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3190 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3197 /* If the next instruction is a goto and the goto target
3198 * is <= 5 instructions previous to this, we can generate
3199 * jumps straight to that target.
3201 if (ic->next && ic->next->op == GOTO
3202 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3203 && labelRange <= 5 )
3205 emitcode(";", "tail decrement optimized (range %d)", labelRange);
3206 tlbl = IC_LABEL(ic->next);
3211 tlbl = newiTempLabel(NULL);
3215 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3216 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3217 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3218 IS_AOP_PREG(IC_RESULT(ic)))
3219 emitcode("cjne","%s,#0xff,%05d$"
3220 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3223 emitcode("mov","a,#0xff");
3224 emitcode("cjne","a,%s,%05d$"
3225 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3228 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3231 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3232 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3233 IS_AOP_PREG(IC_RESULT(ic)))
3234 emitcode("cjne","%s,#0xff,%05d$"
3235 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3238 emitcode("cjne","a,%s,%05d$"
3239 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3242 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3246 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3247 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3248 IS_AOP_PREG(IC_RESULT(ic)))
3249 emitcode("cjne","%s,#0xff,%05d$"
3250 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3253 emitcode("cjne","a,%s,%05d$"
3254 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3257 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3261 emitcode("","%05d$:",tlbl->key+100);
3266 /* if the sizes are greater than 1 then we cannot */
3267 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3268 AOP_SIZE(IC_LEFT(ic)) > 1 )
3271 /* we can if the aops of the left & result match or
3272 if they are in registers and the registers are the
3275 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3276 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3277 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3279 _startLazyDPSEvaluation();
3282 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3284 _endLazyDPSEvaluation();
3292 /*-----------------------------------------------------------------*/
3293 /* addSign - complete with sign */
3294 /*-----------------------------------------------------------------*/
3295 static void addSign(operand *result, int offset, int sign)
3297 int size = (getDataSize(result) - offset);
3300 emitcode("rlc","a");
3301 emitcode("subb","a,acc");
3303 aopPut(AOP(result),"a",offset++);
3306 aopPut(AOP(result),zero,offset++);
3310 /*-----------------------------------------------------------------*/
3311 /* genMinusBits - generates code for subtraction of two bits */
3312 /*-----------------------------------------------------------------*/
3313 static void genMinusBits (iCode *ic)
3315 symbol *lbl = newiTempLabel(NULL);
3317 D(emitcode(";", "genMinusBits "););
3319 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3320 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3321 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3322 emitcode("cpl","c");
3323 emitcode("","%05d$:",(lbl->key+100));
3324 outBitC(IC_RESULT(ic));
3327 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3328 emitcode("subb","a,acc");
3329 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3330 emitcode("inc","a");
3331 emitcode("","%05d$:",(lbl->key+100));
3332 aopPut(AOP(IC_RESULT(ic)),"a",0);
3333 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3337 /*-----------------------------------------------------------------*/
3338 /* genMinus - generates code for subtraction */
3339 /*-----------------------------------------------------------------*/
3340 static void genMinus (iCode *ic)
3342 int size, offset = 0;
3344 unsigned long lit = 0L;
3345 bool pushResult = FALSE;
3347 D(emitcode(";", "genMinus "););
3349 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3350 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3351 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3352 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3358 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3360 /* special cases :- */
3361 /* if both left & right are in bit space */
3362 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3363 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3368 /* if I can do an decrement instead
3369 of subtract then GOOD for ME */
3370 if (genMinusDec (ic) == TRUE)
3375 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3377 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3381 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3386 /* if literal, add a,#-lit, else normal subb */
3387 _startLazyDPSEvaluation();
3389 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3390 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3391 emitcode("subb","a,%s",
3392 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3394 /* first add without previous c */
3396 emitcode("add","a,#0x%02x",
3397 (unsigned int)(lit & 0x0FFL));
3399 emitcode("addc","a,#0x%02x",
3400 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3405 emitcode("push", "acc");
3409 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3413 _endLazyDPSEvaluation();
3417 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3419 size = getDataSize(IC_LEFT(ic));
3420 rSize = getDataSize(IC_RESULT(ic));
3422 /* If the pushed data is bigger than the result,
3423 * simply discard unused bytes. Icky, but works.
3425 * Should we throw a warning here? We're losing data...
3427 while (size > getDataSize(IC_RESULT(ic)))
3429 emitcode(";", "discarding unused result byte.");
3430 emitcode("pop", "acc");
3436 emitcode("clr", "a");
3437 /* Conversly, we haven't pushed enough here.
3438 * just zero-pad, and all is well.
3440 while (size < rSize)
3442 emitcode("push", "acc");
3450 emitcode("pop", "acc");
3451 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3455 adjustArithmeticResult(ic);
3458 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3459 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3460 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3464 /*-----------------------------------------------------------------*/
3465 /* genMultbits :- multiplication of bits */
3466 /*-----------------------------------------------------------------*/
3467 static void genMultbits (operand *left,
3471 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3472 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3477 /*-----------------------------------------------------------------*/
3478 /* genMultOneByte : 8 bit multiplication & division */
3479 /*-----------------------------------------------------------------*/
3480 static void genMultOneByte (operand *left,
3484 sym_link *opetype = operandType(result);
3489 /* (if two literals, the value is computed before) */
3490 /* if one literal, literal on the right */
3491 if (AOP_TYPE(left) == AOP_LIT){
3497 size = AOP_SIZE(result);
3498 /* signed or unsigned */
3499 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3500 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3502 emitcode("mul","ab");
3503 /* if result size = 1, mul signed = mul unsigned */
3504 aopPut(AOP(result),"a",0);
3506 if (SPEC_USIGN(opetype)){
3507 aopPut(AOP(result),"b",1);
3509 /* for filling the MSBs */
3510 emitcode("clr","a");
3513 emitcode("mov","a,b");
3515 /* adjust the MSB if left or right neg */
3517 /* if one literal */
3518 if (AOP_TYPE(right) == AOP_LIT){
3519 /* AND literal negative */
3520 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3521 /* adjust MSB (c==0 after mul) */
3522 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3526 lbl = newiTempLabel(NULL);
3527 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3528 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3529 emitcode("","%05d$:",(lbl->key+100));
3530 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3531 lbl = newiTempLabel(NULL);
3532 emitcode("jc","%05d$",(lbl->key+100));
3533 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3534 emitcode("","%05d$:",(lbl->key+100));
3537 lbl = newiTempLabel(NULL);
3538 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3539 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3540 emitcode("","%05d$:",(lbl->key+100));
3541 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3542 lbl = newiTempLabel(NULL);
3543 emitcode("jc","%05d$",(lbl->key+100));
3544 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3545 emitcode("","%05d$:",(lbl->key+100));
3547 aopPut(AOP(result),"a",1);
3550 emitcode("rlc","a");
3551 emitcode("subb","a,acc");
3558 aopPut(AOP(result),"a",offset++);
3562 /*-----------------------------------------------------------------*/
3563 /* genMult - generates code for multiplication */
3564 /*-----------------------------------------------------------------*/
3565 static void genMult (iCode *ic)
3567 operand *left = IC_LEFT(ic);
3568 operand *right = IC_RIGHT(ic);
3569 operand *result= IC_RESULT(ic);
3571 D(emitcode(";", "genMult "););
3573 /* assign the amsops */
3576 aopOp (left,ic,FALSE, FALSE);
3577 aopOp (right,ic,FALSE, TRUE);
3578 aopOp (result,ic,TRUE, FALSE);
3581 /* special cases first */
3583 if (AOP_TYPE(left) == AOP_CRY &&
3584 AOP_TYPE(right)== AOP_CRY) {
3585 genMultbits(left,right,result);
3589 /* if both are of size == 1 */
3590 if (AOP_SIZE(left) == 1 &&
3591 AOP_SIZE(right) == 1 ) {
3592 genMultOneByte(left,right,result);
3596 /* should have been converted to function call */
3600 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3601 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3602 freeAsmop(result,NULL,ic,TRUE);
3605 /*-----------------------------------------------------------------*/
3606 /* genDivbits :- division of bits */
3607 /*-----------------------------------------------------------------*/
3608 static void genDivbits (operand *left,
3615 /* the result must be bit */
3616 LOAD_AB_FOR_DIV(left, right, l);
3617 emitcode("div","ab");
3618 emitcode("rrc","a");
3619 aopPut(AOP(result),"c",0);
3622 /*-----------------------------------------------------------------*/
3623 /* genDivOneByte : 8 bit division */
3624 /*-----------------------------------------------------------------*/
3625 static void genDivOneByte (operand *left,
3629 sym_link *opetype = operandType(result);
3634 size = AOP_SIZE(result) - 1;
3636 /* signed or unsigned */
3637 if (SPEC_USIGN(opetype)) {
3638 /* unsigned is easy */
3639 LOAD_AB_FOR_DIV(left, right, l);
3640 emitcode("div","ab");
3641 aopPut(AOP(result),"a",0);
3643 aopPut(AOP(result),zero,offset++);
3647 /* signed is a little bit more difficult */
3649 /* save the signs of the operands */
3650 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3652 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3653 emitcode("push","acc"); /* save it on the stack */
3655 /* now sign adjust for both left & right */
3656 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3658 lbl = newiTempLabel(NULL);
3659 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3660 emitcode("cpl","a");
3661 emitcode("inc","a");
3662 emitcode("","%05d$:",(lbl->key+100));
3663 emitcode("mov","b,a");
3665 /* sign adjust left side */
3666 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3669 lbl = newiTempLabel(NULL);
3670 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3671 emitcode("cpl","a");
3672 emitcode("inc","a");
3673 emitcode("","%05d$:",(lbl->key+100));
3675 /* now the division */
3676 emitcode("nop", "; workaround for DS80C390 div bug.");
3677 emitcode("div","ab");
3678 /* we are interested in the lower order
3680 emitcode("mov","b,a");
3681 lbl = newiTempLabel(NULL);
3682 emitcode("pop","acc");
3683 /* if there was an over flow we don't
3684 adjust the sign of the result */
3685 emitcode("jb","ov,%05d$",(lbl->key+100));
3686 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3688 emitcode("clr","a");
3689 emitcode("subb","a,b");
3690 emitcode("mov","b,a");
3691 emitcode("","%05d$:",(lbl->key+100));
3693 /* now we are done */
3694 aopPut(AOP(result),"b",0);
3696 emitcode("mov","c,b.7");
3697 emitcode("subb","a,acc");
3700 aopPut(AOP(result),"a",offset++);
3704 /*-----------------------------------------------------------------*/
3705 /* genDiv - generates code for division */
3706 /*-----------------------------------------------------------------*/
3707 static void genDiv (iCode *ic)
3709 operand *left = IC_LEFT(ic);
3710 operand *right = IC_RIGHT(ic);
3711 operand *result= IC_RESULT(ic);
3713 D(emitcode(";", "genDiv "););
3715 /* assign the amsops */
3718 aopOp (left,ic,FALSE, FALSE);
3719 aopOp (right,ic,FALSE, TRUE);
3720 aopOp (result,ic,TRUE, FALSE);
3723 /* special cases first */
3725 if (AOP_TYPE(left) == AOP_CRY &&
3726 AOP_TYPE(right)== AOP_CRY) {
3727 genDivbits(left,right,result);
3731 /* if both are of size == 1 */
3732 if (AOP_SIZE(left) == 1 &&
3733 AOP_SIZE(right) == 1 ) {
3734 genDivOneByte(left,right,result);
3738 /* should have been converted to function call */
3741 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3742 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3743 freeAsmop(result,NULL,ic,TRUE);
3746 /*-----------------------------------------------------------------*/
3747 /* genModbits :- modulus of bits */
3748 /*-----------------------------------------------------------------*/
3749 static void genModbits (operand *left,
3756 /* the result must be bit */
3757 LOAD_AB_FOR_DIV(left, right, l);
3758 emitcode("div","ab");
3759 emitcode("mov","a,b");
3760 emitcode("rrc","a");
3761 aopPut(AOP(result),"c",0);
3764 /*-----------------------------------------------------------------*/
3765 /* genModOneByte : 8 bit modulus */
3766 /*-----------------------------------------------------------------*/
3767 static void genModOneByte (operand *left,
3771 sym_link *opetype = operandType(result);
3775 /* signed or unsigned */
3776 if (SPEC_USIGN(opetype)) {
3777 /* unsigned is easy */
3778 LOAD_AB_FOR_DIV(left, right, l);
3779 emitcode("div","ab");
3780 aopPut(AOP(result),"b",0);
3784 /* signed is a little bit more difficult */
3786 /* save the signs of the operands */
3787 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3790 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3791 emitcode("push","acc"); /* save it on the stack */
3793 /* now sign adjust for both left & right */
3794 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3797 lbl = newiTempLabel(NULL);
3798 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3799 emitcode("cpl","a");
3800 emitcode("inc","a");
3801 emitcode("","%05d$:",(lbl->key+100));
3802 emitcode("mov","b,a");
3804 /* sign adjust left side */
3805 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3808 lbl = newiTempLabel(NULL);
3809 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3810 emitcode("cpl","a");
3811 emitcode("inc","a");
3812 emitcode("","%05d$:",(lbl->key+100));
3814 /* now the multiplication */
3815 emitcode("nop", "; workaround for DS80C390 div bug.");
3816 emitcode("div","ab");
3817 /* we are interested in the lower order
3819 lbl = newiTempLabel(NULL);
3820 emitcode("pop","acc");
3821 /* if there was an over flow we don't
3822 adjust the sign of the result */
3823 emitcode("jb","ov,%05d$",(lbl->key+100));
3824 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3826 emitcode("clr","a");
3827 emitcode("subb","a,b");
3828 emitcode("mov","b,a");
3829 emitcode("","%05d$:",(lbl->key+100));
3831 /* now we are done */
3832 aopPut(AOP(result),"b",0);
3836 /*-----------------------------------------------------------------*/
3837 /* genMod - generates code for division */
3838 /*-----------------------------------------------------------------*/
3839 static void genMod (iCode *ic)
3841 operand *left = IC_LEFT(ic);
3842 operand *right = IC_RIGHT(ic);
3843 operand *result= IC_RESULT(ic);
3845 D(emitcode(";", "genMod "););
3847 /* assign the amsops */
3850 aopOp (left,ic,FALSE, FALSE);
3851 aopOp (right,ic,FALSE, TRUE);
3852 aopOp (result,ic,TRUE, FALSE);
3855 /* special cases first */
3857 if (AOP_TYPE(left) == AOP_CRY &&
3858 AOP_TYPE(right)== AOP_CRY) {
3859 genModbits(left,right,result);
3863 /* if both are of size == 1 */
3864 if (AOP_SIZE(left) == 1 &&
3865 AOP_SIZE(right) == 1 ) {
3866 genModOneByte(left,right,result);
3870 /* should have been converted to function call */
3874 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3875 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3876 freeAsmop(result,NULL,ic,TRUE);
3879 /*-----------------------------------------------------------------*/
3880 /* genIfxJump :- will create a jump depending on the ifx */
3881 /*-----------------------------------------------------------------*/
3882 static void genIfxJump (iCode *ic, char *jval)
3885 symbol *tlbl = newiTempLabel(NULL);
3888 D(emitcode(";", "genIfxJump "););
3890 /* if true label then we jump if condition
3892 if ( IC_TRUE(ic) ) {
3894 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3895 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3898 /* false label is present */
3899 jlbl = IC_FALSE(ic) ;
3900 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3901 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3903 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3904 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3906 emitcode(inst,"%05d$",tlbl->key+100);
3907 emitcode("ljmp","%05d$",jlbl->key+100);
3908 emitcode("","%05d$:",tlbl->key+100);
3910 /* mark the icode as generated */
3914 /*-----------------------------------------------------------------*/
3915 /* genCmp :- greater or less than comparison */
3916 /*-----------------------------------------------------------------*/
3917 static void genCmp (operand *left,operand *right,
3918 iCode *ic, iCode *ifx, int sign)
3920 int size, offset = 0 ;
3921 unsigned long lit = 0L;
3924 D(emitcode(";", "genCmp"););
3926 result = IC_RESULT(ic);
3928 /* if left & right are bit variables */
3929 if (AOP_TYPE(left) == AOP_CRY &&
3930 AOP_TYPE(right) == AOP_CRY ) {
3931 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3932 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3934 /* subtract right from left if at the
3935 end the carry flag is set then we know that
3936 left is greater than right */
3937 size = max(AOP_SIZE(left),AOP_SIZE(right));
3939 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3940 if((size == 1) && !sign &&
3941 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3942 symbol *lbl = newiTempLabel(NULL);
3943 emitcode("cjne","%s,%s,%05d$",
3944 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3945 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3947 emitcode("","%05d$:",lbl->key+100);
3949 if (AOP_TYPE(right) == AOP_LIT)
3951 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3952 /* optimize if(x < 0) or if(x >= 0) */
3961 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3963 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3964 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3966 aopOp(result,ic,FALSE, FALSE);
3968 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx)
3970 freeAsmop(result,NULL,ic,TRUE);
3971 genIfxJump (ifx,"acc.7");
3976 emitcode("rlc","a");
3978 goto release_freedLR;
3986 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3987 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3988 emitcode(";", "genCmp #2");
3989 if (sign && (size == 0))
3991 emitcode(";", "genCmp #3");
3992 emitcode("xrl","a,#0x80");
3993 if (AOP_TYPE(right) == AOP_LIT)
3995 unsigned long lit = (unsigned long)
3996 floatFromVal(AOP(right)->aopu.aop_lit);
3997 emitcode(";", "genCmp #3.1");
3998 emitcode("subb","a,#0x%02x",
3999 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
4003 emitcode(";", "genCmp #3.2");
4004 if (AOP_NEEDSACC(right))
4006 emitcode("push", "acc");
4008 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
4009 FALSE,FALSE,FALSE));
4010 emitcode("xrl","b,#0x80");
4011 if (AOP_NEEDSACC(right))
4013 emitcode("pop", "acc");
4015 emitcode("subb","a,b");
4022 emitcode(";", "genCmp #4");
4023 if (AOP_NEEDSACC(right))
4026 emitcode(";", "genCmp #4.1");
4027 emitcode("xch", "a, b");
4028 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
4029 emitcode("xch", "a, b");
4034 emitcode(";", "genCmp #4.2");
4035 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
4038 emitcode("subb","a,%s",s);
4045 /* Don't need the left & right operands any more; do need the result. */
4046 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4047 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4049 aopOp(result,ic,FALSE, FALSE);
4053 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result))
4059 /* if the result is used in the next
4060 ifx conditional branch then generate
4061 code a little differently */
4064 genIfxJump (ifx,"c");
4070 /* leave the result in acc */
4072 freeAsmop(result,NULL,ic,TRUE);
4075 /*-----------------------------------------------------------------*/
4076 /* genCmpGt :- greater than comparison */
4077 /*-----------------------------------------------------------------*/
4078 static void genCmpGt (iCode *ic, iCode *ifx)
4080 operand *left, *right;
4081 sym_link *letype , *retype;
4084 D(emitcode(";", "genCmpGt "););
4087 right= IC_RIGHT(ic);
4089 letype = getSpec(operandType(left));
4090 retype =getSpec(operandType(right));
4091 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4093 /* assign the left & right amsops */
4096 genCmp(right, left, ic, ifx, sign);
4099 /*-----------------------------------------------------------------*/
4100 /* genCmpLt - less than comparisons */
4101 /*-----------------------------------------------------------------*/
4102 static void genCmpLt (iCode *ic, iCode *ifx)
4104 operand *left, *right;
4105 sym_link *letype , *retype;
4108 D(emitcode(";", "genCmpLt "););
4111 right= IC_RIGHT(ic);
4113 letype = getSpec(operandType(left));
4114 retype =getSpec(operandType(right));
4115 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4117 /* assign the left & right amsops */
4120 genCmp(left, right, ic, ifx, sign);
4123 /*-----------------------------------------------------------------*/
4124 /* gencjneshort - compare and jump if not equal */
4125 /*-----------------------------------------------------------------*/
4126 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4128 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4130 unsigned long lit = 0L;
4132 D(emitcode(";", "gencjneshort"););
4134 /* if the left side is a literal or
4135 if the right is in a pointer register and left
4137 if ((AOP_TYPE(left) == AOP_LIT) ||
4138 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4144 if(AOP_TYPE(right) == AOP_LIT)
4145 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4147 if (opIsGptr(left) || opIsGptr(right))
4149 /* We are comparing a generic pointer to something.
4150 * Exclude the generic type byte from the comparison.
4153 D(emitcode(";", "cjneshort: generic ptr special case.");)
4157 /* if the right side is a literal then anything goes */
4158 if (AOP_TYPE(right) == AOP_LIT &&
4159 AOP_TYPE(left) != AOP_DIR ) {
4161 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4163 emitcode("cjne","a,%s,%05d$",
4164 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4170 /* if the right side is in a register or in direct space or
4171 if the left is a pointer register & right is not */
4172 else if (AOP_TYPE(right) == AOP_REG ||
4173 AOP_TYPE(right) == AOP_DIR ||
4174 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4175 (IS_AOP_PREG(left) && !IS_AOP_PREG(right)))
4179 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4180 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4181 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4182 emitcode("jnz","%05d$",lbl->key+100);
4184 emitcode("cjne","a,%s,%05d$",
4185 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4190 /* right is a pointer reg need both a & b */
4192 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4194 emitcode("mov","b,%s",l);
4195 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4196 emitcode("cjne","a,b,%05d$",lbl->key+100);
4202 /*-----------------------------------------------------------------*/
4203 /* gencjne - compare and jump if not equal */
4204 /*-----------------------------------------------------------------*/
4205 static void gencjne(operand *left, operand *right, symbol *lbl)
4207 symbol *tlbl = newiTempLabel(NULL);
4209 D(emitcode(";", "gencjne"););
4211 gencjneshort(left, right, lbl);
4213 emitcode("mov","a,%s",one);
4214 emitcode("sjmp","%05d$",tlbl->key+100);
4215 emitcode("","%05d$:",lbl->key+100);
4216 emitcode("clr","a");
4217 emitcode("","%05d$:",tlbl->key+100);
4220 /*-----------------------------------------------------------------*/
4221 /* genCmpEq - generates code for equal to */
4222 /*-----------------------------------------------------------------*/
4223 static void genCmpEq (iCode *ic, iCode *ifx)
4225 operand *left, *right, *result;
4227 D(emitcode(";", "genCmpEq "););
4232 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4233 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4234 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4237 /* if literal, literal on the right or
4238 if the right is in a pointer register and left
4240 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4241 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4242 operand *t = IC_RIGHT(ic);
4243 IC_RIGHT(ic) = IC_LEFT(ic);
4247 if(ifx && !AOP_SIZE(result)){
4249 /* if they are both bit variables */
4250 if (AOP_TYPE(left) == AOP_CRY &&
4251 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4252 if(AOP_TYPE(right) == AOP_LIT){
4253 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4255 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4256 emitcode("cpl","c");
4257 } else if(lit == 1L) {
4258 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4260 emitcode("clr","c");
4262 /* AOP_TYPE(right) == AOP_CRY */
4264 symbol *lbl = newiTempLabel(NULL);
4265 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4266 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4267 emitcode("cpl","c");
4268 emitcode("","%05d$:",(lbl->key+100));
4270 /* if true label then we jump if condition
4272 tlbl = newiTempLabel(NULL);
4273 if ( IC_TRUE(ifx) ) {
4274 emitcode("jnc","%05d$",tlbl->key+100);
4275 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4277 emitcode("jc","%05d$",tlbl->key+100);
4278 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4280 emitcode("","%05d$:",tlbl->key+100);
4282 tlbl = newiTempLabel(NULL);
4283 gencjneshort(left, right, tlbl);
4284 if ( IC_TRUE(ifx) ) {
4285 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4286 emitcode("","%05d$:",tlbl->key+100);
4288 symbol *lbl = newiTempLabel(NULL);
4289 emitcode("sjmp","%05d$",lbl->key+100);
4290 emitcode("","%05d$:",tlbl->key+100);
4291 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4292 emitcode("","%05d$:",lbl->key+100);
4295 /* mark the icode as generated */
4300 /* if they are both bit variables */
4301 if (AOP_TYPE(left) == AOP_CRY &&
4302 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4303 if(AOP_TYPE(right) == AOP_LIT){
4304 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4306 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4307 emitcode("cpl","c");
4308 } else if(lit == 1L) {
4309 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4311 emitcode("clr","c");
4313 /* AOP_TYPE(right) == AOP_CRY */
4315 symbol *lbl = newiTempLabel(NULL);
4316 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4317 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4318 emitcode("cpl","c");
4319 emitcode("","%05d$:",(lbl->key+100));
4322 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4327 genIfxJump (ifx,"c");
4330 /* if the result is used in an arithmetic operation
4331 then put the result in place */
4334 gencjne(left,right,newiTempLabel(NULL));
4335 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4336 aopPut(AOP(result),"a",0);
4340 genIfxJump (ifx,"a");
4343 /* if the result is used in an arithmetic operation
4344 then put the result in place */
4345 if (AOP_TYPE(result) != AOP_CRY)
4347 /* leave the result in acc */
4351 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4352 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4353 freeAsmop(result,NULL,ic,TRUE);
4356 /*-----------------------------------------------------------------*/
4357 /* ifxForOp - returns the icode containing the ifx for operand */
4358 /*-----------------------------------------------------------------*/
4359 static iCode *ifxForOp ( operand *op, iCode *ic )
4361 /* if true symbol then needs to be assigned */
4362 if (IS_TRUE_SYMOP(op))
4365 /* if this has register type condition and
4366 the next instruction is ifx with the same operand
4367 and live to of the operand is upto the ifx only then */
4369 ic->next->op == IFX &&
4370 IC_COND(ic->next)->key == op->key &&
4371 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4376 /*-----------------------------------------------------------------*/
4377 /* genAndOp - for && operation */
4378 /*-----------------------------------------------------------------*/
4379 static void genAndOp (iCode *ic)
4381 operand *left,*right, *result;
4384 D(emitcode(";", "genAndOp "););
4386 /* note here that && operations that are in an
4387 if statement are taken away by backPatchLabels
4388 only those used in arthmetic operations remain */
4392 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4393 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4394 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4397 /* if both are bit variables */
4398 if (AOP_TYPE(left) == AOP_CRY &&
4399 AOP_TYPE(right) == AOP_CRY ) {
4400 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4401 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4404 tlbl = newiTempLabel(NULL);
4406 emitcode("jz","%05d$",tlbl->key+100);
4408 emitcode("","%05d$:",tlbl->key+100);
4412 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4413 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4414 freeAsmop(result,NULL,ic,TRUE);
4418 /*-----------------------------------------------------------------*/
4419 /* genOrOp - for || operation */
4420 /*-----------------------------------------------------------------*/
4421 static void genOrOp (iCode *ic)
4423 operand *left,*right, *result;
4426 D(emitcode(";", "genOrOp "););
4428 /* note here that || operations that are in an
4429 if statement are taken away by backPatchLabels
4430 only those used in arthmetic operations remain */
4434 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4435 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4436 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4439 /* if both are bit variables */
4440 if (AOP_TYPE(left) == AOP_CRY &&
4441 AOP_TYPE(right) == AOP_CRY ) {
4442 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4443 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4446 tlbl = newiTempLabel(NULL);
4448 emitcode("jnz","%05d$",tlbl->key+100);
4450 emitcode("","%05d$:",tlbl->key+100);
4454 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4455 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4456 freeAsmop(result,NULL,ic,TRUE);
4459 /*-----------------------------------------------------------------*/
4460 /* isLiteralBit - test if lit == 2^n */
4461 /*-----------------------------------------------------------------*/
4462 static int isLiteralBit(unsigned long lit)
4464 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4465 0x100L,0x200L,0x400L,0x800L,
4466 0x1000L,0x2000L,0x4000L,0x8000L,
4467 0x10000L,0x20000L,0x40000L,0x80000L,
4468 0x100000L,0x200000L,0x400000L,0x800000L,
4469 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4470 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4473 for(idx = 0; idx < 32; idx++)
4479 /*-----------------------------------------------------------------*/
4480 /* continueIfTrue - */
4481 /*-----------------------------------------------------------------*/
4482 static void continueIfTrue (iCode *ic)
4485 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4489 /*-----------------------------------------------------------------*/
4491 /*-----------------------------------------------------------------*/
4492 static void jumpIfTrue (iCode *ic)
4495 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4499 /*-----------------------------------------------------------------*/
4500 /* jmpTrueOrFalse - */
4501 /*-----------------------------------------------------------------*/
4502 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4504 // ugly but optimized by peephole
4506 symbol *nlbl = newiTempLabel(NULL);
4507 emitcode("sjmp","%05d$",nlbl->key+100);
4508 emitcode("","%05d$:",tlbl->key+100);
4509 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4510 emitcode("","%05d$:",nlbl->key+100);
4513 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4514 emitcode("","%05d$:",tlbl->key+100);
4519 /*-----------------------------------------------------------------*/
4520 /* genAnd - code for and */
4521 /*-----------------------------------------------------------------*/
4522 static void genAnd (iCode *ic, iCode *ifx)
4524 operand *left, *right, *result;
4526 unsigned long lit = 0L;
4530 D(emitcode(";", "genAnd "););
4535 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4536 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4537 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4541 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4543 AOP_TYPE(left), AOP_TYPE(right));
4544 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4546 AOP_SIZE(left), AOP_SIZE(right));
4549 /* if left is a literal & right is not then exchange them */
4550 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4551 AOP_NEEDSACC(left)) {
4552 operand *tmp = right ;
4557 /* if result = right then exchange them */
4558 if(sameRegs(AOP(result),AOP(right))){
4559 operand *tmp = right ;
4564 /* if right is bit then exchange them */
4565 if (AOP_TYPE(right) == AOP_CRY &&
4566 AOP_TYPE(left) != AOP_CRY){
4567 operand *tmp = right ;
4571 if(AOP_TYPE(right) == AOP_LIT)
4572 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4574 size = AOP_SIZE(result);
4577 // result = bit & yy;
4578 if (AOP_TYPE(left) == AOP_CRY){
4579 // c = bit & literal;
4580 if(AOP_TYPE(right) == AOP_LIT){
4582 if(size && sameRegs(AOP(result),AOP(left)))
4585 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4588 if(size && (AOP_TYPE(result) == AOP_CRY)){
4589 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4592 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4596 emitcode("clr","c");
4599 if (AOP_TYPE(right) == AOP_CRY){
4601 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4602 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4605 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4607 emitcode("rrc","a");
4608 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4616 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4617 genIfxJump(ifx, "c");
4621 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4622 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4623 if((AOP_TYPE(right) == AOP_LIT) &&
4624 (AOP_TYPE(result) == AOP_CRY) &&
4625 (AOP_TYPE(left) != AOP_CRY)){
4626 int posbit = isLiteralBit(lit);
4630 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4633 emitcode("mov","c,acc.%d",posbit&0x07);
4637 sprintf(buffer,"acc.%d",posbit&0x07);
4638 genIfxJump(ifx, buffer);
4643 symbol *tlbl = newiTempLabel(NULL);
4644 int sizel = AOP_SIZE(left);
4646 emitcode("setb","c");
4648 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4649 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4651 if((posbit = isLiteralBit(bytelit)) != 0)
4652 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4654 if(bytelit != 0x0FFL)
4655 emitcode("anl","a,%s",
4656 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4657 emitcode("jnz","%05d$",tlbl->key+100);
4662 // bit = left & literal
4664 emitcode("clr","c");
4665 emitcode("","%05d$:",tlbl->key+100);
4667 // if(left & literal)
4670 jmpTrueOrFalse(ifx, tlbl);
4678 /* if left is same as result */
4679 if(sameRegs(AOP(result),AOP(left))){
4680 for(;size--; offset++) {
4681 if(AOP_TYPE(right) == AOP_LIT){
4682 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4686 aopPut(AOP(result),zero,offset);
4688 if (IS_AOP_PREG(result)) {
4689 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4690 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4691 aopPut(AOP(result),"a",offset);
4693 emitcode("anl","%s,%s",
4694 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4695 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4697 if (AOP_TYPE(left) == AOP_ACC)
4698 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4700 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4701 if (IS_AOP_PREG(result)) {
4702 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4703 aopPut(AOP(result),"a",offset);
4706 emitcode("anl","%s,a",
4707 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4712 // left & result in different registers
4713 if(AOP_TYPE(result) == AOP_CRY){
4715 // if(size), result in bit
4716 // if(!size && ifx), conditional oper: if(left & right)
4717 symbol *tlbl = newiTempLabel(NULL);
4718 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4720 emitcode("setb","c");
4722 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4723 emitcode("anl","a,%s",
4724 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4725 emitcode("jnz","%05d$",tlbl->key+100);
4730 emitcode("","%05d$:",tlbl->key+100);
4733 jmpTrueOrFalse(ifx, tlbl);
4735 for(;(size--);offset++) {
4737 // result = left & right
4738 if(AOP_TYPE(right) == AOP_LIT){
4739 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4741 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4744 } else if(bytelit == 0){
4745 aopPut(AOP(result),zero,offset);
4749 // faster than result <- left, anl result,right
4750 // and better if result is SFR
4751 if (AOP_TYPE(left) == AOP_ACC)
4752 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4754 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4755 emitcode("anl","a,%s",
4756 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4758 aopPut(AOP(result),"a",offset);
4764 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4765 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4766 freeAsmop(result,NULL,ic,TRUE);
4769 /*-----------------------------------------------------------------*/
4770 /* genOr - code for or */
4771 /*-----------------------------------------------------------------*/
4772 static void genOr (iCode *ic, iCode *ifx)
4774 operand *left, *right, *result;
4776 unsigned long lit = 0L;
4778 D(emitcode(";", "genOr "););
4783 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4784 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4785 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4789 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4791 AOP_TYPE(left), AOP_TYPE(right));
4792 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4794 AOP_SIZE(left), AOP_SIZE(right));
4797 /* if left is a literal & right is not then exchange them */
4798 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4799 AOP_NEEDSACC(left)) {
4800 operand *tmp = right ;
4805 /* if result = right then exchange them */
4806 if(sameRegs(AOP(result),AOP(right))){
4807 operand *tmp = right ;
4812 /* if right is bit then exchange them */
4813 if (AOP_TYPE(right) == AOP_CRY &&
4814 AOP_TYPE(left) != AOP_CRY){
4815 operand *tmp = right ;
4819 if(AOP_TYPE(right) == AOP_LIT)
4820 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4822 size = AOP_SIZE(result);
4826 if (AOP_TYPE(left) == AOP_CRY){
4827 if(AOP_TYPE(right) == AOP_LIT){
4828 // c = bit & literal;
4830 // lit != 0 => result = 1
4831 if(AOP_TYPE(result) == AOP_CRY){
4833 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4835 continueIfTrue(ifx);
4838 emitcode("setb","c");
4840 // lit == 0 => result = left
4841 if(size && sameRegs(AOP(result),AOP(left)))
4843 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4846 if (AOP_TYPE(right) == AOP_CRY){
4848 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4849 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4853 symbol *tlbl = newiTempLabel(NULL);
4854 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4855 emitcode("setb","c");
4856 emitcode("jb","%s,%05d$",
4857 AOP(left)->aopu.aop_dir,tlbl->key+100);
4859 emitcode("jnz","%05d$",tlbl->key+100);
4860 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4861 jmpTrueOrFalse(ifx, tlbl);
4865 emitcode("","%05d$:",tlbl->key+100);
4874 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4875 genIfxJump(ifx, "c");
4879 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4880 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4881 if((AOP_TYPE(right) == AOP_LIT) &&
4882 (AOP_TYPE(result) == AOP_CRY) &&
4883 (AOP_TYPE(left) != AOP_CRY)){
4887 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4889 continueIfTrue(ifx);
4892 // lit = 0, result = boolean(left)
4894 emitcode("setb","c");
4897 symbol *tlbl = newiTempLabel(NULL);
4898 emitcode("jnz","%05d$",tlbl->key+100);
4900 emitcode("","%05d$:",tlbl->key+100);
4902 genIfxJump (ifx,"a");
4910 /* if left is same as result */
4911 if(sameRegs(AOP(result),AOP(left))){
4912 for(;size--; offset++) {
4913 if(AOP_TYPE(right) == AOP_LIT){
4914 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4917 if (IS_AOP_PREG(left)) {
4918 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4919 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4920 aopPut(AOP(result),"a",offset);
4922 emitcode("orl","%s,%s",
4923 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4924 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4926 if (AOP_TYPE(left) == AOP_ACC)
4927 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4929 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4930 if (IS_AOP_PREG(left)) {
4931 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4932 aopPut(AOP(result),"a",offset);
4934 emitcode("orl","%s,a",
4935 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4940 // left & result in different registers
4941 if(AOP_TYPE(result) == AOP_CRY){
4943 // if(size), result in bit
4944 // if(!size && ifx), conditional oper: if(left | right)
4945 symbol *tlbl = newiTempLabel(NULL);
4946 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4948 emitcode("setb","c");
4950 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4951 emitcode("orl","a,%s",
4952 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4953 emitcode("jnz","%05d$",tlbl->key+100);
4958 emitcode("","%05d$:",tlbl->key+100);
4961 jmpTrueOrFalse(ifx, tlbl);
4962 } else for(;(size--);offset++){
4964 // result = left & right
4965 if(AOP_TYPE(right) == AOP_LIT){
4966 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4968 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4973 // faster than result <- left, anl result,right
4974 // and better if result is SFR
4975 if (AOP_TYPE(left) == AOP_ACC)
4976 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4978 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4979 emitcode("orl","a,%s",
4980 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4982 aopPut(AOP(result),"a",offset);
4987 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4988 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4989 freeAsmop(result,NULL,ic,TRUE);
4992 /*-----------------------------------------------------------------*/
4993 /* genXor - code for xclusive or */
4994 /*-----------------------------------------------------------------*/
4995 static void genXor (iCode *ic, iCode *ifx)
4997 operand *left, *right, *result;
4999 unsigned long lit = 0L;
5001 D(emitcode(";", "genXor "););
5006 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
5007 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
5008 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
5012 emitcode("","; Type res[%d] = l[%d]&r[%d]",
5014 AOP_TYPE(left), AOP_TYPE(right));
5015 emitcode("","; Size res[%d] = l[%d]&r[%d]",
5017 AOP_SIZE(left), AOP_SIZE(right));
5020 /* if left is a literal & right is not ||
5021 if left needs acc & right does not */
5022 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5023 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5024 operand *tmp = right ;
5029 /* if result = right then exchange them */
5030 if(sameRegs(AOP(result),AOP(right))){
5031 operand *tmp = right ;
5036 /* if right is bit then exchange them */
5037 if (AOP_TYPE(right) == AOP_CRY &&
5038 AOP_TYPE(left) != AOP_CRY){
5039 operand *tmp = right ;
5043 if(AOP_TYPE(right) == AOP_LIT)
5044 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5046 size = AOP_SIZE(result);
5050 if (AOP_TYPE(left) == AOP_CRY){
5051 if(AOP_TYPE(right) == AOP_LIT){
5052 // c = bit & literal;
5054 // lit>>1 != 0 => result = 1
5055 if(AOP_TYPE(result) == AOP_CRY){
5057 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5059 continueIfTrue(ifx);
5062 emitcode("setb","c");
5066 // lit == 0, result = left
5067 if(size && sameRegs(AOP(result),AOP(left)))
5069 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5071 // lit == 1, result = not(left)
5072 if(size && sameRegs(AOP(result),AOP(left))){
5073 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5076 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5077 emitcode("cpl","c");
5084 symbol *tlbl = newiTempLabel(NULL);
5085 if (AOP_TYPE(right) == AOP_CRY){
5087 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5090 int sizer = AOP_SIZE(right);
5092 // if val>>1 != 0, result = 1
5093 emitcode("setb","c");
5095 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5097 // test the msb of the lsb
5098 emitcode("anl","a,#0xfe");
5099 emitcode("jnz","%05d$",tlbl->key+100);
5103 emitcode("rrc","a");
5105 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5106 emitcode("cpl","c");
5107 emitcode("","%05d$:",(tlbl->key+100));
5114 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5115 genIfxJump(ifx, "c");
5119 if(sameRegs(AOP(result),AOP(left))){
5120 /* if left is same as result */
5121 for(;size--; offset++) {
5122 if(AOP_TYPE(right) == AOP_LIT){
5123 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5126 if (IS_AOP_PREG(left)) {
5127 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5128 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5129 aopPut(AOP(result),"a",offset);
5131 emitcode("xrl","%s,%s",
5132 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5133 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5135 if (AOP_TYPE(left) == AOP_ACC)
5136 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5138 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5139 if (IS_AOP_PREG(left)) {
5140 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5141 aopPut(AOP(result),"a",offset);
5143 emitcode("xrl","%s,a",
5144 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5149 // left & result in different registers
5150 if(AOP_TYPE(result) == AOP_CRY){
5152 // if(size), result in bit
5153 // if(!size && ifx), conditional oper: if(left ^ right)
5154 symbol *tlbl = newiTempLabel(NULL);
5155 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5157 emitcode("setb","c");
5159 if((AOP_TYPE(right) == AOP_LIT) &&
5160 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5161 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5163 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5164 emitcode("xrl","a,%s",
5165 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5167 emitcode("jnz","%05d$",tlbl->key+100);
5172 emitcode("","%05d$:",tlbl->key+100);
5175 jmpTrueOrFalse(ifx, tlbl);
5176 } else for(;(size--);offset++){
5178 // result = left & right
5179 if(AOP_TYPE(right) == AOP_LIT){
5180 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
5182 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5187 // faster than result <- left, anl result,right
5188 // and better if result is SFR
5189 if (AOP_TYPE(left) == AOP_ACC)
5190 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5192 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5193 emitcode("xrl","a,%s",
5194 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5196 aopPut(AOP(result),"a",offset);
5201 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5202 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5203 freeAsmop(result,NULL,ic,TRUE);
5206 /*-----------------------------------------------------------------*/
5207 /* genInline - write the inline code out */
5208 /*-----------------------------------------------------------------*/
5209 static void genInline (iCode *ic)
5211 char buffer[MAX_INLINEASM];
5215 D(emitcode(";", "genInline "););
5217 _G.inLine += (!options.asmpeep);
5218 strcpy(buffer,IC_INLINE(ic));
5220 /* emit each line as a code */
5239 /* emitcode("",buffer); */
5240 _G.inLine -= (!options.asmpeep);
5243 /*-----------------------------------------------------------------*/
5244 /* genRRC - rotate right with carry */
5245 /*-----------------------------------------------------------------*/
5246 static void genRRC (iCode *ic)
5248 operand *left , *result ;
5249 int size, offset = 0;
5252 D(emitcode(";", "genRRC "););
5254 /* rotate right with carry */
5256 result=IC_RESULT(ic);
5257 aopOp (left,ic,FALSE, FALSE);
5258 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5260 /* move it to the result */
5261 size = AOP_SIZE(result);
5265 _startLazyDPSEvaluation();
5267 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5269 emitcode("rrc","a");
5270 if (AOP_SIZE(result) > 1)
5271 aopPut(AOP(result),"a",offset--);
5273 _endLazyDPSEvaluation();
5275 /* now we need to put the carry into the
5276 highest order byte of the result */
5277 if (AOP_SIZE(result) > 1) {
5278 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5281 emitcode("mov","acc.7,c");
5282 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5283 freeAsmop(left,NULL,ic,TRUE);
5284 freeAsmop(result,NULL,ic,TRUE);
5287 /*-----------------------------------------------------------------*/
5288 /* genRLC - generate code for rotate left with carry */
5289 /*-----------------------------------------------------------------*/
5290 static void genRLC (iCode *ic)
5292 operand *left , *result ;
5293 int size, offset = 0;
5296 D(emitcode(";", "genRLC "););
5298 /* rotate right with carry */
5300 result=IC_RESULT(ic);
5301 aopOp (left,ic,FALSE, FALSE);
5302 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5304 /* move it to the result */
5305 size = AOP_SIZE(result);
5308 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5310 emitcode("add","a,acc");
5311 if (AOP_SIZE(result) > 1)
5313 aopPut(AOP(result),"a",offset++);
5316 _startLazyDPSEvaluation();
5318 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5320 emitcode("rlc","a");
5321 if (AOP_SIZE(result) > 1)
5322 aopPut(AOP(result),"a",offset++);
5324 _endLazyDPSEvaluation();
5326 /* now we need to put the carry into the
5327 highest order byte of the result */
5328 if (AOP_SIZE(result) > 1) {
5329 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5332 emitcode("mov","acc.0,c");
5333 aopPut(AOP(result),"a",0);
5334 freeAsmop(left,NULL,ic,TRUE);
5335 freeAsmop(result,NULL,ic,TRUE);
5338 /*-----------------------------------------------------------------*/
5339 /* genGetHbit - generates code get highest order bit */
5340 /*-----------------------------------------------------------------*/
5341 static void genGetHbit (iCode *ic)
5343 operand *left, *result;
5345 result=IC_RESULT(ic);
5346 aopOp (left,ic,FALSE, FALSE);
5347 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5349 D(emitcode(";", "genGetHbit "););
5351 /* get the highest order byte into a */
5352 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5353 if(AOP_TYPE(result) == AOP_CRY){
5354 emitcode("rlc","a");
5359 emitcode("anl","a,#0x01");
5364 freeAsmop(left,NULL,ic,TRUE);
5365 freeAsmop(result,NULL,ic,TRUE);
5368 /*-----------------------------------------------------------------*/
5369 /* AccRol - rotate left accumulator by known count */
5370 /*-----------------------------------------------------------------*/
5371 static void AccRol (int shCount)
5373 shCount &= 0x0007; // shCount : 0..7
5385 emitcode("swap","a");
5389 emitcode("swap","a");
5392 emitcode("swap","a");
5405 /*-----------------------------------------------------------------*/
5406 /* AccLsh - left shift accumulator by known count */
5407 /*-----------------------------------------------------------------*/
5408 static void AccLsh (int shCount)
5412 emitcode("add","a,acc");
5415 emitcode("add","a,acc");
5416 emitcode("add","a,acc");
5418 /* rotate left accumulator */
5420 /* and kill the lower order bits */
5421 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5426 /*-----------------------------------------------------------------*/
5427 /* AccRsh - right shift accumulator by known count */
5428 /*-----------------------------------------------------------------*/
5429 static void AccRsh (int shCount)
5434 emitcode("rrc","a");
5436 /* rotate right accumulator */
5437 AccRol(8 - shCount);
5438 /* and kill the higher order bits */
5439 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5446 /*-----------------------------------------------------------------*/
5447 /* AccSRsh - signed right shift accumulator by known count */
5448 /*-----------------------------------------------------------------*/
5449 static void AccSRsh (int shCount)
5454 emitcode("mov","c,acc.7");
5455 emitcode("rrc","a");
5456 } else if(shCount == 2){
5457 emitcode("mov","c,acc.7");
5458 emitcode("rrc","a");
5459 emitcode("mov","c,acc.7");
5460 emitcode("rrc","a");
5462 tlbl = newiTempLabel(NULL);
5463 /* rotate right accumulator */
5464 AccRol(8 - shCount);
5465 /* and kill the higher order bits */
5466 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5467 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5468 emitcode("orl","a,#0x%02x",
5469 (unsigned char)~SRMask[shCount]);
5470 emitcode("","%05d$:",tlbl->key+100);
5478 /*-----------------------------------------------------------------*/
5479 /* shiftR1Left2Result - shift right one byte from left to result */
5480 /*-----------------------------------------------------------------*/
5481 static void shiftR1Left2Result (operand *left, int offl,
5482 operand *result, int offr,
5483 int shCount, int sign)
5485 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5486 /* shift right accumulator */
5491 aopPut(AOP(result),"a",offr);
5497 /*-----------------------------------------------------------------*/
5498 /* shiftL1Left2Result - shift left one byte from left to result */
5499 /*-----------------------------------------------------------------*/
5500 static void shiftL1Left2Result (operand *left, int offl,
5501 operand *result, int offr, int shCount)
5504 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5506 /* shift left accumulator */
5508 aopPut(AOP(result),"a",offr);
5514 /*-----------------------------------------------------------------*/
5515 /* movLeft2Result - move byte from left to result */
5516 /*-----------------------------------------------------------------*/
5517 static void movLeft2Result (operand *left, int offl,
5518 operand *result, int offr, int sign)
5521 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5522 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5524 if (*l == '@' && (IS_AOP_PREG(result))) {
5525 emitcode("mov","a,%s",l);
5526 aopPut(AOP(result),"a",offr);
5529 aopPut(AOP(result),l,offr);
5531 /* MSB sign in acc.7 ! */
5532 if(getDataSize(left) == offl+1){
5533 emitcode("mov","a,%s",l);
5534 aopPut(AOP(result),"a",offr);
5544 /*-----------------------------------------------------------------*/
5545 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5546 /*-----------------------------------------------------------------*/
5547 static void AccAXRrl1 (char *x)
5549 emitcode("rrc","a");
5550 emitcode("xch","a,%s", x);
5551 emitcode("rrc","a");
5552 emitcode("xch","a,%s", x);
5558 /*-----------------------------------------------------------------*/
5559 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5560 /*-----------------------------------------------------------------*/
5561 static void AccAXLrl1 (char *x)
5563 emitcode("xch","a,%s",x);
5564 emitcode("rlc","a");
5565 emitcode("xch","a,%s",x);
5566 emitcode("rlc","a");
5572 /*-----------------------------------------------------------------*/
5573 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5574 /*-----------------------------------------------------------------*/
5575 static void AccAXLsh1 (char *x)
5577 emitcode("xch","a,%s",x);
5578 emitcode("add","a,acc");
5579 emitcode("xch","a,%s",x);
5580 emitcode("rlc","a");
5586 /*-----------------------------------------------------------------*/
5587 /* AccAXLsh - left shift a:x by known count (0..7) */
5588 /*-----------------------------------------------------------------*/
5589 static void AccAXLsh (char *x, int shCount)
5603 case 5 : // AAAAABBB:CCCCCDDD
5604 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5605 emitcode("anl","a,#0x%02x",
5606 SLMask[shCount]); // BBB00000:CCCCCDDD
5607 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5608 AccRol(shCount); // DDDCCCCC:BBB00000
5609 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5610 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5611 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5612 emitcode("anl","a,#0x%02x",
5613 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5614 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5615 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5617 case 6 : // AAAAAABB:CCCCCCDD
5618 emitcode("anl","a,#0x%02x",
5619 SRMask[shCount]); // 000000BB:CCCCCCDD
5620 emitcode("mov","c,acc.0"); // c = B
5621 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5622 AccAXRrl1(x); // BCCCCCCD:D000000B
5623 AccAXRrl1(x); // BBCCCCCC:DD000000
5625 case 7 : // a:x <<= 7
5626 emitcode("anl","a,#0x%02x",
5627 SRMask[shCount]); // 0000000B:CCCCCCCD
5628 emitcode("mov","c,acc.0"); // c = B
5629 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5630 AccAXRrl1(x); // BCCCCCCC:D0000000
5640 /*-----------------------------------------------------------------*/
5641 /* AccAXRsh - right shift a:x known count (0..7) */
5642 /*-----------------------------------------------------------------*/
5643 static void AccAXRsh (char *x, int shCount)
5650 AccAXRrl1(x); // 0->a:x
5654 AccAXRrl1(x); // 0->a:x
5656 AccAXRrl1(x); // 0->a:x
5660 case 5 : // AAAAABBB:CCCCCDDD = a:x
5661 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5662 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5663 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5664 emitcode("anl","a,#0x%02x",
5665 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5666 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5667 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5668 emitcode("anl","a,#0x%02x",
5669 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5670 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5671 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5672 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5674 case 6 : // AABBBBBB:CCDDDDDD
5675 emitcode("mov","c,acc.7");
5676 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5677 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5678 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5679 emitcode("anl","a,#0x%02x",
5680 SRMask[shCount]); // 000000AA:BBBBBBCC
5682 case 7 : // ABBBBBBB:CDDDDDDD
5683 emitcode("mov","c,acc.7"); // c = A
5684 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5685 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5686 emitcode("anl","a,#0x%02x",
5687 SRMask[shCount]); // 0000000A:BBBBBBBC
5697 /*-----------------------------------------------------------------*/
5698 /* AccAXRshS - right shift signed a:x known count (0..7) */
5699 /*-----------------------------------------------------------------*/
5700 static void AccAXRshS (char *x, int shCount)
5707 emitcode("mov","c,acc.7");
5708 AccAXRrl1(x); // s->a:x
5711 emitcode("mov","c,acc.7");
5712 AccAXRrl1(x); // s->a:x
5713 emitcode("mov","c,acc.7");
5714 AccAXRrl1(x); // s->a:x
5718 case 5 : // AAAAABBB:CCCCCDDD = a:x
5719 tlbl = newiTempLabel(NULL);
5720 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5721 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5722 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5723 emitcode("anl","a,#0x%02x",
5724 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5725 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5726 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5727 emitcode("anl","a,#0x%02x",
5728 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5729 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5730 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5731 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5732 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5733 emitcode("orl","a,#0x%02x",
5734 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5735 emitcode("","%05d$:",tlbl->key+100);
5736 break; // SSSSAAAA:BBBCCCCC
5737 case 6 : // AABBBBBB:CCDDDDDD
5738 tlbl = newiTempLabel(NULL);
5739 emitcode("mov","c,acc.7");
5740 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5741 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5742 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5743 emitcode("anl","a,#0x%02x",
5744 SRMask[shCount]); // 000000AA:BBBBBBCC
5745 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5746 emitcode("orl","a,#0x%02x",
5747 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5748 emitcode("","%05d$:",tlbl->key+100);
5750 case 7 : // ABBBBBBB:CDDDDDDD
5751 tlbl = newiTempLabel(NULL);
5752 emitcode("mov","c,acc.7"); // c = A
5753 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5754 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5755 emitcode("anl","a,#0x%02x",
5756 SRMask[shCount]); // 0000000A:BBBBBBBC
5757 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5758 emitcode("orl","a,#0x%02x",
5759 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5760 emitcode("","%05d$:",tlbl->key+100);
5770 /*-----------------------------------------------------------------*/
5771 /* shiftL2Left2Result - shift left two bytes from left to result */
5772 /*-----------------------------------------------------------------*/
5773 static void shiftL2Left2Result (operand *left, int offl,
5774 operand *result, int offr, int shCount)
5776 if(sameRegs(AOP(result), AOP(left)) &&
5777 ((offl + MSB16) == offr)){
5778 /* don't crash result[offr] */
5779 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5780 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5782 movLeft2Result(left,offl, result, offr, 0);
5783 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5785 /* ax << shCount (x = lsb(result))*/
5786 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5787 aopPut(AOP(result),"a",offr+MSB16);
5793 /*-----------------------------------------------------------------*/
5794 /* shiftR2Left2Result - shift right two bytes from left to result */
5795 /*-----------------------------------------------------------------*/
5796 static void shiftR2Left2Result (operand *left, int offl,
5797 operand *result, int offr,
5798 int shCount, int sign)
5800 if(sameRegs(AOP(result), AOP(left)) &&
5801 ((offl + MSB16) == offr)){
5802 /* don't crash result[offr] */
5803 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5804 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5806 movLeft2Result(left,offl, result, offr, 0);
5807 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5809 /* a:x >> shCount (x = lsb(result))*/
5811 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5813 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5814 if(getDataSize(result) > 1)
5815 aopPut(AOP(result),"a",offr+MSB16);
5821 /*-----------------------------------------------------------------*/
5822 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5823 /*-----------------------------------------------------------------*/
5824 static void shiftLLeftOrResult (operand *left, int offl,
5825 operand *result, int offr, int shCount)
5827 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5828 /* shift left accumulator */
5830 /* or with result */
5831 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5832 /* back to result */
5833 aopPut(AOP(result),"a",offr);
5839 /*-----------------------------------------------------------------*/
5840 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5841 /*-----------------------------------------------------------------*/
5842 static void shiftRLeftOrResult (operand *left, int offl,
5843 operand *result, int offr, int shCount)
5845 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5846 /* shift right accumulator */
5848 /* or with result */
5849 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5850 /* back to result */
5851 aopPut(AOP(result),"a",offr);
5857 /*-----------------------------------------------------------------*/
5858 /* genlshOne - left shift a one byte quantity by known count */
5859 /*-----------------------------------------------------------------*/
5860 static void genlshOne (operand *result, operand *left, int shCount)
5862 D(emitcode(";", "genlshOne "););
5863 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5869 /*-----------------------------------------------------------------*/
5870 /* genlshTwo - left shift two bytes by known amount != 0 */
5871 /*-----------------------------------------------------------------*/
5872 static void genlshTwo (operand *result,operand *left, int shCount)
5876 D(emitcode(";", "genlshTwo "););
5878 size = getDataSize(result);
5880 /* if shCount >= 8 */
5886 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5888 movLeft2Result(left, LSB, result, MSB16, 0);
5890 aopPut(AOP(result),zero,LSB);
5893 /* 1 <= shCount <= 7 */
5896 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5898 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5905 /*-----------------------------------------------------------------*/
5906 /* shiftLLong - shift left one long from left to result */
5907 /* offl = LSB or MSB16 */
5908 /*-----------------------------------------------------------------*/
5909 static void shiftLLong (operand *left, operand *result, int offr )
5912 int size = AOP_SIZE(result);
5914 if(size >= LSB+offr){
5915 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5917 emitcode("add","a,acc");
5918 if (sameRegs(AOP(left),AOP(result)) &&
5919 size >= MSB16+offr && offr != LSB )
5920 emitcode("xch","a,%s",
5921 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5923 aopPut(AOP(result),"a",LSB+offr);
5926 if(size >= MSB16+offr){
5927 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5928 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5931 emitcode("rlc","a");
5932 if (sameRegs(AOP(left),AOP(result)) &&
5933 size >= MSB24+offr && offr != LSB)
5934 emitcode("xch","a,%s",
5935 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5937 aopPut(AOP(result),"a",MSB16+offr);
5940 if(size >= MSB24+offr){
5941 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5942 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5945 emitcode("rlc","a");
5946 if (sameRegs(AOP(left),AOP(result)) &&
5947 size >= MSB32+offr && offr != LSB )
5948 emitcode("xch","a,%s",
5949 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5951 aopPut(AOP(result),"a",MSB24+offr);
5954 if(size > MSB32+offr){
5955 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5956 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5959 emitcode("rlc","a");
5960 aopPut(AOP(result),"a",MSB32+offr);
5963 aopPut(AOP(result),zero,LSB);
5969 /*-----------------------------------------------------------------*/
5970 /* genlshFour - shift four byte by a known amount != 0 */
5971 /*-----------------------------------------------------------------*/
5972 static void genlshFour (operand *result, operand *left, int shCount)
5976 D(emitcode(";", "genlshFour "););
5978 size = AOP_SIZE(result);
5980 /* if shifting more that 3 bytes */
5981 if (shCount >= 24 ) {
5984 /* lowest order of left goes to the highest
5985 order of the destination */
5986 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5988 movLeft2Result(left, LSB, result, MSB32, 0);
5989 aopPut(AOP(result),zero,LSB);
5990 aopPut(AOP(result),zero,MSB16);
5991 aopPut(AOP(result),zero,MSB32);
5995 /* more than two bytes */
5996 else if ( shCount >= 16 ) {
5997 /* lower order two bytes goes to higher order two bytes */
5999 /* if some more remaining */
6001 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6003 movLeft2Result(left, MSB16, result, MSB32, 0);
6004 movLeft2Result(left, LSB, result, MSB24, 0);
6006 aopPut(AOP(result),zero,MSB16);
6007 aopPut(AOP(result),zero,LSB);
6011 /* if more than 1 byte */
6012 else if ( shCount >= 8 ) {
6013 /* lower order three bytes goes to higher order three bytes */
6017 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6019 movLeft2Result(left, LSB, result, MSB16, 0);
6021 else{ /* size = 4 */
6023 movLeft2Result(left, MSB24, result, MSB32, 0);
6024 movLeft2Result(left, MSB16, result, MSB24, 0);
6025 movLeft2Result(left, LSB, result, MSB16, 0);
6026 aopPut(AOP(result),zero,LSB);
6028 else if(shCount == 1)
6029 shiftLLong(left, result, MSB16);
6031 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6032 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6033 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6034 aopPut(AOP(result),zero,LSB);
6039 /* 1 <= shCount <= 7 */
6040 else if(shCount <= 2){
6041 shiftLLong(left, result, LSB);
6043 shiftLLong(result, result, LSB);
6045 /* 3 <= shCount <= 7, optimize */
6047 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6048 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6049 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6056 /*-----------------------------------------------------------------*/
6057 /* genLeftShiftLiteral - left shifting by known count */
6058 /*-----------------------------------------------------------------*/
6059 static void genLeftShiftLiteral (operand *left,
6064 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6067 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
6069 freeAsmop(right,NULL,ic,TRUE);
6071 aopOp(left,ic,FALSE, FALSE);
6072 aopOp(result,ic,FALSE, TRUE);
6074 size = getSize(operandType(result));
6077 emitcode("; shift left ","result %d, left %d",size,
6081 /* I suppose that the left size >= result size */
6084 movLeft2Result(left, size, result, size, 0);
6088 else if(shCount >= (size * 8))
6090 aopPut(AOP(result),zero,size);
6094 genlshOne (result,left,shCount);
6098 case 3: /* bug: this is for generic pointers, I bet. */
6099 genlshTwo (result,left,shCount);
6103 genlshFour (result,left,shCount);
6107 freeAsmop(left,NULL,ic,TRUE);
6108 freeAsmop(result,NULL,ic,TRUE);
6112 /*-----------------------------------------------------------------*/
6113 /* genLeftShift - generates code for left shifting */
6114 /*-----------------------------------------------------------------*/
6115 static void genLeftShift (iCode *ic)
6117 operand *left,*right, *result;
6120 symbol *tlbl , *tlbl1;
6122 D(emitcode(";", "genLeftShift "););
6124 right = IC_RIGHT(ic);
6126 result = IC_RESULT(ic);
6128 aopOp(right,ic,FALSE, FALSE);
6131 /* if the shift count is known then do it
6132 as efficiently as possible */
6133 if (AOP_TYPE(right) == AOP_LIT) {
6134 genLeftShiftLiteral (left,right,result,ic);
6139 /* shift count is unknown then we have to form
6140 a loop get the loop count in B : Note: we take
6141 only the lower order byte since shifting
6142 more that 32 bits make no sense anyway, ( the
6143 largest size of an object can be only 32 bits ) */
6145 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6146 emitcode("inc","b");
6147 freeAsmop (right,NULL,ic,TRUE);
6148 aopOp(left,ic,FALSE, FALSE);
6149 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6151 /* now move the left to the result if they are not the
6153 if (!sameRegs(AOP(left),AOP(result)) &&
6154 AOP_SIZE(result) > 1) {
6156 size = AOP_SIZE(result);
6158 _startLazyDPSEvaluation();
6160 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6161 if (*l == '@' && (IS_AOP_PREG(result))) {
6163 emitcode("mov","a,%s",l);
6164 aopPut(AOP(result),"a",offset);
6166 aopPut(AOP(result),l,offset);
6169 _endLazyDPSEvaluation();
6172 tlbl = newiTempLabel(NULL);
6173 size = AOP_SIZE(result);
6175 tlbl1 = newiTempLabel(NULL);
6177 /* if it is only one byte then */
6179 symbol *tlbl1 = newiTempLabel(NULL);
6181 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6183 emitcode("sjmp","%05d$",tlbl1->key+100);
6184 emitcode("","%05d$:",tlbl->key+100);
6185 emitcode("add","a,acc");
6186 emitcode("","%05d$:",tlbl1->key+100);
6187 emitcode("djnz","b,%05d$",tlbl->key+100);
6188 aopPut(AOP(result),"a",0);
6192 reAdjustPreg(AOP(result));
6194 emitcode("sjmp","%05d$",tlbl1->key+100);
6195 emitcode("","%05d$:",tlbl->key+100);
6196 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6198 emitcode("add","a,acc");
6199 aopPut(AOP(result),"a",offset++);
6200 _startLazyDPSEvaluation();
6202 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6204 emitcode("rlc","a");
6205 aopPut(AOP(result),"a",offset++);
6207 _endLazyDPSEvaluation();
6208 reAdjustPreg(AOP(result));
6210 emitcode("","%05d$:",tlbl1->key+100);
6211 emitcode("djnz","b,%05d$",tlbl->key+100);
6213 freeAsmop(left,NULL,ic,TRUE);
6214 freeAsmop(result,NULL,ic,TRUE);
6219 /*-----------------------------------------------------------------*/
6220 /* genrshOne - right shift a one byte quantity by known count */
6221 /*-----------------------------------------------------------------*/
6222 static void genrshOne (operand *result, operand *left,
6223 int shCount, int sign)
6225 D(emitcode(";", "genrshOne"););
6226 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6232 /*-----------------------------------------------------------------*/
6233 /* genrshTwo - right shift two bytes by known amount != 0 */
6234 /*-----------------------------------------------------------------*/
6235 static void genrshTwo (operand *result,operand *left,
6236 int shCount, int sign)
6238 D(emitcode(";", "genrshTwo"););
6240 /* if shCount >= 8 */
6244 shiftR1Left2Result(left, MSB16, result, LSB,
6247 movLeft2Result(left, MSB16, result, LSB, sign);
6248 addSign(result, MSB16, sign);
6251 /* 1 <= shCount <= 7 */
6253 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6259 /*-----------------------------------------------------------------*/
6260 /* shiftRLong - shift right one long from left to result */
6261 /* offl = LSB or MSB16 */
6262 /*-----------------------------------------------------------------*/
6263 static void shiftRLong (operand *left, int offl,
6264 operand *result, int sign)
6267 emitcode("clr","c");
6268 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6270 emitcode("mov","c,acc.7");
6271 emitcode("rrc","a");
6272 aopPut(AOP(result),"a",MSB32-offl);
6274 /* add sign of "a" */
6275 addSign(result, MSB32, sign);
6277 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6278 emitcode("rrc","a");
6279 aopPut(AOP(result),"a",MSB24-offl);
6281 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6282 emitcode("rrc","a");
6283 aopPut(AOP(result),"a",MSB16-offl);
6286 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6287 emitcode("rrc","a");
6288 aopPut(AOP(result),"a",LSB);
6295 /*-----------------------------------------------------------------*/
6296 /* genrshFour - shift four byte by a known amount != 0 */
6297 /*-----------------------------------------------------------------*/
6298 static void genrshFour (operand *result, operand *left,
6299 int shCount, int sign)
6301 D(emitcode(";", "genrshFour"););
6303 /* if shifting more that 3 bytes */
6304 if(shCount >= 24 ) {
6307 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6309 movLeft2Result(left, MSB32, result, LSB, sign);
6310 addSign(result, MSB16, sign);
6312 else if(shCount >= 16){
6315 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6317 movLeft2Result(left, MSB24, result, LSB, 0);
6318 movLeft2Result(left, MSB32, result, MSB16, sign);
6320 addSign(result, MSB24, sign);
6322 else if(shCount >= 8){
6325 shiftRLong(left, MSB16, result, sign);
6326 else if(shCount == 0){
6327 movLeft2Result(left, MSB16, result, LSB, 0);
6328 movLeft2Result(left, MSB24, result, MSB16, 0);
6329 movLeft2Result(left, MSB32, result, MSB24, sign);
6330 addSign(result, MSB32, sign);
6333 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6334 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6335 /* the last shift is signed */
6336 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6337 addSign(result, MSB32, sign);
6340 else{ /* 1 <= shCount <= 7 */
6342 shiftRLong(left, LSB, result, sign);
6344 shiftRLong(result, LSB, result, sign);
6347 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6348 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6349 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6357 /*-----------------------------------------------------------------*/
6358 /* genRightShiftLiteral - right shifting by known count */
6359 /*-----------------------------------------------------------------*/
6360 static void genRightShiftLiteral (operand *left,
6366 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6369 D(emitcode(";", "genRightShiftLiteral"););
6371 freeAsmop(right,NULL,ic,TRUE);
6373 aopOp(left,ic,FALSE, FALSE);
6374 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6377 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6381 size = getDataSize(left);
6382 /* test the LEFT size !!! */
6384 /* I suppose that the left size >= result size */
6386 size = getDataSize(result);
6388 movLeft2Result(left, size, result, size, 0);
6391 else if(shCount >= (size * 8)){
6393 /* get sign in acc.7 */
6394 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6395 addSign(result, LSB, sign);
6399 genrshOne (result,left,shCount,sign);
6403 genrshTwo (result,left,shCount,sign);
6407 genrshFour (result,left,shCount,sign);
6413 freeAsmop(left,NULL,ic,TRUE);
6414 freeAsmop(result,NULL,ic,TRUE);
6419 /*-----------------------------------------------------------------*/
6420 /* genSignedRightShift - right shift of signed number */
6421 /*-----------------------------------------------------------------*/
6422 static void genSignedRightShift (iCode *ic)
6424 operand *right, *left, *result;
6427 symbol *tlbl, *tlbl1 ;
6429 D(emitcode(";", "genSignedRightShift "););
6431 /* we do it the hard way put the shift count in b
6432 and loop thru preserving the sign */
6434 right = IC_RIGHT(ic);
6436 result = IC_RESULT(ic);
6438 aopOp(right,ic,FALSE, FALSE);
6441 if ( AOP_TYPE(right) == AOP_LIT) {
6442 genRightShiftLiteral (left,right,result,ic,1);
6446 /* shift count is unknown then we have to form
6447 a loop get the loop count in B : Note: we take
6448 only the lower order byte since shifting
6449 more that 32 bits make no sense anyway, ( the
6450 largest size of an object can be only 32 bits ) */
6452 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6453 emitcode("inc","b");
6454 freeAsmop (right,NULL,ic,TRUE);
6455 aopOp(left,ic,FALSE, FALSE);
6456 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6458 /* now move the left to the result if they are not the
6460 if (!sameRegs(AOP(left),AOP(result)) &&
6461 AOP_SIZE(result) > 1) {
6463 size = AOP_SIZE(result);
6465 _startLazyDPSEvaluation();
6467 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6468 if (*l == '@' && IS_AOP_PREG(result)) {
6470 emitcode("mov","a,%s",l);
6471 aopPut(AOP(result),"a",offset);
6473 aopPut(AOP(result),l,offset);
6476 _endLazyDPSEvaluation();
6479 /* mov the highest order bit to OVR */
6480 tlbl = newiTempLabel(NULL);
6481 tlbl1= newiTempLabel(NULL);
6483 size = AOP_SIZE(result);
6485 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6486 emitcode("rlc","a");
6487 emitcode("mov","ov,c");
6488 /* if it is only one byte then */
6490 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6492 emitcode("sjmp","%05d$",tlbl1->key+100);
6493 emitcode("","%05d$:",tlbl->key+100);
6494 emitcode("mov","c,ov");
6495 emitcode("rrc","a");
6496 emitcode("","%05d$:",tlbl1->key+100);
6497 emitcode("djnz","b,%05d$",tlbl->key+100);
6498 aopPut(AOP(result),"a",0);
6502 reAdjustPreg(AOP(result));
6503 emitcode("sjmp","%05d$",tlbl1->key+100);
6504 emitcode("","%05d$:",tlbl->key+100);
6505 emitcode("mov","c,ov");
6506 _startLazyDPSEvaluation();
6508 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6510 emitcode("rrc","a");
6511 aopPut(AOP(result),"a",offset--);
6513 _endLazyDPSEvaluation();
6514 reAdjustPreg(AOP(result));
6515 emitcode("","%05d$:",tlbl1->key+100);
6516 emitcode("djnz","b,%05d$",tlbl->key+100);
6519 freeAsmop(left,NULL,ic,TRUE);
6520 freeAsmop(result,NULL,ic,TRUE);
6523 /*-----------------------------------------------------------------*/
6524 /* genRightShift - generate code for right shifting */
6525 /*-----------------------------------------------------------------*/
6526 static void genRightShift (iCode *ic)
6528 operand *right, *left, *result;
6532 symbol *tlbl, *tlbl1 ;
6534 D(emitcode(";", "genRightShift "););
6536 /* if signed then we do it the hard way preserve the
6537 sign bit moving it inwards */
6538 retype = getSpec(operandType(IC_RESULT(ic)));
6540 if (!SPEC_USIGN(retype)) {
6541 genSignedRightShift (ic);
6545 /* signed & unsigned types are treated the same : i.e. the
6546 signed is NOT propagated inwards : quoting from the
6547 ANSI - standard : "for E1 >> E2, is equivalent to division
6548 by 2**E2 if unsigned or if it has a non-negative value,
6549 otherwise the result is implementation defined ", MY definition
6550 is that the sign does not get propagated */
6552 right = IC_RIGHT(ic);
6554 result = IC_RESULT(ic);
6556 aopOp(right,ic,FALSE, FALSE);
6559 /* if the shift count is known then do it
6560 as efficiently as possible */
6561 if (AOP_TYPE(right) == AOP_LIT) {
6562 genRightShiftLiteral (left,right,result,ic, 0);
6567 /* shift count is unknown then we have to form
6568 a loop get the loop count in B : Note: we take
6569 only the lower order byte since shifting
6570 more that 32 bits make no sense anyway, ( the
6571 largest size of an object can be only 32 bits ) */
6573 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6574 emitcode("inc","b");
6575 freeAsmop (right,NULL,ic,TRUE);
6576 aopOp(left,ic,FALSE, FALSE);
6577 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6579 /* now move the left to the result if they are not the
6581 if (!sameRegs(AOP(left),AOP(result)) &&
6582 AOP_SIZE(result) > 1) {
6584 size = AOP_SIZE(result);
6586 _startLazyDPSEvaluation();
6588 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6589 if (*l == '@' && IS_AOP_PREG(result)) {
6591 emitcode("mov","a,%s",l);
6592 aopPut(AOP(result),"a",offset);
6594 aopPut(AOP(result),l,offset);
6597 _endLazyDPSEvaluation();
6600 tlbl = newiTempLabel(NULL);
6601 tlbl1= newiTempLabel(NULL);
6602 size = AOP_SIZE(result);
6605 /* if it is only one byte then */
6607 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6609 emitcode("sjmp","%05d$",tlbl1->key+100);
6610 emitcode("","%05d$:",tlbl->key+100);
6612 emitcode("rrc","a");
6613 emitcode("","%05d$:",tlbl1->key+100);
6614 emitcode("djnz","b,%05d$",tlbl->key+100);
6615 aopPut(AOP(result),"a",0);
6619 reAdjustPreg(AOP(result));
6620 emitcode("sjmp","%05d$",tlbl1->key+100);
6621 emitcode("","%05d$:",tlbl->key+100);
6623 _startLazyDPSEvaluation();
6625 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6627 emitcode("rrc","a");
6628 aopPut(AOP(result),"a",offset--);
6630 _endLazyDPSEvaluation();
6631 reAdjustPreg(AOP(result));
6633 emitcode("","%05d$:",tlbl1->key+100);
6634 emitcode("djnz","b,%05d$",tlbl->key+100);
6637 freeAsmop(left,NULL,ic,TRUE);
6638 freeAsmop(result,NULL,ic,TRUE);
6641 /*-----------------------------------------------------------------*/
6642 /* genUnpackBits - generates code for unpacking bits */
6643 /*-----------------------------------------------------------------*/
6644 static void genUnpackBits (operand *result, char *rname, int ptype)
6651 D(emitcode(";", "genUnpackBits "););
6653 etype = getSpec(operandType(result));
6655 /* read the first byte */
6660 emitcode("mov","a,@%s",rname);
6664 emitcode("movx","a,@%s",rname);
6668 emitcode("movx","a,@dptr");
6672 emitcode("clr","a");
6673 emitcode("movc","a","@a+dptr");
6677 emitcode("lcall","__gptrget");
6681 /* if we have bitdisplacement then it fits */
6682 /* into this byte completely or if length is */
6683 /* less than a byte */
6684 if ((shCnt = SPEC_BSTR(etype)) ||
6685 (SPEC_BLEN(etype) <= 8)) {
6687 /* shift right acc */
6690 emitcode("anl","a,#0x%02x",
6691 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6692 aopPut(AOP(result),"a",offset);
6696 /* bit field did not fit in a byte */
6697 rlen = SPEC_BLEN(etype) - 8;
6698 aopPut(AOP(result),"a",offset++);
6705 emitcode("inc","%s",rname);
6706 emitcode("mov","a,@%s",rname);
6710 emitcode("inc","%s",rname);
6711 emitcode("movx","a,@%s",rname);
6715 emitcode("inc","dptr");
6716 emitcode("movx","a,@dptr");
6720 emitcode("clr","a");
6721 emitcode("inc","dptr");
6722 emitcode("movc","a","@a+dptr");
6726 emitcode("inc","dptr");
6727 emitcode("lcall","__gptrget");
6732 /* if we are done */
6736 aopPut(AOP(result),"a",offset++);
6741 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6742 aopPut(AOP(result),"a",offset);
6749 /*-----------------------------------------------------------------*/
6750 /* genDataPointerGet - generates code when ptr offset is known */
6751 /*-----------------------------------------------------------------*/
6752 static void genDataPointerGet (operand *left,
6758 int size , offset = 0;
6759 aopOp(result,ic,TRUE, FALSE);
6761 /* get the string representation of the name */
6762 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6763 size = AOP_SIZE(result);
6764 _startLazyDPSEvaluation();
6767 sprintf(buffer,"(%s + %d)",l+1,offset);
6769 sprintf(buffer,"%s",l+1);
6770 aopPut(AOP(result),buffer,offset++);
6772 _endLazyDPSEvaluation();
6774 freeAsmop(left,NULL,ic,TRUE);
6775 freeAsmop(result,NULL,ic,TRUE);
6778 /*-----------------------------------------------------------------*/
6779 /* genNearPointerGet - emitcode for near pointer fetch */
6780 /*-----------------------------------------------------------------*/
6781 static void genNearPointerGet (operand *left,
6788 sym_link *rtype, *retype, *letype;
6789 sym_link *ltype = operandType(left);
6792 rtype = operandType(result);
6793 retype= getSpec(rtype);
6794 letype= getSpec(ltype);
6796 aopOp(left,ic,FALSE, FALSE);
6798 /* if left is rematerialisable and
6799 result is not bit variable type and
6800 the left is pointer to data space i.e
6801 lower 128 bytes of space */
6802 if (AOP_TYPE(left) == AOP_IMMD &&
6803 !IS_BITVAR(retype) &&
6804 !IS_BITVAR(letype) &&
6805 DCL_TYPE(ltype) == POINTER) {
6806 genDataPointerGet (left,result,ic);
6810 /* if the value is already in a pointer register
6811 then don't need anything more */
6812 if (!AOP_INPREG(AOP(left))) {
6813 /* otherwise get a free pointer register */
6815 preg = getFreePtr(ic,&aop,FALSE);
6816 emitcode("mov","%s,%s",
6818 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6819 rname = preg->name ;
6821 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6823 freeAsmop(left,NULL,ic,TRUE);
6824 aopOp (result,ic,FALSE, FALSE);
6826 /* if bitfield then unpack the bits */
6827 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6828 genUnpackBits (result,rname,POINTER);
6830 /* we have can just get the values */
6831 int size = AOP_SIZE(result);
6835 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6837 emitcode("mov","a,@%s",rname);
6838 aopPut(AOP(result),"a",offset);
6840 sprintf(buffer,"@%s",rname);
6841 aopPut(AOP(result),buffer,offset);
6845 emitcode("inc","%s",rname);
6849 /* now some housekeeping stuff */
6851 /* we had to allocate for this iCode */
6852 freeAsmop(NULL,aop,ic,TRUE);
6854 /* we did not allocate which means left
6855 already in a pointer register, then
6856 if size > 0 && this could be used again
6857 we have to point it back to where it
6859 if (AOP_SIZE(result) > 1 &&
6860 !OP_SYMBOL(left)->remat &&
6861 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6863 int size = AOP_SIZE(result) - 1;
6865 emitcode("dec","%s",rname);
6870 freeAsmop(result,NULL,ic,TRUE);
6874 /*-----------------------------------------------------------------*/
6875 /* genPagedPointerGet - emitcode for paged pointer fetch */
6876 /*-----------------------------------------------------------------*/
6877 static void genPagedPointerGet (operand *left,
6884 sym_link *rtype, *retype, *letype;
6886 rtype = operandType(result);
6887 retype= getSpec(rtype);
6888 letype= getSpec(operandType(left));
6889 aopOp(left,ic,FALSE, FALSE);
6891 /* if the value is already in a pointer register
6892 then don't need anything more */
6893 if (!AOP_INPREG(AOP(left))) {
6894 /* otherwise get a free pointer register */
6896 preg = getFreePtr(ic,&aop,FALSE);
6897 emitcode("mov","%s,%s",
6899 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6900 rname = preg->name ;
6902 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6904 freeAsmop(left,NULL,ic,TRUE);
6905 aopOp (result,ic,FALSE, FALSE);
6907 /* if bitfield then unpack the bits */
6908 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6909 genUnpackBits (result,rname,PPOINTER);
6911 /* we have can just get the values */
6912 int size = AOP_SIZE(result);
6917 emitcode("movx","a,@%s",rname);
6918 aopPut(AOP(result),"a",offset);
6923 emitcode("inc","%s",rname);
6927 /* now some housekeeping stuff */
6929 /* we had to allocate for this iCode */
6930 freeAsmop(NULL,aop,ic,TRUE);
6932 /* we did not allocate which means left
6933 already in a pointer register, then
6934 if size > 0 && this could be used again
6935 we have to point it back to where it
6937 if (AOP_SIZE(result) > 1 &&
6938 !OP_SYMBOL(left)->remat &&
6939 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6941 int size = AOP_SIZE(result) - 1;
6943 emitcode("dec","%s",rname);
6948 freeAsmop(result,NULL,ic,TRUE);
6953 /*-----------------------------------------------------------------*/
6954 /* genFarPointerGet - gget value from far space */
6955 /*-----------------------------------------------------------------*/
6956 static void genFarPointerGet (operand *left,
6957 operand *result, iCode *ic)
6960 sym_link *retype = getSpec(operandType(result));
6961 sym_link *letype = getSpec(operandType(left));
6962 D(emitcode(";", "genFarPointerGet"););
6964 aopOp(left,ic,FALSE, FALSE);
6966 /* if the operand is already in dptr
6967 then we do nothing else we move the value to dptr */
6968 if (AOP_TYPE(left) != AOP_STR) {
6969 /* if this is remateriazable */
6970 if (AOP_TYPE(left) == AOP_IMMD)
6972 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6976 /* we need to get it byte by byte */
6977 _startLazyDPSEvaluation();
6978 if (AOP_TYPE(left) != AOP_DPTR)
6980 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6981 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6982 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6986 /* We need to generate a load to DPTR indirect through DPTR. */
6987 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6988 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6989 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6990 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6991 emitcode("pop", "dph");
6992 emitcode("pop", "dpl");
6994 _endLazyDPSEvaluation();
6997 /* so dptr know contains the address */
6998 freeAsmop(left,NULL,ic,TRUE);
6999 aopOp(result,ic,FALSE, TRUE);
7001 /* if bit then unpack */
7002 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7003 genUnpackBits(result,"dptr",FPOINTER);
7005 size = AOP_SIZE(result);
7008 _startLazyDPSEvaluation();
7014 emitcode("movx","a,@dptr");
7016 emitcode("inc","dptr");
7018 aopPut(AOP(result),"a",offset++);
7020 _endLazyDPSEvaluation();
7023 freeAsmop(result,NULL,ic,TRUE);
7026 /*-----------------------------------------------------------------*/
7027 /* emitcodePointerGet - gget value from code space */
7028 /*-----------------------------------------------------------------*/
7029 static void emitcodePointerGet (operand *left,
7030 operand *result, iCode *ic)
7033 sym_link *retype = getSpec(operandType(result));
7035 aopOp(left,ic,FALSE, FALSE);
7037 /* if the operand is already in dptr
7038 then we do nothing else we move the value to dptr */
7039 if (AOP_TYPE(left) != AOP_STR) {
7040 /* if this is remateriazable */
7041 if (AOP_TYPE(left) == AOP_IMMD)
7043 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7046 { /* we need to get it byte by byte */
7047 _startLazyDPSEvaluation();
7048 if (AOP_TYPE(left) != AOP_DPTR)
7050 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7051 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7052 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7056 /* We need to generate a load to DPTR indirect through DPTR. */
7057 D(emitcode(";", "gencodePointerGet -- indirection special case."););
7058 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7059 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7060 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7061 emitcode("pop", "dph");
7062 emitcode("pop", "dpl");
7064 _endLazyDPSEvaluation();
7067 /* so dptr know contains the address */
7068 freeAsmop(left,NULL,ic,TRUE);
7069 aopOp(result,ic,FALSE, TRUE);
7071 /* if bit then unpack */
7072 if (IS_BITVAR(retype))
7073 genUnpackBits(result,"dptr",CPOINTER);
7075 size = AOP_SIZE(result);
7078 _startLazyDPSEvaluation();
7084 emitcode("clr","a");
7085 emitcode("movc","a,@a+dptr");
7087 emitcode("inc","dptr");
7088 aopPut(AOP(result),"a",offset++);
7090 _endLazyDPSEvaluation();
7093 freeAsmop(result,NULL,ic,TRUE);
7096 /*-----------------------------------------------------------------*/
7097 /* genGenPointerGet - gget value from generic pointer space */
7098 /*-----------------------------------------------------------------*/
7099 static void genGenPointerGet (operand *left,
7100 operand *result, iCode *ic)
7103 sym_link *retype = getSpec(operandType(result));
7104 sym_link *letype = getSpec(operandType(left));
7106 aopOp(left,ic,FALSE, TRUE);
7108 /* if the operand is already in dptr
7109 then we do nothing else we move the value to dptr */
7110 if (AOP_TYPE(left) != AOP_STR) {
7111 /* if this is remateriazable */
7112 if (AOP_TYPE(left) == AOP_IMMD) {
7113 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7114 emitcode("mov","b,#%d",pointerCode(retype));
7116 else { /* we need to get it byte by byte */
7117 _startLazyDPSEvaluation();
7118 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7119 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7120 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7121 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7122 _endLazyDPSEvaluation();
7125 /* so dptr know contains the address */
7126 freeAsmop(left,NULL,ic,TRUE);
7127 aopOp(result,ic,FALSE, TRUE);
7129 /* if bit then unpack */
7130 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7131 genUnpackBits(result,"dptr",GPOINTER);
7133 size = AOP_SIZE(result);
7137 emitcode("lcall","__gptrget");
7138 aopPut(AOP(result),"a",offset++);
7140 emitcode("inc","dptr");
7144 freeAsmop(result,NULL,ic,TRUE);
7147 /*-----------------------------------------------------------------*/
7148 /* genPointerGet - generate code for pointer get */
7149 /*-----------------------------------------------------------------*/
7150 static void genPointerGet (iCode *ic)
7152 operand *left, *result ;
7153 sym_link *type, *etype;
7156 D(emitcode(";", "genPointerGet "););
7159 result = IC_RESULT(ic) ;
7161 /* depending on the type of pointer we need to
7162 move it to the correct pointer register */
7163 type = operandType(left);
7164 etype = getSpec(type);
7165 /* if left is of type of pointer then it is simple */
7166 if (IS_PTR(type) && !IS_FUNC(type->next))
7167 p_type = DCL_TYPE(type);
7169 /* we have to go by the storage class */
7170 p_type = PTR_TYPE(SPEC_OCLS(etype));
7173 /* now that we have the pointer type we assign
7174 the pointer values */
7179 genNearPointerGet (left,result,ic);
7183 genPagedPointerGet(left,result,ic);
7187 genFarPointerGet (left,result,ic);
7191 emitcodePointerGet (left,result,ic);
7195 genGenPointerGet (left,result,ic);
7201 /*-----------------------------------------------------------------*/
7202 /* genPackBits - generates code for packed bit storage */
7203 /*-----------------------------------------------------------------*/
7204 static void genPackBits (sym_link *etype ,
7206 char *rname, int p_type)
7214 blen = SPEC_BLEN(etype);
7215 bstr = SPEC_BSTR(etype);
7217 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7220 /* if the bit lenth is less than or */
7221 /* it exactly fits a byte then */
7222 if (SPEC_BLEN(etype) <= 8 ) {
7223 shCount = SPEC_BSTR(etype) ;
7225 /* shift left acc */
7228 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7233 emitcode ("mov","b,a");
7234 emitcode("mov","a,@%s",rname);
7238 emitcode ("mov","b,a");
7239 emitcode("movx","a,@dptr");
7243 emitcode ("push","b");
7244 emitcode ("push","acc");
7245 emitcode ("lcall","__gptrget");
7246 emitcode ("pop","b");
7250 emitcode ("anl","a,#0x%02x",(unsigned char)
7251 ((unsigned char)(0xFF << (blen+bstr)) |
7252 (unsigned char)(0xFF >> (8-bstr)) ) );
7253 emitcode ("orl","a,b");
7254 if (p_type == GPOINTER)
7255 emitcode("pop","b");
7261 emitcode("mov","@%s,a",rname);
7265 emitcode("movx","@dptr,a");
7269 emitcode("lcall","__gptrput");
7274 if ( SPEC_BLEN(etype) <= 8 )
7277 emitcode("inc","%s",rname);
7278 rLen = SPEC_BLEN(etype) ;
7280 /* now generate for lengths greater than one byte */
7283 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7293 emitcode("mov","@%s,a",rname);
7295 emitcode("mov","@%s,%s",rname,l);
7300 emitcode("movx","@dptr,a");
7305 emitcode("lcall","__gptrput");
7308 emitcode ("inc","%s",rname);
7313 /* last last was not complete */
7315 /* save the byte & read byte */
7318 emitcode ("mov","b,a");
7319 emitcode("mov","a,@%s",rname);
7323 emitcode ("mov","b,a");
7324 emitcode("movx","a,@dptr");
7328 emitcode ("push","b");
7329 emitcode ("push","acc");
7330 emitcode ("lcall","__gptrget");
7331 emitcode ("pop","b");
7335 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << rLen) );
7336 emitcode ("orl","a,b");
7339 if (p_type == GPOINTER)
7340 emitcode("pop","b");
7345 emitcode("mov","@%s,a",rname);
7349 emitcode("movx","@dptr,a");
7353 emitcode("lcall","__gptrput");
7357 /*-----------------------------------------------------------------*/
7358 /* genDataPointerSet - remat pointer to data space */
7359 /*-----------------------------------------------------------------*/
7360 static void genDataPointerSet(operand *right,
7364 int size, offset = 0 ;
7365 char *l, buffer[256];
7367 aopOp(right,ic,FALSE, FALSE);
7369 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7370 size = AOP_SIZE(right);
7373 sprintf(buffer,"(%s + %d)",l+1,offset);
7375 sprintf(buffer,"%s",l+1);
7376 emitcode("mov","%s,%s",buffer,
7377 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7380 freeAsmop(right,NULL,ic,TRUE);
7381 freeAsmop(result,NULL,ic,TRUE);
7384 /*-----------------------------------------------------------------*/
7385 /* genNearPointerSet - emitcode for near pointer put */
7386 /*-----------------------------------------------------------------*/
7387 static void genNearPointerSet (operand *right,
7394 sym_link *retype, *letype;
7395 sym_link *ptype = operandType(result);
7397 retype= getSpec(operandType(right));
7398 letype= getSpec(ptype);
7400 aopOp(result,ic,FALSE, FALSE);
7402 /* if the result is rematerializable &
7403 in data space & not a bit variable */
7404 if (AOP_TYPE(result) == AOP_IMMD &&
7405 DCL_TYPE(ptype) == POINTER &&
7406 !IS_BITVAR(retype) &&
7407 !IS_BITVAR(letype)) {
7408 genDataPointerSet (right,result,ic);
7412 /* if the value is already in a pointer register
7413 then don't need anything more */
7414 if (!AOP_INPREG(AOP(result))) {
7415 /* otherwise get a free pointer register */
7417 preg = getFreePtr(ic,&aop,FALSE);
7418 emitcode("mov","%s,%s",
7420 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7421 rname = preg->name ;
7423 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7425 freeAsmop(result,NULL,ic,TRUE);
7426 aopOp (right,ic,FALSE, FALSE);
7428 /* if bitfield then unpack the bits */
7429 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7430 genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
7432 /* we have can just get the values */
7433 int size = AOP_SIZE(right);
7437 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7440 emitcode("mov","@%s,a",rname);
7442 emitcode("mov","@%s,%s",rname,l);
7444 emitcode("inc","%s",rname);
7449 /* now some housekeeping stuff */
7451 /* we had to allocate for this iCode */
7452 freeAsmop(NULL,aop,ic,TRUE);
7454 /* we did not allocate which means left
7455 already in a pointer register, then
7456 if size > 0 && this could be used again
7457 we have to point it back to where it
7459 if (AOP_SIZE(right) > 1 &&
7460 !OP_SYMBOL(result)->remat &&
7461 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7463 int size = AOP_SIZE(right) - 1;
7465 emitcode("dec","%s",rname);
7470 freeAsmop(right,NULL,ic,TRUE);
7475 /*-----------------------------------------------------------------*/
7476 /* genPagedPointerSet - emitcode for Paged pointer put */
7477 /*-----------------------------------------------------------------*/
7478 static void genPagedPointerSet (operand *right,
7485 sym_link *retype, *letype;
7487 retype= getSpec(operandType(right));
7488 letype= getSpec(operandType(result));
7490 aopOp(result,ic,FALSE, FALSE);
7492 /* if the value is already in a pointer register
7493 then don't need anything more */
7494 if (!AOP_INPREG(AOP(result))) {
7495 /* otherwise get a free pointer register */
7497 preg = getFreePtr(ic,&aop,FALSE);
7498 emitcode("mov","%s,%s",
7500 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7501 rname = preg->name ;
7503 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7505 freeAsmop(result,NULL,ic,TRUE);
7506 aopOp (right,ic,FALSE, FALSE);
7508 /* if bitfield then unpack the bits */
7509 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7510 genPackBits ((IS_BITVAR(retype) ? retype : letype) ,right,rname,PPOINTER);
7512 /* we have can just get the values */
7513 int size = AOP_SIZE(right);
7517 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7520 emitcode("movx","@%s,a",rname);
7523 emitcode("inc","%s",rname);
7529 /* now some housekeeping stuff */
7531 /* we had to allocate for this iCode */
7532 freeAsmop(NULL,aop,ic,TRUE);
7534 /* we did not allocate which means left
7535 already in a pointer register, then
7536 if size > 0 && this could be used again
7537 we have to point it back to where it
7539 if (AOP_SIZE(right) > 1 &&
7540 !OP_SYMBOL(result)->remat &&
7541 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7543 int size = AOP_SIZE(right) - 1;
7545 emitcode("dec","%s",rname);
7550 freeAsmop(right,NULL,ic,TRUE);
7555 /*-----------------------------------------------------------------*/
7556 /* genFarPointerSet - set value from far space */
7557 /*-----------------------------------------------------------------*/
7558 static void genFarPointerSet (operand *right,
7559 operand *result, iCode *ic)
7562 sym_link *retype = getSpec(operandType(right));
7563 sym_link *letype = getSpec(operandType(result));
7565 aopOp(result,ic,FALSE, FALSE);
7567 /* if the operand is already in dptr
7568 then we do nothing else we move the value to dptr */
7569 if (AOP_TYPE(result) != AOP_STR) {
7570 /* if this is remateriazable */
7571 if (AOP_TYPE(result) == AOP_IMMD)
7572 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7575 /* we need to get it byte by byte */
7576 _startLazyDPSEvaluation();
7577 if (AOP_TYPE(result) != AOP_DPTR)
7579 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7580 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7581 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7585 /* We need to generate a load to DPTR indirect through DPTR. */
7586 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7587 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7588 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7589 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7590 emitcode("pop", "dph");
7591 emitcode("pop", "dpl");
7593 _endLazyDPSEvaluation();
7596 /* so dptr know contains the address */
7597 freeAsmop(result,NULL,ic,TRUE);
7598 aopOp(right,ic,FALSE, TRUE);
7600 /* if bit then unpack */
7601 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7602 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",FPOINTER);
7604 size = AOP_SIZE(right);
7607 _startLazyDPSEvaluation();
7609 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7615 emitcode("movx","@dptr,a");
7617 emitcode("inc","dptr");
7619 _endLazyDPSEvaluation();
7622 freeAsmop(right,NULL,ic,TRUE);
7625 /*-----------------------------------------------------------------*/
7626 /* genGenPointerSet - set value from generic pointer space */
7627 /*-----------------------------------------------------------------*/
7628 static void genGenPointerSet (operand *right,
7629 operand *result, iCode *ic)
7632 sym_link *retype = getSpec(operandType(right));
7633 sym_link *letype = getSpec(operandType(result));
7635 aopOp(result,ic,FALSE, TRUE);
7637 /* if the operand is already in dptr
7638 then we do nothing else we move the value to dptr */
7639 if (AOP_TYPE(result) != AOP_STR) {
7640 _startLazyDPSEvaluation();
7641 /* if this is remateriazable */
7642 if (AOP_TYPE(result) == AOP_IMMD) {
7643 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7644 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7646 else { /* we need to get it byte by byte */
7647 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7648 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7649 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7650 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7652 _endLazyDPSEvaluation();
7654 /* so dptr know contains the address */
7655 freeAsmop(result,NULL,ic,TRUE);
7656 aopOp(right,ic,FALSE, TRUE);
7658 /* if bit then unpack */
7659 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7660 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",GPOINTER);
7662 size = AOP_SIZE(right);
7665 _startLazyDPSEvaluation();
7667 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7673 emitcode("lcall","__gptrput");
7675 emitcode("inc","dptr");
7677 _endLazyDPSEvaluation();
7680 freeAsmop(right,NULL,ic,TRUE);
7683 /*-----------------------------------------------------------------*/
7684 /* genPointerSet - stores the value into a pointer location */
7685 /*-----------------------------------------------------------------*/
7686 static void genPointerSet (iCode *ic)
7688 operand *right, *result ;
7689 sym_link *type, *etype;
7692 D(emitcode(";", "genPointerSet "););
7694 right = IC_RIGHT(ic);
7695 result = IC_RESULT(ic) ;
7697 /* depending on the type of pointer we need to
7698 move it to the correct pointer register */
7699 type = operandType(result);
7700 etype = getSpec(type);
7701 /* if left is of type of pointer then it is simple */
7702 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7703 p_type = DCL_TYPE(type);
7706 /* we have to go by the storage class */
7707 p_type = PTR_TYPE(SPEC_OCLS(etype));
7710 /* now that we have the pointer type we assign
7711 the pointer values */
7716 genNearPointerSet (right,result,ic);
7720 genPagedPointerSet (right,result,ic);
7724 genFarPointerSet (right,result,ic);
7728 genGenPointerSet (right,result,ic);
7734 /*-----------------------------------------------------------------*/
7735 /* genIfx - generate code for Ifx statement */
7736 /*-----------------------------------------------------------------*/
7737 static void genIfx (iCode *ic, iCode *popIc)
7739 operand *cond = IC_COND(ic);
7742 D(emitcode(";", "genIfx "););
7744 aopOp(cond,ic,FALSE, FALSE);
7746 /* get the value into acc */
7747 if (AOP_TYPE(cond) != AOP_CRY)
7751 /* the result is now in the accumulator */
7752 freeAsmop(cond,NULL,ic,TRUE);
7754 /* if there was something to be popped then do it */
7758 /* if the condition is a bit variable */
7759 if (isbit && IS_ITEMP(cond) &&
7761 genIfxJump(ic,SPIL_LOC(cond)->rname);
7763 if (isbit && !IS_ITEMP(cond))
7764 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7771 /*-----------------------------------------------------------------*/
7772 /* genAddrOf - generates code for address of */
7773 /*-----------------------------------------------------------------*/
7774 static void genAddrOf (iCode *ic)
7776 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7779 D(emitcode(";", "genAddrOf "););
7781 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7783 /* if the operand is on the stack then we
7784 need to get the stack offset of this
7787 /* if it has an offset then we need to compute
7790 emitcode("mov","a,_bp");
7791 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7792 aopPut(AOP(IC_RESULT(ic)),"a",0);
7794 /* we can just move _bp */
7795 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7797 /* fill the result with zero */
7798 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7801 if (options.stack10bit && size < (FPTRSIZE - 1))
7804 "*** warning: pointer to stack var truncated.\n");
7811 if (options.stack10bit && offset == 2)
7813 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7817 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7824 /* object not on stack then we need the name */
7825 size = AOP_SIZE(IC_RESULT(ic));
7829 char s[SDCC_NAME_MAX];
7831 sprintf(s,"#(%s >> %d)",
7835 sprintf(s,"#%s",sym->rname);
7836 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7840 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7844 /*-----------------------------------------------------------------*/
7845 /* genFarFarAssign - assignment when both are in far space */
7846 /*-----------------------------------------------------------------*/
7847 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7849 int size = AOP_SIZE(right);
7856 /* This is a net loss for size == 1, but a big gain
7859 D(emitcode(";", "genFarFarAssign (improved)"););
7861 aopOp(result,ic,TRUE, TRUE);
7863 _startLazyDPSEvaluation();
7867 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7871 _endLazyDPSEvaluation();
7872 freeAsmop(result,NULL,ic,FALSE);
7873 freeAsmop(right,NULL,ic,FALSE);
7878 D(emitcode(";", "genFarFarAssign "););
7880 /* first push the right side on to the stack */
7881 _startLazyDPSEvaluation();
7883 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7885 emitcode ("push","acc");
7888 freeAsmop(right,NULL,ic,FALSE);
7889 /* now assign DPTR to result */
7890 aopOp(result,ic,FALSE, FALSE);
7891 size = AOP_SIZE(result);
7893 emitcode ("pop","acc");
7894 aopPut(AOP(result),"a",--offset);
7896 freeAsmop(result,NULL,ic,FALSE);
7897 _endLazyDPSEvaluation();
7901 /*-----------------------------------------------------------------*/
7902 /* genAssign - generate code for assignment */
7903 /*-----------------------------------------------------------------*/
7904 static void genAssign (iCode *ic)
7906 operand *result, *right;
7908 unsigned long lit = 0L;
7910 D(emitcode(";", "genAssign "););
7912 result = IC_RESULT(ic);
7913 right = IC_RIGHT(ic) ;
7915 /* if they are the same */
7916 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7919 aopOp(right,ic,FALSE, FALSE);
7921 emitcode(";", "genAssign: resultIsFar = %s",
7922 isOperandInFarSpace(result) ?
7925 /* special case both in far space */
7926 if ((AOP_TYPE(right) == AOP_DPTR ||
7927 AOP_TYPE(right) == AOP_DPTR2) &&
7928 /* IS_TRUE_SYMOP(result) && */
7929 isOperandInFarSpace(result)) {
7931 genFarFarAssign (result,right,ic);
7935 aopOp(result,ic,TRUE, FALSE);
7937 /* if they are the same registers */
7938 if (sameRegs(AOP(right),AOP(result)))
7941 /* if the result is a bit */
7942 if (AOP_TYPE(result) == AOP_CRY) {
7944 /* if the right size is a literal then
7945 we know what the value is */
7946 if (AOP_TYPE(right) == AOP_LIT) {
7947 if (((int) operandLitValue(right)))
7948 aopPut(AOP(result),one,0);
7950 aopPut(AOP(result),zero,0);
7954 /* the right is also a bit variable */
7955 if (AOP_TYPE(right) == AOP_CRY) {
7956 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7957 aopPut(AOP(result),"c",0);
7963 aopPut(AOP(result),"a",0);
7967 /* bit variables done */
7969 size = AOP_SIZE(result);
7971 if(AOP_TYPE(right) == AOP_LIT)
7972 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7975 (AOP_TYPE(result) != AOP_REG) &&
7976 (AOP_TYPE(right) == AOP_LIT) &&
7977 !IS_FLOAT(operandType(right))
7978 #ifndef LAZY_DPS_OPT
7984 D(emitcode(";", "Kevin's better literal load code"););
7985 _startLazyDPSEvaluation();
7986 while (size && ((unsigned int)(lit >> (offset*8)) != 0))
7989 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
7994 /* And now fill the rest with zeros. */
7997 emitcode("clr","a");
8001 aopPut(AOP(result), "a", offset++);
8003 _endLazyDPSEvaluation();
8005 emitcode("clr","a");
8007 _startLazyDPSEvaluation();
8010 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
8011 aopPut(AOP(result),"a",size);
8014 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
8017 _endLazyDPSEvaluation();
8022 _startLazyDPSEvaluation();
8026 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8030 _endLazyDPSEvaluation();
8034 freeAsmop (right,NULL,ic,FALSE);
8035 freeAsmop (result,NULL,ic,TRUE);
8038 /*-----------------------------------------------------------------*/
8039 /* genJumpTab - generates code for jump table */
8040 /*-----------------------------------------------------------------*/
8041 static void genJumpTab (iCode *ic)
8046 D(emitcode(";", "genJumpTab "););
8048 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
8049 /* get the condition into accumulator */
8050 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
8052 /* multiply by four! */
8053 emitcode("add","a,acc");
8054 emitcode("add","a,acc");
8055 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8057 jtab = newiTempLabel(NULL);
8058 emitcode("mov","dptr,#%05d$",jtab->key+100);
8059 emitcode("jmp","@a+dptr");
8060 emitcode("","%05d$:",jtab->key+100);
8061 /* now generate the jump labels */
8062 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8063 jtab = setNextItem(IC_JTLABELS(ic)))
8064 emitcode("ljmp","%05d$",jtab->key+100);
8068 /*-----------------------------------------------------------------*/
8069 /* genCast - gen code for casting */
8070 /*-----------------------------------------------------------------*/
8071 static void genCast (iCode *ic)
8073 operand *result = IC_RESULT(ic);
8074 sym_link *ctype = operandType(IC_LEFT(ic));
8075 sym_link *rtype = operandType(IC_RIGHT(ic));
8076 operand *right = IC_RIGHT(ic);
8079 D(emitcode(";", "genCast "););
8081 /* if they are equivalent then do nothing */
8082 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8085 aopOp(right,ic,FALSE, FALSE) ;
8086 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
8088 /* if the result is a bit */
8089 if (AOP_TYPE(result) == AOP_CRY) {
8090 /* if the right size is a literal then
8091 we know what the value is */
8092 if (AOP_TYPE(right) == AOP_LIT) {
8093 if (((int) operandLitValue(right)))
8094 aopPut(AOP(result),one,0);
8096 aopPut(AOP(result),zero,0);
8101 /* the right is also a bit variable */
8102 if (AOP_TYPE(right) == AOP_CRY) {
8103 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8104 aopPut(AOP(result),"c",0);
8110 aopPut(AOP(result),"a",0);
8114 /* if they are the same size : or less */
8115 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8117 /* if they are in the same place */
8118 if (sameRegs(AOP(right),AOP(result)))
8121 /* if they in different places then copy */
8122 size = AOP_SIZE(result);
8124 _startLazyDPSEvaluation();
8127 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8131 _endLazyDPSEvaluation();
8136 /* if the result is of type pointer */
8137 if (IS_PTR(ctype)) {
8140 sym_link *type = operandType(right);
8142 /* pointer to generic pointer */
8143 if (IS_GENPTR(ctype)) {
8148 p_type = DCL_TYPE(type);
8152 #if OLD_CAST_BEHAVIOR
8153 /* KV: we are converting a non-pointer type to
8154 * a generic pointer. This (ifdef'd out) code
8155 * says that the resulting generic pointer
8156 * should have the same class as the storage
8157 * location of the non-pointer variable.
8159 * For example, converting an int (which happens
8160 * to be stored in DATA space) to a pointer results
8161 * in a DATA generic pointer; if the original int
8162 * in XDATA space, so will be the resulting pointer.
8164 * I don't like that behavior, and thus this change:
8165 * all such conversions will be forced to XDATA and
8166 * throw a warning. If you want some non-XDATA
8167 * type, or you want to suppress the warning, you
8168 * must go through an intermediate cast, like so:
8170 * char _generic *gp = (char _xdata *)(intVar);
8172 sym_link *etype = getSpec(type);
8174 /* we have to go by the storage class */
8175 if (SPEC_OCLS(etype) != generic)
8177 p_type = PTR_TYPE(SPEC_OCLS(etype));
8182 /* Converting unknown class (i.e. register variable)
8183 * to generic pointer. This is not good, but
8184 * we'll make a guess (and throw a warning).
8187 werror(W_INT_TO_GEN_PTR_CAST);
8191 /* the first two bytes are known */
8192 size = GPTRSIZE - 1;
8194 _startLazyDPSEvaluation();
8197 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8201 _endLazyDPSEvaluation();
8203 /* the last byte depending on type */
8220 /* this should never happen */
8221 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8222 "got unknown pointer type");
8225 aopPut(AOP(result),l, GPTRSIZE - 1);
8229 /* just copy the pointers */
8230 size = AOP_SIZE(result);
8232 _startLazyDPSEvaluation();
8235 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8239 _endLazyDPSEvaluation();
8243 /* so we now know that the size of destination is greater
8244 than the size of the source */
8245 /* we move to result for the size of source */
8246 size = AOP_SIZE(right);
8248 _startLazyDPSEvaluation();
8251 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8255 _endLazyDPSEvaluation();
8257 /* now depending on the sign of the source && destination */
8258 size = AOP_SIZE(result) - AOP_SIZE(right);
8259 /* if unsigned or not an integral type */
8260 /* also, if the source is a bit, we don't need to sign extend, because
8261 * it can't possibly have set the sign bit.
8263 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype) || AOP_TYPE(right) == AOP_CRY)
8267 aopPut(AOP(result),zero,offset++);
8272 /* we need to extend the sign :{ */
8273 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8276 emitcode("rlc","a");
8277 emitcode("subb","a,acc");
8279 aopPut(AOP(result),"a",offset++);
8282 /* we are done hurray !!!! */
8285 freeAsmop(right,NULL,ic,TRUE);
8286 freeAsmop(result,NULL,ic,TRUE);
8290 /*-----------------------------------------------------------------*/
8291 /* genDjnz - generate decrement & jump if not zero instrucion */
8292 /*-----------------------------------------------------------------*/
8293 static int genDjnz (iCode *ic, iCode *ifx)
8299 /* if the if condition has a false label
8300 then we cannot save */
8304 /* if the minus is not of the form
8306 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8307 !IS_OP_LITERAL(IC_RIGHT(ic)))
8310 if (operandLitValue(IC_RIGHT(ic)) != 1)
8313 /* if the size of this greater than one then no
8315 if (getSize(operandType(IC_RESULT(ic))) > 1)
8318 /* otherwise we can save BIG */
8319 lbl = newiTempLabel(NULL);
8320 lbl1= newiTempLabel(NULL);
8322 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8324 if (IS_AOP_PREG(IC_RESULT(ic))) {
8325 emitcode("dec","%s",
8326 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8327 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8328 emitcode("jnz","%05d$",lbl->key+100);
8330 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8333 emitcode ("sjmp","%05d$",lbl1->key+100);
8334 emitcode ("","%05d$:",lbl->key+100);
8335 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8336 emitcode ("","%05d$:",lbl1->key+100);
8338 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8343 /*-----------------------------------------------------------------*/
8344 /* genReceive - generate code for a receive iCode */
8345 /*-----------------------------------------------------------------*/
8346 static void genReceive (iCode *ic)
8349 D(emitcode(";", "genReceive "););
8351 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8352 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8353 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8354 int size = getSize(operandType(IC_RESULT(ic)));
8355 int offset = fReturnSize_390 - size;
8357 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8358 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8361 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8362 size = AOP_SIZE(IC_RESULT(ic));
8365 emitcode ("pop","acc");
8366 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8371 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8373 assignResultValue(IC_RESULT(ic));
8376 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8379 /*-----------------------------------------------------------------*/
8380 /* gen390Code - generate code for Dallas 390 based controllers */
8381 /*-----------------------------------------------------------------*/
8382 void gen390Code (iCode *lic)
8387 lineHead = lineCurr = NULL;
8391 /* print the allocation information */
8393 printAllocInfo( currFunc, codeOutFile);
8395 /* if debug information required */
8396 if (options.debug && currFunc) {
8397 //jwk if (currFunc) {
8398 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8400 if (IS_STATIC(currFunc->etype))
8401 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8403 emitcode("","G$%s$0$0 ==.",currFunc->name);
8406 /* stack pointer name */
8407 if (options.useXstack)
8413 for (ic = lic ; ic ; ic = ic->next ) {
8415 if ( cln != ic->lineno ) {
8416 if ( options.debug ) {
8418 emitcode("","C$%s$%d$%d$%d ==.",
8419 ic->filename,ic->lineno,
8420 ic->level,ic->block);
8423 emitcode(";","%s %d",ic->filename,ic->lineno);
8426 /* if the result is marked as
8427 spilt and rematerializable or code for
8428 this has already been generated then
8430 if (resultRemat(ic) || ic->generated )
8433 /* depending on the operation */
8452 /* IPOP happens only when trying to restore a
8453 spilt live range, if there is an ifx statement
8454 following this pop then the if statement might
8455 be using some of the registers being popped which
8456 would destory the contents of the register so
8457 we need to check for this condition and handle it */
8459 ic->next->op == IFX &&
8460 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8461 genIfx (ic->next,ic);
8479 genEndFunction (ic);
8499 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8516 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8520 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8527 /* note these two are xlated by algebraic equivalence
8528 during parsing SDCC.y */
8529 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8530 "got '>=' or '<=' shouldn't have come here");
8534 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8546 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8550 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8554 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8581 case GET_VALUE_AT_ADDRESS:
8586 if (POINTER_SET(ic))
8613 addSet(&_G.sendSet,ic);
8618 /* piCode(ic,stdout); */
8624 /* now we are ready to call the
8625 peep hole optimizer */
8626 if (!options.nopeep)
8627 peepHole (&lineHead);
8629 /* now do the actual printing */
8630 printLine (lineHead,codeOutFile);