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);
4736 for(;(size--);offset++)
4739 // result = left & right
4740 if(AOP_TYPE(right) == AOP_LIT)
4742 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4745 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4749 else if (bytelit == 0)
4751 aopPut(AOP(result),zero,offset);
4754 D(emitcode(";", "better literal AND."););
4755 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4756 emitcode("anl", "a, %s", aopGet(AOP(right),offset,
4757 FALSE,FALSE,FALSE));
4762 // faster than result <- left, anl result,right
4763 // and better if result is SFR
4764 if (AOP_TYPE(left) == AOP_ACC)
4766 emitcode("anl","a,%s",aopGet(AOP(right),offset,
4767 FALSE,FALSE,FALSE));
4771 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4772 emitcode("anl","a,%s",
4773 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4776 aopPut(AOP(result),"a",offset);
4782 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4783 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4784 freeAsmop(result,NULL,ic,TRUE);
4787 /*-----------------------------------------------------------------*/
4788 /* genOr - code for or */
4789 /*-----------------------------------------------------------------*/
4790 static void genOr (iCode *ic, iCode *ifx)
4792 operand *left, *right, *result;
4794 unsigned long lit = 0L;
4796 D(emitcode(";", "genOr "););
4801 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4802 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4803 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4807 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4809 AOP_TYPE(left), AOP_TYPE(right));
4810 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4812 AOP_SIZE(left), AOP_SIZE(right));
4815 /* if left is a literal & right is not then exchange them */
4816 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4817 AOP_NEEDSACC(left)) {
4818 operand *tmp = right ;
4823 /* if result = right then exchange them */
4824 if(sameRegs(AOP(result),AOP(right))){
4825 operand *tmp = right ;
4830 /* if right is bit then exchange them */
4831 if (AOP_TYPE(right) == AOP_CRY &&
4832 AOP_TYPE(left) != AOP_CRY){
4833 operand *tmp = right ;
4837 if(AOP_TYPE(right) == AOP_LIT)
4838 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4840 size = AOP_SIZE(result);
4844 if (AOP_TYPE(left) == AOP_CRY){
4845 if(AOP_TYPE(right) == AOP_LIT){
4846 // c = bit & literal;
4848 // lit != 0 => result = 1
4849 if(AOP_TYPE(result) == AOP_CRY){
4851 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4853 continueIfTrue(ifx);
4856 emitcode("setb","c");
4858 // lit == 0 => result = left
4859 if(size && sameRegs(AOP(result),AOP(left)))
4861 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4864 if (AOP_TYPE(right) == AOP_CRY){
4866 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4867 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4871 symbol *tlbl = newiTempLabel(NULL);
4872 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4873 emitcode("setb","c");
4874 emitcode("jb","%s,%05d$",
4875 AOP(left)->aopu.aop_dir,tlbl->key+100);
4877 emitcode("jnz","%05d$",tlbl->key+100);
4878 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4879 jmpTrueOrFalse(ifx, tlbl);
4883 emitcode("","%05d$:",tlbl->key+100);
4892 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4893 genIfxJump(ifx, "c");
4897 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4898 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4899 if((AOP_TYPE(right) == AOP_LIT) &&
4900 (AOP_TYPE(result) == AOP_CRY) &&
4901 (AOP_TYPE(left) != AOP_CRY)){
4905 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4907 continueIfTrue(ifx);
4910 // lit = 0, result = boolean(left)
4912 emitcode("setb","c");
4915 symbol *tlbl = newiTempLabel(NULL);
4916 emitcode("jnz","%05d$",tlbl->key+100);
4918 emitcode("","%05d$:",tlbl->key+100);
4920 genIfxJump (ifx,"a");
4928 /* if left is same as result */
4929 if(sameRegs(AOP(result),AOP(left)))
4931 for(;size--; offset++)
4933 if(AOP_TYPE(right) == AOP_LIT){
4934 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4940 if (IS_AOP_PREG(left))
4942 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4943 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4944 aopPut(AOP(result),"a",offset);
4948 emitcode("orl","%s,%s",
4949 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4950 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4956 if (AOP_TYPE(left) == AOP_ACC)
4958 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4962 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4963 if (IS_AOP_PREG(left))
4965 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4966 aopPut(AOP(result),"a",offset);
4970 emitcode("orl","%s,a",
4971 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4979 // left & result in different registers
4980 if(AOP_TYPE(result) == AOP_CRY)
4983 // if(size), result in bit
4984 // if(!size && ifx), conditional oper: if(left | right)
4985 symbol *tlbl = newiTempLabel(NULL);
4986 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4988 emitcode("setb","c");
4990 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4991 emitcode("orl","a,%s",
4992 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4993 emitcode("jnz","%05d$",tlbl->key+100);
4998 emitcode("","%05d$:",tlbl->key+100);
5001 jmpTrueOrFalse(ifx, tlbl);
5005 for(;(size--);offset++)
5008 // result = left & right
5009 if(AOP_TYPE(right) == AOP_LIT)
5011 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5014 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5018 D(emitcode(";", "better literal OR."););
5019 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5020 emitcode("orl", "a, %s", aopGet(AOP(right),offset,
5021 FALSE,FALSE,FALSE));
5026 // faster than result <- left, anl result,right
5027 // and better if result is SFR
5028 if (AOP_TYPE(left) == AOP_ACC)
5030 emitcode("orl","a,%s",aopGet(AOP(right),offset,
5031 FALSE,FALSE,FALSE));
5035 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5036 emitcode("orl","a,%s",
5037 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5040 aopPut(AOP(result),"a",offset);
5046 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5047 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5048 freeAsmop(result,NULL,ic,TRUE);
5051 /*-----------------------------------------------------------------*/
5052 /* genXor - code for xclusive or */
5053 /*-----------------------------------------------------------------*/
5054 static void genXor (iCode *ic, iCode *ifx)
5056 operand *left, *right, *result;
5058 unsigned long lit = 0L;
5060 D(emitcode(";", "genXor "););
5065 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
5066 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
5067 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
5071 emitcode("","; Type res[%d] = l[%d]&r[%d]",
5073 AOP_TYPE(left), AOP_TYPE(right));
5074 emitcode("","; Size res[%d] = l[%d]&r[%d]",
5076 AOP_SIZE(left), AOP_SIZE(right));
5079 /* if left is a literal & right is not ||
5080 if left needs acc & right does not */
5081 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5082 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5083 operand *tmp = right ;
5088 /* if result = right then exchange them */
5089 if(sameRegs(AOP(result),AOP(right))){
5090 operand *tmp = right ;
5095 /* if right is bit then exchange them */
5096 if (AOP_TYPE(right) == AOP_CRY &&
5097 AOP_TYPE(left) != AOP_CRY){
5098 operand *tmp = right ;
5102 if(AOP_TYPE(right) == AOP_LIT)
5103 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5105 size = AOP_SIZE(result);
5109 if (AOP_TYPE(left) == AOP_CRY){
5110 if(AOP_TYPE(right) == AOP_LIT){
5111 // c = bit & literal;
5113 // lit>>1 != 0 => result = 1
5114 if(AOP_TYPE(result) == AOP_CRY){
5116 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5118 continueIfTrue(ifx);
5121 emitcode("setb","c");
5125 // lit == 0, result = left
5126 if(size && sameRegs(AOP(result),AOP(left)))
5128 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5130 // lit == 1, result = not(left)
5131 if(size && sameRegs(AOP(result),AOP(left))){
5132 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5135 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5136 emitcode("cpl","c");
5143 symbol *tlbl = newiTempLabel(NULL);
5144 if (AOP_TYPE(right) == AOP_CRY){
5146 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5149 int sizer = AOP_SIZE(right);
5151 // if val>>1 != 0, result = 1
5152 emitcode("setb","c");
5154 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5156 // test the msb of the lsb
5157 emitcode("anl","a,#0xfe");
5158 emitcode("jnz","%05d$",tlbl->key+100);
5162 emitcode("rrc","a");
5164 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5165 emitcode("cpl","c");
5166 emitcode("","%05d$:",(tlbl->key+100));
5173 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5174 genIfxJump(ifx, "c");
5178 if(sameRegs(AOP(result),AOP(left))){
5179 /* if left is same as result */
5180 for(;size--; offset++) {
5181 if(AOP_TYPE(right) == AOP_LIT){
5182 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5185 if (IS_AOP_PREG(left)) {
5186 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5187 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5188 aopPut(AOP(result),"a",offset);
5190 emitcode("xrl","%s,%s",
5191 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5192 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5194 if (AOP_TYPE(left) == AOP_ACC)
5195 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5197 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5198 if (IS_AOP_PREG(left)) {
5199 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5200 aopPut(AOP(result),"a",offset);
5202 emitcode("xrl","%s,a",
5203 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5208 // left & result in different registers
5209 if(AOP_TYPE(result) == AOP_CRY){
5211 // if(size), result in bit
5212 // if(!size && ifx), conditional oper: if(left ^ right)
5213 symbol *tlbl = newiTempLabel(NULL);
5214 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5216 emitcode("setb","c");
5218 if((AOP_TYPE(right) == AOP_LIT) &&
5219 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5220 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5222 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5223 emitcode("xrl","a,%s",
5224 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5226 emitcode("jnz","%05d$",tlbl->key+100);
5231 emitcode("","%05d$:",tlbl->key+100);
5234 jmpTrueOrFalse(ifx, tlbl);
5235 } else for(;(size--);offset++)
5238 // result = left & right
5239 if(AOP_TYPE(right) == AOP_LIT)
5241 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5244 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5248 D(emitcode(";", "better literal XOR."););
5249 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5250 emitcode("xrl", "a, %s", aopGet(AOP(right),offset,
5251 FALSE,FALSE,FALSE));
5255 // faster than result <- left, anl result,right
5256 // and better if result is SFR
5257 if (AOP_TYPE(left) == AOP_ACC)
5259 emitcode("xrl","a,%s",aopGet(AOP(right),offset,
5260 FALSE,FALSE,FALSE));
5264 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5265 emitcode("xrl","a,%s",
5266 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5269 aopPut(AOP(result),"a",offset);
5274 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5275 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5276 freeAsmop(result,NULL,ic,TRUE);
5279 /*-----------------------------------------------------------------*/
5280 /* genInline - write the inline code out */
5281 /*-----------------------------------------------------------------*/
5282 static void genInline (iCode *ic)
5284 char buffer[MAX_INLINEASM];
5288 D(emitcode(";", "genInline "););
5290 _G.inLine += (!options.asmpeep);
5291 strcpy(buffer,IC_INLINE(ic));
5293 /* emit each line as a code */
5312 /* emitcode("",buffer); */
5313 _G.inLine -= (!options.asmpeep);
5316 /*-----------------------------------------------------------------*/
5317 /* genRRC - rotate right with carry */
5318 /*-----------------------------------------------------------------*/
5319 static void genRRC (iCode *ic)
5321 operand *left , *result ;
5322 int size, offset = 0;
5325 D(emitcode(";", "genRRC "););
5327 /* rotate right with carry */
5329 result=IC_RESULT(ic);
5330 aopOp (left,ic,FALSE, FALSE);
5331 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5333 /* move it to the result */
5334 size = AOP_SIZE(result);
5338 _startLazyDPSEvaluation();
5340 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5342 emitcode("rrc","a");
5343 if (AOP_SIZE(result) > 1)
5344 aopPut(AOP(result),"a",offset--);
5346 _endLazyDPSEvaluation();
5348 /* now we need to put the carry into the
5349 highest order byte of the result */
5350 if (AOP_SIZE(result) > 1) {
5351 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5354 emitcode("mov","acc.7,c");
5355 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5356 freeAsmop(left,NULL,ic,TRUE);
5357 freeAsmop(result,NULL,ic,TRUE);
5360 /*-----------------------------------------------------------------*/
5361 /* genRLC - generate code for rotate left with carry */
5362 /*-----------------------------------------------------------------*/
5363 static void genRLC (iCode *ic)
5365 operand *left , *result ;
5366 int size, offset = 0;
5369 D(emitcode(";", "genRLC "););
5371 /* rotate right with carry */
5373 result=IC_RESULT(ic);
5374 aopOp (left,ic,FALSE, FALSE);
5375 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5377 /* move it to the result */
5378 size = AOP_SIZE(result);
5381 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5383 emitcode("add","a,acc");
5384 if (AOP_SIZE(result) > 1)
5386 aopPut(AOP(result),"a",offset++);
5389 _startLazyDPSEvaluation();
5391 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5393 emitcode("rlc","a");
5394 if (AOP_SIZE(result) > 1)
5395 aopPut(AOP(result),"a",offset++);
5397 _endLazyDPSEvaluation();
5399 /* now we need to put the carry into the
5400 highest order byte of the result */
5401 if (AOP_SIZE(result) > 1) {
5402 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5405 emitcode("mov","acc.0,c");
5406 aopPut(AOP(result),"a",0);
5407 freeAsmop(left,NULL,ic,TRUE);
5408 freeAsmop(result,NULL,ic,TRUE);
5411 /*-----------------------------------------------------------------*/
5412 /* genGetHbit - generates code get highest order bit */
5413 /*-----------------------------------------------------------------*/
5414 static void genGetHbit (iCode *ic)
5416 operand *left, *result;
5418 result=IC_RESULT(ic);
5419 aopOp (left,ic,FALSE, FALSE);
5420 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5422 D(emitcode(";", "genGetHbit "););
5424 /* get the highest order byte into a */
5425 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5426 if(AOP_TYPE(result) == AOP_CRY){
5427 emitcode("rlc","a");
5432 emitcode("anl","a,#0x01");
5437 freeAsmop(left,NULL,ic,TRUE);
5438 freeAsmop(result,NULL,ic,TRUE);
5441 /*-----------------------------------------------------------------*/
5442 /* AccRol - rotate left accumulator by known count */
5443 /*-----------------------------------------------------------------*/
5444 static void AccRol (int shCount)
5446 shCount &= 0x0007; // shCount : 0..7
5458 emitcode("swap","a");
5462 emitcode("swap","a");
5465 emitcode("swap","a");
5478 /*-----------------------------------------------------------------*/
5479 /* AccLsh - left shift accumulator by known count */
5480 /*-----------------------------------------------------------------*/
5481 static void AccLsh (int shCount)
5485 emitcode("add","a,acc");
5488 emitcode("add","a,acc");
5489 emitcode("add","a,acc");
5491 /* rotate left accumulator */
5493 /* and kill the lower order bits */
5494 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5499 /*-----------------------------------------------------------------*/
5500 /* AccRsh - right shift accumulator by known count */
5501 /*-----------------------------------------------------------------*/
5502 static void AccRsh (int shCount)
5507 emitcode("rrc","a");
5509 /* rotate right accumulator */
5510 AccRol(8 - shCount);
5511 /* and kill the higher order bits */
5512 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5519 /*-----------------------------------------------------------------*/
5520 /* AccSRsh - signed right shift accumulator by known count */
5521 /*-----------------------------------------------------------------*/
5522 static void AccSRsh (int shCount)
5527 emitcode("mov","c,acc.7");
5528 emitcode("rrc","a");
5529 } else if(shCount == 2){
5530 emitcode("mov","c,acc.7");
5531 emitcode("rrc","a");
5532 emitcode("mov","c,acc.7");
5533 emitcode("rrc","a");
5535 tlbl = newiTempLabel(NULL);
5536 /* rotate right accumulator */
5537 AccRol(8 - shCount);
5538 /* and kill the higher order bits */
5539 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5540 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5541 emitcode("orl","a,#0x%02x",
5542 (unsigned char)~SRMask[shCount]);
5543 emitcode("","%05d$:",tlbl->key+100);
5551 /*-----------------------------------------------------------------*/
5552 /* shiftR1Left2Result - shift right one byte from left to result */
5553 /*-----------------------------------------------------------------*/
5554 static void shiftR1Left2Result (operand *left, int offl,
5555 operand *result, int offr,
5556 int shCount, int sign)
5558 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5559 /* shift right accumulator */
5564 aopPut(AOP(result),"a",offr);
5570 /*-----------------------------------------------------------------*/
5571 /* shiftL1Left2Result - shift left one byte from left to result */
5572 /*-----------------------------------------------------------------*/
5573 static void shiftL1Left2Result (operand *left, int offl,
5574 operand *result, int offr, int shCount)
5577 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5579 /* shift left accumulator */
5581 aopPut(AOP(result),"a",offr);
5587 /*-----------------------------------------------------------------*/
5588 /* movLeft2Result - move byte from left to result */
5589 /*-----------------------------------------------------------------*/
5590 static void movLeft2Result (operand *left, int offl,
5591 operand *result, int offr, int sign)
5594 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5595 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5597 if (*l == '@' && (IS_AOP_PREG(result))) {
5598 emitcode("mov","a,%s",l);
5599 aopPut(AOP(result),"a",offr);
5602 aopPut(AOP(result),l,offr);
5604 /* MSB sign in acc.7 ! */
5605 if(getDataSize(left) == offl+1){
5606 emitcode("mov","a,%s",l);
5607 aopPut(AOP(result),"a",offr);
5617 /*-----------------------------------------------------------------*/
5618 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5619 /*-----------------------------------------------------------------*/
5620 static void AccAXRrl1 (char *x)
5622 emitcode("rrc","a");
5623 emitcode("xch","a,%s", x);
5624 emitcode("rrc","a");
5625 emitcode("xch","a,%s", x);
5631 /*-----------------------------------------------------------------*/
5632 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5633 /*-----------------------------------------------------------------*/
5634 static void AccAXLrl1 (char *x)
5636 emitcode("xch","a,%s",x);
5637 emitcode("rlc","a");
5638 emitcode("xch","a,%s",x);
5639 emitcode("rlc","a");
5645 /*-----------------------------------------------------------------*/
5646 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5647 /*-----------------------------------------------------------------*/
5648 static void AccAXLsh1 (char *x)
5650 emitcode("xch","a,%s",x);
5651 emitcode("add","a,acc");
5652 emitcode("xch","a,%s",x);
5653 emitcode("rlc","a");
5659 /*-----------------------------------------------------------------*/
5660 /* AccAXLsh - left shift a:x by known count (0..7) */
5661 /*-----------------------------------------------------------------*/
5662 static void AccAXLsh (char *x, int shCount)
5676 case 5 : // AAAAABBB:CCCCCDDD
5677 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5678 emitcode("anl","a,#0x%02x",
5679 SLMask[shCount]); // BBB00000:CCCCCDDD
5680 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5681 AccRol(shCount); // DDDCCCCC:BBB00000
5682 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5683 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5684 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5685 emitcode("anl","a,#0x%02x",
5686 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5687 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5688 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5690 case 6 : // AAAAAABB:CCCCCCDD
5691 emitcode("anl","a,#0x%02x",
5692 SRMask[shCount]); // 000000BB:CCCCCCDD
5693 emitcode("mov","c,acc.0"); // c = B
5694 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5695 AccAXRrl1(x); // BCCCCCCD:D000000B
5696 AccAXRrl1(x); // BBCCCCCC:DD000000
5698 case 7 : // a:x <<= 7
5699 emitcode("anl","a,#0x%02x",
5700 SRMask[shCount]); // 0000000B:CCCCCCCD
5701 emitcode("mov","c,acc.0"); // c = B
5702 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5703 AccAXRrl1(x); // BCCCCCCC:D0000000
5713 /*-----------------------------------------------------------------*/
5714 /* AccAXRsh - right shift a:x known count (0..7) */
5715 /*-----------------------------------------------------------------*/
5716 static void AccAXRsh (char *x, int shCount)
5723 AccAXRrl1(x); // 0->a:x
5727 AccAXRrl1(x); // 0->a:x
5729 AccAXRrl1(x); // 0->a:x
5733 case 5 : // AAAAABBB:CCCCCDDD = a:x
5734 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5735 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5736 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5737 emitcode("anl","a,#0x%02x",
5738 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5739 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5740 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5741 emitcode("anl","a,#0x%02x",
5742 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5743 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5744 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5745 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5747 case 6 : // AABBBBBB:CCDDDDDD
5748 emitcode("mov","c,acc.7");
5749 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5750 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5751 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5752 emitcode("anl","a,#0x%02x",
5753 SRMask[shCount]); // 000000AA:BBBBBBCC
5755 case 7 : // ABBBBBBB:CDDDDDDD
5756 emitcode("mov","c,acc.7"); // c = A
5757 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5758 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5759 emitcode("anl","a,#0x%02x",
5760 SRMask[shCount]); // 0000000A:BBBBBBBC
5770 /*-----------------------------------------------------------------*/
5771 /* AccAXRshS - right shift signed a:x known count (0..7) */
5772 /*-----------------------------------------------------------------*/
5773 static void AccAXRshS (char *x, int shCount)
5780 emitcode("mov","c,acc.7");
5781 AccAXRrl1(x); // s->a:x
5784 emitcode("mov","c,acc.7");
5785 AccAXRrl1(x); // s->a:x
5786 emitcode("mov","c,acc.7");
5787 AccAXRrl1(x); // s->a:x
5791 case 5 : // AAAAABBB:CCCCCDDD = a:x
5792 tlbl = newiTempLabel(NULL);
5793 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5794 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5795 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5796 emitcode("anl","a,#0x%02x",
5797 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5798 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5799 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5800 emitcode("anl","a,#0x%02x",
5801 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5802 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5803 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5804 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5805 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5806 emitcode("orl","a,#0x%02x",
5807 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5808 emitcode("","%05d$:",tlbl->key+100);
5809 break; // SSSSAAAA:BBBCCCCC
5810 case 6 : // AABBBBBB:CCDDDDDD
5811 tlbl = newiTempLabel(NULL);
5812 emitcode("mov","c,acc.7");
5813 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5814 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5815 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5816 emitcode("anl","a,#0x%02x",
5817 SRMask[shCount]); // 000000AA:BBBBBBCC
5818 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5819 emitcode("orl","a,#0x%02x",
5820 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5821 emitcode("","%05d$:",tlbl->key+100);
5823 case 7 : // ABBBBBBB:CDDDDDDD
5824 tlbl = newiTempLabel(NULL);
5825 emitcode("mov","c,acc.7"); // c = A
5826 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5827 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5828 emitcode("anl","a,#0x%02x",
5829 SRMask[shCount]); // 0000000A:BBBBBBBC
5830 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5831 emitcode("orl","a,#0x%02x",
5832 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5833 emitcode("","%05d$:",tlbl->key+100);
5843 /*-----------------------------------------------------------------*/
5844 /* shiftL2Left2Result - shift left two bytes from left to result */
5845 /*-----------------------------------------------------------------*/
5846 static void shiftL2Left2Result (operand *left, int offl,
5847 operand *result, int offr, int shCount)
5849 if(sameRegs(AOP(result), AOP(left)) &&
5850 ((offl + MSB16) == offr)){
5851 /* don't crash result[offr] */
5852 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5853 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5855 movLeft2Result(left,offl, result, offr, 0);
5856 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5858 /* ax << shCount (x = lsb(result))*/
5859 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5860 aopPut(AOP(result),"a",offr+MSB16);
5866 /*-----------------------------------------------------------------*/
5867 /* shiftR2Left2Result - shift right two bytes from left to result */
5868 /*-----------------------------------------------------------------*/
5869 static void shiftR2Left2Result (operand *left, int offl,
5870 operand *result, int offr,
5871 int shCount, int sign)
5873 if(sameRegs(AOP(result), AOP(left)) &&
5874 ((offl + MSB16) == offr)){
5875 /* don't crash result[offr] */
5876 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5877 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5879 movLeft2Result(left,offl, result, offr, 0);
5880 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5882 /* a:x >> shCount (x = lsb(result))*/
5884 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5886 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5887 if(getDataSize(result) > 1)
5888 aopPut(AOP(result),"a",offr+MSB16);
5894 /*-----------------------------------------------------------------*/
5895 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5896 /*-----------------------------------------------------------------*/
5897 static void shiftLLeftOrResult (operand *left, int offl,
5898 operand *result, int offr, int shCount)
5900 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5901 /* shift left accumulator */
5903 /* or with result */
5904 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5905 /* back to result */
5906 aopPut(AOP(result),"a",offr);
5912 /*-----------------------------------------------------------------*/
5913 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5914 /*-----------------------------------------------------------------*/
5915 static void shiftRLeftOrResult (operand *left, int offl,
5916 operand *result, int offr, int shCount)
5918 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5919 /* shift right accumulator */
5921 /* or with result */
5922 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5923 /* back to result */
5924 aopPut(AOP(result),"a",offr);
5930 /*-----------------------------------------------------------------*/
5931 /* genlshOne - left shift a one byte quantity by known count */
5932 /*-----------------------------------------------------------------*/
5933 static void genlshOne (operand *result, operand *left, int shCount)
5935 D(emitcode(";", "genlshOne "););
5936 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5942 /*-----------------------------------------------------------------*/
5943 /* genlshTwo - left shift two bytes by known amount != 0 */
5944 /*-----------------------------------------------------------------*/
5945 static void genlshTwo (operand *result,operand *left, int shCount)
5949 D(emitcode(";", "genlshTwo "););
5951 size = getDataSize(result);
5953 /* if shCount >= 8 */
5959 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5961 movLeft2Result(left, LSB, result, MSB16, 0);
5963 aopPut(AOP(result),zero,LSB);
5966 /* 1 <= shCount <= 7 */
5969 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5971 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5978 /*-----------------------------------------------------------------*/
5979 /* shiftLLong - shift left one long from left to result */
5980 /* offl = LSB or MSB16 */
5981 /*-----------------------------------------------------------------*/
5982 static void shiftLLong (operand *left, operand *result, int offr )
5985 int size = AOP_SIZE(result);
5987 if(size >= LSB+offr){
5988 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5990 emitcode("add","a,acc");
5991 if (sameRegs(AOP(left),AOP(result)) &&
5992 size >= MSB16+offr && offr != LSB )
5993 emitcode("xch","a,%s",
5994 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5996 aopPut(AOP(result),"a",LSB+offr);
5999 if(size >= MSB16+offr){
6000 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6001 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
6004 emitcode("rlc","a");
6005 if (sameRegs(AOP(left),AOP(result)) &&
6006 size >= MSB24+offr && offr != LSB)
6007 emitcode("xch","a,%s",
6008 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
6010 aopPut(AOP(result),"a",MSB16+offr);
6013 if(size >= MSB24+offr){
6014 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6015 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
6018 emitcode("rlc","a");
6019 if (sameRegs(AOP(left),AOP(result)) &&
6020 size >= MSB32+offr && offr != LSB )
6021 emitcode("xch","a,%s",
6022 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
6024 aopPut(AOP(result),"a",MSB24+offr);
6027 if(size > MSB32+offr){
6028 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6029 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
6032 emitcode("rlc","a");
6033 aopPut(AOP(result),"a",MSB32+offr);
6036 aopPut(AOP(result),zero,LSB);
6042 /*-----------------------------------------------------------------*/
6043 /* genlshFour - shift four byte by a known amount != 0 */
6044 /*-----------------------------------------------------------------*/
6045 static void genlshFour (operand *result, operand *left, int shCount)
6049 D(emitcode(";", "genlshFour "););
6051 size = AOP_SIZE(result);
6053 /* if shifting more that 3 bytes */
6054 if (shCount >= 24 ) {
6057 /* lowest order of left goes to the highest
6058 order of the destination */
6059 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6061 movLeft2Result(left, LSB, result, MSB32, 0);
6062 aopPut(AOP(result),zero,LSB);
6063 aopPut(AOP(result),zero,MSB16);
6064 aopPut(AOP(result),zero,MSB32);
6068 /* more than two bytes */
6069 else if ( shCount >= 16 ) {
6070 /* lower order two bytes goes to higher order two bytes */
6072 /* if some more remaining */
6074 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6076 movLeft2Result(left, MSB16, result, MSB32, 0);
6077 movLeft2Result(left, LSB, result, MSB24, 0);
6079 aopPut(AOP(result),zero,MSB16);
6080 aopPut(AOP(result),zero,LSB);
6084 /* if more than 1 byte */
6085 else if ( shCount >= 8 ) {
6086 /* lower order three bytes goes to higher order three bytes */
6090 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6092 movLeft2Result(left, LSB, result, MSB16, 0);
6094 else{ /* size = 4 */
6096 movLeft2Result(left, MSB24, result, MSB32, 0);
6097 movLeft2Result(left, MSB16, result, MSB24, 0);
6098 movLeft2Result(left, LSB, result, MSB16, 0);
6099 aopPut(AOP(result),zero,LSB);
6101 else if(shCount == 1)
6102 shiftLLong(left, result, MSB16);
6104 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6105 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6106 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6107 aopPut(AOP(result),zero,LSB);
6112 /* 1 <= shCount <= 7 */
6113 else if(shCount <= 2){
6114 shiftLLong(left, result, LSB);
6116 shiftLLong(result, result, LSB);
6118 /* 3 <= shCount <= 7, optimize */
6120 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6121 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6122 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6129 /*-----------------------------------------------------------------*/
6130 /* genLeftShiftLiteral - left shifting by known count */
6131 /*-----------------------------------------------------------------*/
6132 static void genLeftShiftLiteral (operand *left,
6137 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6140 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
6142 freeAsmop(right,NULL,ic,TRUE);
6144 aopOp(left,ic,FALSE, FALSE);
6145 aopOp(result,ic,FALSE, TRUE);
6147 size = getSize(operandType(result));
6150 emitcode("; shift left ","result %d, left %d",size,
6154 /* I suppose that the left size >= result size */
6157 movLeft2Result(left, size, result, size, 0);
6161 else if(shCount >= (size * 8))
6163 aopPut(AOP(result),zero,size);
6167 genlshOne (result,left,shCount);
6171 case 3: /* bug: this is for generic pointers, I bet. */
6172 genlshTwo (result,left,shCount);
6176 genlshFour (result,left,shCount);
6180 freeAsmop(left,NULL,ic,TRUE);
6181 freeAsmop(result,NULL,ic,TRUE);
6185 /*-----------------------------------------------------------------*/
6186 /* genLeftShift - generates code for left shifting */
6187 /*-----------------------------------------------------------------*/
6188 static void genLeftShift (iCode *ic)
6190 operand *left,*right, *result;
6193 symbol *tlbl , *tlbl1;
6195 D(emitcode(";", "genLeftShift "););
6197 right = IC_RIGHT(ic);
6199 result = IC_RESULT(ic);
6201 aopOp(right,ic,FALSE, FALSE);
6204 /* if the shift count is known then do it
6205 as efficiently as possible */
6206 if (AOP_TYPE(right) == AOP_LIT) {
6207 genLeftShiftLiteral (left,right,result,ic);
6212 /* shift count is unknown then we have to form
6213 a loop get the loop count in B : Note: we take
6214 only the lower order byte since shifting
6215 more that 32 bits make no sense anyway, ( the
6216 largest size of an object can be only 32 bits ) */
6218 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6219 emitcode("inc","b");
6220 freeAsmop (right,NULL,ic,TRUE);
6221 aopOp(left,ic,FALSE, FALSE);
6222 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6224 /* now move the left to the result if they are not the
6226 if (!sameRegs(AOP(left),AOP(result)) &&
6227 AOP_SIZE(result) > 1) {
6229 size = AOP_SIZE(result);
6231 _startLazyDPSEvaluation();
6233 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6234 if (*l == '@' && (IS_AOP_PREG(result))) {
6236 emitcode("mov","a,%s",l);
6237 aopPut(AOP(result),"a",offset);
6239 aopPut(AOP(result),l,offset);
6242 _endLazyDPSEvaluation();
6245 tlbl = newiTempLabel(NULL);
6246 size = AOP_SIZE(result);
6248 tlbl1 = newiTempLabel(NULL);
6250 /* if it is only one byte then */
6252 symbol *tlbl1 = newiTempLabel(NULL);
6254 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6256 emitcode("sjmp","%05d$",tlbl1->key+100);
6257 emitcode("","%05d$:",tlbl->key+100);
6258 emitcode("add","a,acc");
6259 emitcode("","%05d$:",tlbl1->key+100);
6260 emitcode("djnz","b,%05d$",tlbl->key+100);
6261 aopPut(AOP(result),"a",0);
6265 reAdjustPreg(AOP(result));
6267 emitcode("sjmp","%05d$",tlbl1->key+100);
6268 emitcode("","%05d$:",tlbl->key+100);
6269 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6271 emitcode("add","a,acc");
6272 aopPut(AOP(result),"a",offset++);
6273 _startLazyDPSEvaluation();
6275 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6277 emitcode("rlc","a");
6278 aopPut(AOP(result),"a",offset++);
6280 _endLazyDPSEvaluation();
6281 reAdjustPreg(AOP(result));
6283 emitcode("","%05d$:",tlbl1->key+100);
6284 emitcode("djnz","b,%05d$",tlbl->key+100);
6286 freeAsmop(left,NULL,ic,TRUE);
6287 freeAsmop(result,NULL,ic,TRUE);
6292 /*-----------------------------------------------------------------*/
6293 /* genrshOne - right shift a one byte quantity by known count */
6294 /*-----------------------------------------------------------------*/
6295 static void genrshOne (operand *result, operand *left,
6296 int shCount, int sign)
6298 D(emitcode(";", "genrshOne"););
6299 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6305 /*-----------------------------------------------------------------*/
6306 /* genrshTwo - right shift two bytes by known amount != 0 */
6307 /*-----------------------------------------------------------------*/
6308 static void genrshTwo (operand *result,operand *left,
6309 int shCount, int sign)
6311 D(emitcode(";", "genrshTwo"););
6313 /* if shCount >= 8 */
6317 shiftR1Left2Result(left, MSB16, result, LSB,
6320 movLeft2Result(left, MSB16, result, LSB, sign);
6321 addSign(result, MSB16, sign);
6324 /* 1 <= shCount <= 7 */
6326 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6332 /*-----------------------------------------------------------------*/
6333 /* shiftRLong - shift right one long from left to result */
6334 /* offl = LSB or MSB16 */
6335 /*-----------------------------------------------------------------*/
6336 static void shiftRLong (operand *left, int offl,
6337 operand *result, int sign)
6340 emitcode("clr","c");
6341 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6343 emitcode("mov","c,acc.7");
6344 emitcode("rrc","a");
6345 aopPut(AOP(result),"a",MSB32-offl);
6347 /* add sign of "a" */
6348 addSign(result, MSB32, sign);
6350 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6351 emitcode("rrc","a");
6352 aopPut(AOP(result),"a",MSB24-offl);
6354 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6355 emitcode("rrc","a");
6356 aopPut(AOP(result),"a",MSB16-offl);
6359 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6360 emitcode("rrc","a");
6361 aopPut(AOP(result),"a",LSB);
6368 /*-----------------------------------------------------------------*/
6369 /* genrshFour - shift four byte by a known amount != 0 */
6370 /*-----------------------------------------------------------------*/
6371 static void genrshFour (operand *result, operand *left,
6372 int shCount, int sign)
6374 D(emitcode(";", "genrshFour"););
6376 /* if shifting more that 3 bytes */
6377 if(shCount >= 24 ) {
6380 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6382 movLeft2Result(left, MSB32, result, LSB, sign);
6383 addSign(result, MSB16, sign);
6385 else if(shCount >= 16){
6388 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6390 movLeft2Result(left, MSB24, result, LSB, 0);
6391 movLeft2Result(left, MSB32, result, MSB16, sign);
6393 addSign(result, MSB24, sign);
6395 else if(shCount >= 8){
6398 shiftRLong(left, MSB16, result, sign);
6399 else if(shCount == 0){
6400 movLeft2Result(left, MSB16, result, LSB, 0);
6401 movLeft2Result(left, MSB24, result, MSB16, 0);
6402 movLeft2Result(left, MSB32, result, MSB24, sign);
6403 addSign(result, MSB32, sign);
6406 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6407 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6408 /* the last shift is signed */
6409 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6410 addSign(result, MSB32, sign);
6413 else{ /* 1 <= shCount <= 7 */
6415 shiftRLong(left, LSB, result, sign);
6417 shiftRLong(result, LSB, result, sign);
6420 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6421 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6422 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6430 /*-----------------------------------------------------------------*/
6431 /* genRightShiftLiteral - right shifting by known count */
6432 /*-----------------------------------------------------------------*/
6433 static void genRightShiftLiteral (operand *left,
6439 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6442 D(emitcode(";", "genRightShiftLiteral"););
6444 freeAsmop(right,NULL,ic,TRUE);
6446 aopOp(left,ic,FALSE, FALSE);
6447 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6450 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6454 size = getDataSize(left);
6455 /* test the LEFT size !!! */
6457 /* I suppose that the left size >= result size */
6459 size = getDataSize(result);
6461 movLeft2Result(left, size, result, size, 0);
6464 else if(shCount >= (size * 8)){
6466 /* get sign in acc.7 */
6467 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6468 addSign(result, LSB, sign);
6472 genrshOne (result,left,shCount,sign);
6476 genrshTwo (result,left,shCount,sign);
6480 genrshFour (result,left,shCount,sign);
6486 freeAsmop(left,NULL,ic,TRUE);
6487 freeAsmop(result,NULL,ic,TRUE);
6492 /*-----------------------------------------------------------------*/
6493 /* genSignedRightShift - right shift of signed number */
6494 /*-----------------------------------------------------------------*/
6495 static void genSignedRightShift (iCode *ic)
6497 operand *right, *left, *result;
6500 symbol *tlbl, *tlbl1 ;
6502 D(emitcode(";", "genSignedRightShift "););
6504 /* we do it the hard way put the shift count in b
6505 and loop thru preserving the sign */
6507 right = IC_RIGHT(ic);
6509 result = IC_RESULT(ic);
6511 aopOp(right,ic,FALSE, FALSE);
6514 if ( AOP_TYPE(right) == AOP_LIT) {
6515 genRightShiftLiteral (left,right,result,ic,1);
6519 /* shift count is unknown then we have to form
6520 a loop get the loop count in B : Note: we take
6521 only the lower order byte since shifting
6522 more that 32 bits make no sense anyway, ( the
6523 largest size of an object can be only 32 bits ) */
6525 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6526 emitcode("inc","b");
6527 freeAsmop (right,NULL,ic,TRUE);
6528 aopOp(left,ic,FALSE, FALSE);
6529 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6531 /* now move the left to the result if they are not the
6533 if (!sameRegs(AOP(left),AOP(result)) &&
6534 AOP_SIZE(result) > 1) {
6536 size = AOP_SIZE(result);
6538 _startLazyDPSEvaluation();
6540 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6541 if (*l == '@' && IS_AOP_PREG(result)) {
6543 emitcode("mov","a,%s",l);
6544 aopPut(AOP(result),"a",offset);
6546 aopPut(AOP(result),l,offset);
6549 _endLazyDPSEvaluation();
6552 /* mov the highest order bit to OVR */
6553 tlbl = newiTempLabel(NULL);
6554 tlbl1= newiTempLabel(NULL);
6556 size = AOP_SIZE(result);
6558 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6559 emitcode("rlc","a");
6560 emitcode("mov","ov,c");
6561 /* if it is only one byte then */
6563 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6565 emitcode("sjmp","%05d$",tlbl1->key+100);
6566 emitcode("","%05d$:",tlbl->key+100);
6567 emitcode("mov","c,ov");
6568 emitcode("rrc","a");
6569 emitcode("","%05d$:",tlbl1->key+100);
6570 emitcode("djnz","b,%05d$",tlbl->key+100);
6571 aopPut(AOP(result),"a",0);
6575 reAdjustPreg(AOP(result));
6576 emitcode("sjmp","%05d$",tlbl1->key+100);
6577 emitcode("","%05d$:",tlbl->key+100);
6578 emitcode("mov","c,ov");
6579 _startLazyDPSEvaluation();
6581 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6583 emitcode("rrc","a");
6584 aopPut(AOP(result),"a",offset--);
6586 _endLazyDPSEvaluation();
6587 reAdjustPreg(AOP(result));
6588 emitcode("","%05d$:",tlbl1->key+100);
6589 emitcode("djnz","b,%05d$",tlbl->key+100);
6592 freeAsmop(left,NULL,ic,TRUE);
6593 freeAsmop(result,NULL,ic,TRUE);
6596 /*-----------------------------------------------------------------*/
6597 /* genRightShift - generate code for right shifting */
6598 /*-----------------------------------------------------------------*/
6599 static void genRightShift (iCode *ic)
6601 operand *right, *left, *result;
6605 symbol *tlbl, *tlbl1 ;
6607 D(emitcode(";", "genRightShift "););
6609 /* if signed then we do it the hard way preserve the
6610 sign bit moving it inwards */
6611 retype = getSpec(operandType(IC_RESULT(ic)));
6613 if (!SPEC_USIGN(retype)) {
6614 genSignedRightShift (ic);
6618 /* signed & unsigned types are treated the same : i.e. the
6619 signed is NOT propagated inwards : quoting from the
6620 ANSI - standard : "for E1 >> E2, is equivalent to division
6621 by 2**E2 if unsigned or if it has a non-negative value,
6622 otherwise the result is implementation defined ", MY definition
6623 is that the sign does not get propagated */
6625 right = IC_RIGHT(ic);
6627 result = IC_RESULT(ic);
6629 aopOp(right,ic,FALSE, FALSE);
6632 /* if the shift count is known then do it
6633 as efficiently as possible */
6634 if (AOP_TYPE(right) == AOP_LIT) {
6635 genRightShiftLiteral (left,right,result,ic, 0);
6640 /* shift count is unknown then we have to form
6641 a loop get the loop count in B : Note: we take
6642 only the lower order byte since shifting
6643 more that 32 bits make no sense anyway, ( the
6644 largest size of an object can be only 32 bits ) */
6646 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6647 emitcode("inc","b");
6648 freeAsmop (right,NULL,ic,TRUE);
6649 aopOp(left,ic,FALSE, FALSE);
6650 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6652 /* now move the left to the result if they are not the
6654 if (!sameRegs(AOP(left),AOP(result)) &&
6655 AOP_SIZE(result) > 1) {
6657 size = AOP_SIZE(result);
6659 _startLazyDPSEvaluation();
6661 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6662 if (*l == '@' && IS_AOP_PREG(result)) {
6664 emitcode("mov","a,%s",l);
6665 aopPut(AOP(result),"a",offset);
6667 aopPut(AOP(result),l,offset);
6670 _endLazyDPSEvaluation();
6673 tlbl = newiTempLabel(NULL);
6674 tlbl1= newiTempLabel(NULL);
6675 size = AOP_SIZE(result);
6678 /* if it is only one byte then */
6680 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6682 emitcode("sjmp","%05d$",tlbl1->key+100);
6683 emitcode("","%05d$:",tlbl->key+100);
6685 emitcode("rrc","a");
6686 emitcode("","%05d$:",tlbl1->key+100);
6687 emitcode("djnz","b,%05d$",tlbl->key+100);
6688 aopPut(AOP(result),"a",0);
6692 reAdjustPreg(AOP(result));
6693 emitcode("sjmp","%05d$",tlbl1->key+100);
6694 emitcode("","%05d$:",tlbl->key+100);
6696 _startLazyDPSEvaluation();
6698 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6700 emitcode("rrc","a");
6701 aopPut(AOP(result),"a",offset--);
6703 _endLazyDPSEvaluation();
6704 reAdjustPreg(AOP(result));
6706 emitcode("","%05d$:",tlbl1->key+100);
6707 emitcode("djnz","b,%05d$",tlbl->key+100);
6710 freeAsmop(left,NULL,ic,TRUE);
6711 freeAsmop(result,NULL,ic,TRUE);
6714 /*-----------------------------------------------------------------*/
6715 /* genUnpackBits - generates code for unpacking bits */
6716 /*-----------------------------------------------------------------*/
6717 static void genUnpackBits (operand *result, char *rname, int ptype)
6724 D(emitcode(";", "genUnpackBits "););
6726 etype = getSpec(operandType(result));
6728 /* read the first byte */
6733 emitcode("mov","a,@%s",rname);
6737 emitcode("movx","a,@%s",rname);
6741 emitcode("movx","a,@dptr");
6745 emitcode("clr","a");
6746 emitcode("movc","a","@a+dptr");
6750 emitcode("lcall","__gptrget");
6754 /* if we have bitdisplacement then it fits */
6755 /* into this byte completely or if length is */
6756 /* less than a byte */
6757 if ((shCnt = SPEC_BSTR(etype)) ||
6758 (SPEC_BLEN(etype) <= 8)) {
6760 /* shift right acc */
6763 emitcode("anl","a,#0x%02x",
6764 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6765 aopPut(AOP(result),"a",offset);
6769 /* bit field did not fit in a byte */
6770 rlen = SPEC_BLEN(etype) - 8;
6771 aopPut(AOP(result),"a",offset++);
6778 emitcode("inc","%s",rname);
6779 emitcode("mov","a,@%s",rname);
6783 emitcode("inc","%s",rname);
6784 emitcode("movx","a,@%s",rname);
6788 emitcode("inc","dptr");
6789 emitcode("movx","a,@dptr");
6793 emitcode("clr","a");
6794 emitcode("inc","dptr");
6795 emitcode("movc","a","@a+dptr");
6799 emitcode("inc","dptr");
6800 emitcode("lcall","__gptrget");
6805 /* if we are done */
6809 aopPut(AOP(result),"a",offset++);
6814 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6815 aopPut(AOP(result),"a",offset);
6822 /*-----------------------------------------------------------------*/
6823 /* genDataPointerGet - generates code when ptr offset is known */
6824 /*-----------------------------------------------------------------*/
6825 static void genDataPointerGet (operand *left,
6831 int size , offset = 0;
6832 aopOp(result,ic,TRUE, FALSE);
6834 /* get the string representation of the name */
6835 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6836 size = AOP_SIZE(result);
6837 _startLazyDPSEvaluation();
6840 sprintf(buffer,"(%s + %d)",l+1,offset);
6842 sprintf(buffer,"%s",l+1);
6843 aopPut(AOP(result),buffer,offset++);
6845 _endLazyDPSEvaluation();
6847 freeAsmop(left,NULL,ic,TRUE);
6848 freeAsmop(result,NULL,ic,TRUE);
6851 /*-----------------------------------------------------------------*/
6852 /* genNearPointerGet - emitcode for near pointer fetch */
6853 /*-----------------------------------------------------------------*/
6854 static void genNearPointerGet (operand *left,
6861 sym_link *rtype, *retype, *letype;
6862 sym_link *ltype = operandType(left);
6865 rtype = operandType(result);
6866 retype= getSpec(rtype);
6867 letype= getSpec(ltype);
6869 aopOp(left,ic,FALSE, FALSE);
6871 /* if left is rematerialisable and
6872 result is not bit variable type and
6873 the left is pointer to data space i.e
6874 lower 128 bytes of space */
6875 if (AOP_TYPE(left) == AOP_IMMD &&
6876 !IS_BITVAR(retype) &&
6877 !IS_BITVAR(letype) &&
6878 DCL_TYPE(ltype) == POINTER) {
6879 genDataPointerGet (left,result,ic);
6883 /* if the value is already in a pointer register
6884 then don't need anything more */
6885 if (!AOP_INPREG(AOP(left))) {
6886 /* otherwise get a free pointer register */
6888 preg = getFreePtr(ic,&aop,FALSE);
6889 emitcode("mov","%s,%s",
6891 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6892 rname = preg->name ;
6894 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6896 freeAsmop(left,NULL,ic,TRUE);
6897 aopOp (result,ic,FALSE, FALSE);
6899 /* if bitfield then unpack the bits */
6900 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6901 genUnpackBits (result,rname,POINTER);
6903 /* we have can just get the values */
6904 int size = AOP_SIZE(result);
6908 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6910 emitcode("mov","a,@%s",rname);
6911 aopPut(AOP(result),"a",offset);
6913 sprintf(buffer,"@%s",rname);
6914 aopPut(AOP(result),buffer,offset);
6918 emitcode("inc","%s",rname);
6922 /* now some housekeeping stuff */
6924 /* we had to allocate for this iCode */
6925 freeAsmop(NULL,aop,ic,TRUE);
6927 /* we did not allocate which means left
6928 already in a pointer register, then
6929 if size > 0 && this could be used again
6930 we have to point it back to where it
6932 if (AOP_SIZE(result) > 1 &&
6933 !OP_SYMBOL(left)->remat &&
6934 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6936 int size = AOP_SIZE(result) - 1;
6938 emitcode("dec","%s",rname);
6943 freeAsmop(result,NULL,ic,TRUE);
6947 /*-----------------------------------------------------------------*/
6948 /* genPagedPointerGet - emitcode for paged pointer fetch */
6949 /*-----------------------------------------------------------------*/
6950 static void genPagedPointerGet (operand *left,
6957 sym_link *rtype, *retype, *letype;
6959 rtype = operandType(result);
6960 retype= getSpec(rtype);
6961 letype= getSpec(operandType(left));
6962 aopOp(left,ic,FALSE, FALSE);
6964 /* if the value is already in a pointer register
6965 then don't need anything more */
6966 if (!AOP_INPREG(AOP(left))) {
6967 /* otherwise get a free pointer register */
6969 preg = getFreePtr(ic,&aop,FALSE);
6970 emitcode("mov","%s,%s",
6972 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6973 rname = preg->name ;
6975 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6977 freeAsmop(left,NULL,ic,TRUE);
6978 aopOp (result,ic,FALSE, FALSE);
6980 /* if bitfield then unpack the bits */
6981 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6982 genUnpackBits (result,rname,PPOINTER);
6984 /* we have can just get the values */
6985 int size = AOP_SIZE(result);
6990 emitcode("movx","a,@%s",rname);
6991 aopPut(AOP(result),"a",offset);
6996 emitcode("inc","%s",rname);
7000 /* now some housekeeping stuff */
7002 /* we had to allocate for this iCode */
7003 freeAsmop(NULL,aop,ic,TRUE);
7005 /* we did not allocate which means left
7006 already in a pointer register, then
7007 if size > 0 && this could be used again
7008 we have to point it back to where it
7010 if (AOP_SIZE(result) > 1 &&
7011 !OP_SYMBOL(left)->remat &&
7012 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7014 int size = AOP_SIZE(result) - 1;
7016 emitcode("dec","%s",rname);
7021 freeAsmop(result,NULL,ic,TRUE);
7026 /*-----------------------------------------------------------------*/
7027 /* genFarPointerGet - gget value from far space */
7028 /*-----------------------------------------------------------------*/
7029 static void genFarPointerGet (operand *left,
7030 operand *result, iCode *ic)
7033 sym_link *retype = getSpec(operandType(result));
7034 sym_link *letype = getSpec(operandType(left));
7035 D(emitcode(";", "genFarPointerGet"););
7037 aopOp(left,ic,FALSE, FALSE);
7039 /* if the operand is already in dptr
7040 then we do nothing else we move the value to dptr */
7041 if (AOP_TYPE(left) != AOP_STR) {
7042 /* if this is remateriazable */
7043 if (AOP_TYPE(left) == AOP_IMMD)
7045 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7049 /* we need to get it byte by byte */
7050 _startLazyDPSEvaluation();
7051 if (AOP_TYPE(left) != AOP_DPTR)
7053 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7054 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7055 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7059 /* We need to generate a load to DPTR indirect through DPTR. */
7060 D(emitcode(";", "genFarPointerGet -- indirection special case."););
7061 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7062 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7063 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7064 emitcode("pop", "dph");
7065 emitcode("pop", "dpl");
7067 _endLazyDPSEvaluation();
7070 /* so dptr know contains the address */
7071 freeAsmop(left,NULL,ic,TRUE);
7072 aopOp(result,ic,FALSE, TRUE);
7074 /* if bit then unpack */
7075 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7076 genUnpackBits(result,"dptr",FPOINTER);
7078 size = AOP_SIZE(result);
7081 _startLazyDPSEvaluation();
7087 emitcode("movx","a,@dptr");
7089 emitcode("inc","dptr");
7091 aopPut(AOP(result),"a",offset++);
7093 _endLazyDPSEvaluation();
7096 freeAsmop(result,NULL,ic,TRUE);
7099 /*-----------------------------------------------------------------*/
7100 /* emitcodePointerGet - gget value from code space */
7101 /*-----------------------------------------------------------------*/
7102 static void emitcodePointerGet (operand *left,
7103 operand *result, iCode *ic)
7106 sym_link *retype = getSpec(operandType(result));
7108 aopOp(left,ic,FALSE, FALSE);
7110 /* if the operand is already in dptr
7111 then we do nothing else we move the value to dptr */
7112 if (AOP_TYPE(left) != AOP_STR) {
7113 /* if this is remateriazable */
7114 if (AOP_TYPE(left) == AOP_IMMD)
7116 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7119 { /* we need to get it byte by byte */
7120 _startLazyDPSEvaluation();
7121 if (AOP_TYPE(left) != AOP_DPTR)
7123 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7124 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7125 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7129 /* We need to generate a load to DPTR indirect through DPTR. */
7130 D(emitcode(";", "gencodePointerGet -- indirection special case."););
7131 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7132 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7133 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7134 emitcode("pop", "dph");
7135 emitcode("pop", "dpl");
7137 _endLazyDPSEvaluation();
7140 /* so dptr know contains the address */
7141 freeAsmop(left,NULL,ic,TRUE);
7142 aopOp(result,ic,FALSE, TRUE);
7144 /* if bit then unpack */
7145 if (IS_BITVAR(retype))
7146 genUnpackBits(result,"dptr",CPOINTER);
7148 size = AOP_SIZE(result);
7151 _startLazyDPSEvaluation();
7157 emitcode("clr","a");
7158 emitcode("movc","a,@a+dptr");
7160 emitcode("inc","dptr");
7161 aopPut(AOP(result),"a",offset++);
7163 _endLazyDPSEvaluation();
7166 freeAsmop(result,NULL,ic,TRUE);
7169 /*-----------------------------------------------------------------*/
7170 /* genGenPointerGet - gget value from generic pointer space */
7171 /*-----------------------------------------------------------------*/
7172 static void genGenPointerGet (operand *left,
7173 operand *result, iCode *ic)
7176 sym_link *retype = getSpec(operandType(result));
7177 sym_link *letype = getSpec(operandType(left));
7179 aopOp(left,ic,FALSE, TRUE);
7181 /* if the operand is already in dptr
7182 then we do nothing else we move the value to dptr */
7183 if (AOP_TYPE(left) != AOP_STR) {
7184 /* if this is remateriazable */
7185 if (AOP_TYPE(left) == AOP_IMMD) {
7186 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7187 emitcode("mov","b,#%d",pointerCode(retype));
7189 else { /* we need to get it byte by byte */
7190 _startLazyDPSEvaluation();
7191 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7192 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7193 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7194 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7195 _endLazyDPSEvaluation();
7198 /* so dptr know contains the address */
7199 freeAsmop(left,NULL,ic,TRUE);
7200 aopOp(result,ic,FALSE, TRUE);
7202 /* if bit then unpack */
7203 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7204 genUnpackBits(result,"dptr",GPOINTER);
7206 size = AOP_SIZE(result);
7210 emitcode("lcall","__gptrget");
7211 aopPut(AOP(result),"a",offset++);
7213 emitcode("inc","dptr");
7217 freeAsmop(result,NULL,ic,TRUE);
7220 /*-----------------------------------------------------------------*/
7221 /* genPointerGet - generate code for pointer get */
7222 /*-----------------------------------------------------------------*/
7223 static void genPointerGet (iCode *ic)
7225 operand *left, *result ;
7226 sym_link *type, *etype;
7229 D(emitcode(";", "genPointerGet "););
7232 result = IC_RESULT(ic) ;
7234 /* depending on the type of pointer we need to
7235 move it to the correct pointer register */
7236 type = operandType(left);
7237 etype = getSpec(type);
7238 /* if left is of type of pointer then it is simple */
7239 if (IS_PTR(type) && !IS_FUNC(type->next))
7240 p_type = DCL_TYPE(type);
7242 /* we have to go by the storage class */
7243 p_type = PTR_TYPE(SPEC_OCLS(etype));
7246 /* now that we have the pointer type we assign
7247 the pointer values */
7252 genNearPointerGet (left,result,ic);
7256 genPagedPointerGet(left,result,ic);
7260 genFarPointerGet (left,result,ic);
7264 emitcodePointerGet (left,result,ic);
7268 genGenPointerGet (left,result,ic);
7274 /*-----------------------------------------------------------------*/
7275 /* genPackBits - generates code for packed bit storage */
7276 /*-----------------------------------------------------------------*/
7277 static void genPackBits (sym_link *etype ,
7279 char *rname, int p_type)
7287 blen = SPEC_BLEN(etype);
7288 bstr = SPEC_BSTR(etype);
7290 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7293 /* if the bit lenth is less than or */
7294 /* it exactly fits a byte then */
7295 if (SPEC_BLEN(etype) <= 8 ) {
7296 shCount = SPEC_BSTR(etype) ;
7298 /* shift left acc */
7301 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7306 emitcode ("mov","b,a");
7307 emitcode("mov","a,@%s",rname);
7311 emitcode ("mov","b,a");
7312 emitcode("movx","a,@dptr");
7316 emitcode ("push","b");
7317 emitcode ("push","acc");
7318 emitcode ("lcall","__gptrget");
7319 emitcode ("pop","b");
7323 emitcode ("anl","a,#0x%02x",(unsigned char)
7324 ((unsigned char)(0xFF << (blen+bstr)) |
7325 (unsigned char)(0xFF >> (8-bstr)) ) );
7326 emitcode ("orl","a,b");
7327 if (p_type == GPOINTER)
7328 emitcode("pop","b");
7334 emitcode("mov","@%s,a",rname);
7338 emitcode("movx","@dptr,a");
7342 emitcode("lcall","__gptrput");
7347 if ( SPEC_BLEN(etype) <= 8 )
7350 emitcode("inc","%s",rname);
7351 rLen = SPEC_BLEN(etype) ;
7353 /* now generate for lengths greater than one byte */
7356 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7366 emitcode("mov","@%s,a",rname);
7368 emitcode("mov","@%s,%s",rname,l);
7373 emitcode("movx","@dptr,a");
7378 emitcode("lcall","__gptrput");
7381 emitcode ("inc","%s",rname);
7386 /* last last was not complete */
7388 /* save the byte & read byte */
7391 emitcode ("mov","b,a");
7392 emitcode("mov","a,@%s",rname);
7396 emitcode ("mov","b,a");
7397 emitcode("movx","a,@dptr");
7401 emitcode ("push","b");
7402 emitcode ("push","acc");
7403 emitcode ("lcall","__gptrget");
7404 emitcode ("pop","b");
7408 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << rLen) );
7409 emitcode ("orl","a,b");
7412 if (p_type == GPOINTER)
7413 emitcode("pop","b");
7418 emitcode("mov","@%s,a",rname);
7422 emitcode("movx","@dptr,a");
7426 emitcode("lcall","__gptrput");
7430 /*-----------------------------------------------------------------*/
7431 /* genDataPointerSet - remat pointer to data space */
7432 /*-----------------------------------------------------------------*/
7433 static void genDataPointerSet(operand *right,
7437 int size, offset = 0 ;
7438 char *l, buffer[256];
7440 aopOp(right,ic,FALSE, FALSE);
7442 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7443 size = AOP_SIZE(right);
7446 sprintf(buffer,"(%s + %d)",l+1,offset);
7448 sprintf(buffer,"%s",l+1);
7449 emitcode("mov","%s,%s",buffer,
7450 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7453 freeAsmop(right,NULL,ic,TRUE);
7454 freeAsmop(result,NULL,ic,TRUE);
7457 /*-----------------------------------------------------------------*/
7458 /* genNearPointerSet - emitcode for near pointer put */
7459 /*-----------------------------------------------------------------*/
7460 static void genNearPointerSet (operand *right,
7467 sym_link *retype, *letype;
7468 sym_link *ptype = operandType(result);
7470 retype= getSpec(operandType(right));
7471 letype= getSpec(ptype);
7473 aopOp(result,ic,FALSE, FALSE);
7475 /* if the result is rematerializable &
7476 in data space & not a bit variable */
7477 if (AOP_TYPE(result) == AOP_IMMD &&
7478 DCL_TYPE(ptype) == POINTER &&
7479 !IS_BITVAR(retype) &&
7480 !IS_BITVAR(letype)) {
7481 genDataPointerSet (right,result,ic);
7485 /* if the value is already in a pointer register
7486 then don't need anything more */
7487 if (!AOP_INPREG(AOP(result))) {
7488 /* otherwise get a free pointer register */
7490 preg = getFreePtr(ic,&aop,FALSE);
7491 emitcode("mov","%s,%s",
7493 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7494 rname = preg->name ;
7496 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7498 freeAsmop(result,NULL,ic,TRUE);
7499 aopOp (right,ic,FALSE, FALSE);
7501 /* if bitfield then unpack the bits */
7502 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7503 genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
7505 /* we have can just get the values */
7506 int size = AOP_SIZE(right);
7510 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7513 emitcode("mov","@%s,a",rname);
7515 emitcode("mov","@%s,%s",rname,l);
7517 emitcode("inc","%s",rname);
7522 /* now some housekeeping stuff */
7524 /* we had to allocate for this iCode */
7525 freeAsmop(NULL,aop,ic,TRUE);
7527 /* we did not allocate which means left
7528 already in a pointer register, then
7529 if size > 0 && this could be used again
7530 we have to point it back to where it
7532 if (AOP_SIZE(right) > 1 &&
7533 !OP_SYMBOL(result)->remat &&
7534 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7536 int size = AOP_SIZE(right) - 1;
7538 emitcode("dec","%s",rname);
7543 freeAsmop(right,NULL,ic,TRUE);
7548 /*-----------------------------------------------------------------*/
7549 /* genPagedPointerSet - emitcode for Paged pointer put */
7550 /*-----------------------------------------------------------------*/
7551 static void genPagedPointerSet (operand *right,
7558 sym_link *retype, *letype;
7560 retype= getSpec(operandType(right));
7561 letype= getSpec(operandType(result));
7563 aopOp(result,ic,FALSE, FALSE);
7565 /* if the value is already in a pointer register
7566 then don't need anything more */
7567 if (!AOP_INPREG(AOP(result))) {
7568 /* otherwise get a free pointer register */
7570 preg = getFreePtr(ic,&aop,FALSE);
7571 emitcode("mov","%s,%s",
7573 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7574 rname = preg->name ;
7576 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7578 freeAsmop(result,NULL,ic,TRUE);
7579 aopOp (right,ic,FALSE, FALSE);
7581 /* if bitfield then unpack the bits */
7582 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7583 genPackBits ((IS_BITVAR(retype) ? retype : letype) ,right,rname,PPOINTER);
7585 /* we have can just get the values */
7586 int size = AOP_SIZE(right);
7590 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7593 emitcode("movx","@%s,a",rname);
7596 emitcode("inc","%s",rname);
7602 /* now some housekeeping stuff */
7604 /* we had to allocate for this iCode */
7605 freeAsmop(NULL,aop,ic,TRUE);
7607 /* we did not allocate which means left
7608 already in a pointer register, then
7609 if size > 0 && this could be used again
7610 we have to point it back to where it
7612 if (AOP_SIZE(right) > 1 &&
7613 !OP_SYMBOL(result)->remat &&
7614 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7616 int size = AOP_SIZE(right) - 1;
7618 emitcode("dec","%s",rname);
7623 freeAsmop(right,NULL,ic,TRUE);
7628 /*-----------------------------------------------------------------*/
7629 /* genFarPointerSet - set value from far space */
7630 /*-----------------------------------------------------------------*/
7631 static void genFarPointerSet (operand *right,
7632 operand *result, iCode *ic)
7635 sym_link *retype = getSpec(operandType(right));
7636 sym_link *letype = getSpec(operandType(result));
7638 aopOp(result,ic,FALSE, FALSE);
7640 /* if the operand is already in dptr
7641 then we do nothing else we move the value to dptr */
7642 if (AOP_TYPE(result) != AOP_STR) {
7643 /* if this is remateriazable */
7644 if (AOP_TYPE(result) == AOP_IMMD)
7645 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7648 /* we need to get it byte by byte */
7649 _startLazyDPSEvaluation();
7650 if (AOP_TYPE(result) != AOP_DPTR)
7652 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7653 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7654 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7658 /* We need to generate a load to DPTR indirect through DPTR. */
7659 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7660 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7661 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7662 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7663 emitcode("pop", "dph");
7664 emitcode("pop", "dpl");
7666 _endLazyDPSEvaluation();
7669 /* so dptr know contains the address */
7670 freeAsmop(result,NULL,ic,TRUE);
7671 aopOp(right,ic,FALSE, TRUE);
7673 /* if bit then unpack */
7674 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7675 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",FPOINTER);
7677 size = AOP_SIZE(right);
7680 _startLazyDPSEvaluation();
7682 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7688 emitcode("movx","@dptr,a");
7690 emitcode("inc","dptr");
7692 _endLazyDPSEvaluation();
7695 freeAsmop(right,NULL,ic,TRUE);
7698 /*-----------------------------------------------------------------*/
7699 /* genGenPointerSet - set value from generic pointer space */
7700 /*-----------------------------------------------------------------*/
7701 static void genGenPointerSet (operand *right,
7702 operand *result, iCode *ic)
7705 sym_link *retype = getSpec(operandType(right));
7706 sym_link *letype = getSpec(operandType(result));
7708 aopOp(result,ic,FALSE, TRUE);
7710 /* if the operand is already in dptr
7711 then we do nothing else we move the value to dptr */
7712 if (AOP_TYPE(result) != AOP_STR) {
7713 _startLazyDPSEvaluation();
7714 /* if this is remateriazable */
7715 if (AOP_TYPE(result) == AOP_IMMD) {
7716 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7717 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7719 else { /* we need to get it byte by byte */
7720 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7721 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7722 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7723 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7725 _endLazyDPSEvaluation();
7727 /* so dptr know contains the address */
7728 freeAsmop(result,NULL,ic,TRUE);
7729 aopOp(right,ic,FALSE, TRUE);
7731 /* if bit then unpack */
7732 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7733 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",GPOINTER);
7735 size = AOP_SIZE(right);
7738 _startLazyDPSEvaluation();
7740 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7746 emitcode("lcall","__gptrput");
7748 emitcode("inc","dptr");
7750 _endLazyDPSEvaluation();
7753 freeAsmop(right,NULL,ic,TRUE);
7756 /*-----------------------------------------------------------------*/
7757 /* genPointerSet - stores the value into a pointer location */
7758 /*-----------------------------------------------------------------*/
7759 static void genPointerSet (iCode *ic)
7761 operand *right, *result ;
7762 sym_link *type, *etype;
7765 D(emitcode(";", "genPointerSet "););
7767 right = IC_RIGHT(ic);
7768 result = IC_RESULT(ic) ;
7770 /* depending on the type of pointer we need to
7771 move it to the correct pointer register */
7772 type = operandType(result);
7773 etype = getSpec(type);
7774 /* if left is of type of pointer then it is simple */
7775 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7776 p_type = DCL_TYPE(type);
7779 /* we have to go by the storage class */
7780 p_type = PTR_TYPE(SPEC_OCLS(etype));
7783 /* now that we have the pointer type we assign
7784 the pointer values */
7789 genNearPointerSet (right,result,ic);
7793 genPagedPointerSet (right,result,ic);
7797 genFarPointerSet (right,result,ic);
7801 genGenPointerSet (right,result,ic);
7807 /*-----------------------------------------------------------------*/
7808 /* genIfx - generate code for Ifx statement */
7809 /*-----------------------------------------------------------------*/
7810 static void genIfx (iCode *ic, iCode *popIc)
7812 operand *cond = IC_COND(ic);
7815 D(emitcode(";", "genIfx "););
7817 aopOp(cond,ic,FALSE, FALSE);
7819 /* get the value into acc */
7820 if (AOP_TYPE(cond) != AOP_CRY)
7824 /* the result is now in the accumulator */
7825 freeAsmop(cond,NULL,ic,TRUE);
7827 /* if there was something to be popped then do it */
7831 /* if the condition is a bit variable */
7832 if (isbit && IS_ITEMP(cond) &&
7834 genIfxJump(ic,SPIL_LOC(cond)->rname);
7836 if (isbit && !IS_ITEMP(cond))
7837 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7844 /*-----------------------------------------------------------------*/
7845 /* genAddrOf - generates code for address of */
7846 /*-----------------------------------------------------------------*/
7847 static void genAddrOf (iCode *ic)
7849 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7852 D(emitcode(";", "genAddrOf "););
7854 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7856 /* if the operand is on the stack then we
7857 need to get the stack offset of this
7860 /* if it has an offset then we need to compute
7863 emitcode("mov","a,_bp");
7864 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7865 aopPut(AOP(IC_RESULT(ic)),"a",0);
7867 /* we can just move _bp */
7868 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7870 /* fill the result with zero */
7871 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7874 if (options.stack10bit && size < (FPTRSIZE - 1))
7877 "*** warning: pointer to stack var truncated.\n");
7884 if (options.stack10bit && offset == 2)
7886 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7890 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7897 /* object not on stack then we need the name */
7898 size = AOP_SIZE(IC_RESULT(ic));
7902 char s[SDCC_NAME_MAX];
7904 sprintf(s,"#(%s >> %d)",
7908 sprintf(s,"#%s",sym->rname);
7909 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7913 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7917 /*-----------------------------------------------------------------*/
7918 /* genFarFarAssign - assignment when both are in far space */
7919 /*-----------------------------------------------------------------*/
7920 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7922 int size = AOP_SIZE(right);
7929 /* This is a net loss for size == 1, but a big gain
7932 D(emitcode(";", "genFarFarAssign (improved)"););
7934 aopOp(result,ic,TRUE, TRUE);
7936 _startLazyDPSEvaluation();
7940 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7944 _endLazyDPSEvaluation();
7945 freeAsmop(result,NULL,ic,FALSE);
7946 freeAsmop(right,NULL,ic,FALSE);
7951 D(emitcode(";", "genFarFarAssign "););
7953 /* first push the right side on to the stack */
7954 _startLazyDPSEvaluation();
7956 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7958 emitcode ("push","acc");
7961 freeAsmop(right,NULL,ic,FALSE);
7962 /* now assign DPTR to result */
7963 aopOp(result,ic,FALSE, FALSE);
7964 size = AOP_SIZE(result);
7966 emitcode ("pop","acc");
7967 aopPut(AOP(result),"a",--offset);
7969 freeAsmop(result,NULL,ic,FALSE);
7970 _endLazyDPSEvaluation();
7974 /*-----------------------------------------------------------------*/
7975 /* genAssign - generate code for assignment */
7976 /*-----------------------------------------------------------------*/
7977 static void genAssign (iCode *ic)
7979 operand *result, *right;
7981 unsigned long lit = 0L;
7983 D(emitcode(";", "genAssign "););
7985 result = IC_RESULT(ic);
7986 right = IC_RIGHT(ic) ;
7988 /* if they are the same */
7989 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7992 aopOp(right,ic,FALSE, FALSE);
7994 emitcode(";", "genAssign: resultIsFar = %s",
7995 isOperandInFarSpace(result) ?
7998 /* special case both in far space */
7999 if ((AOP_TYPE(right) == AOP_DPTR ||
8000 AOP_TYPE(right) == AOP_DPTR2) &&
8001 /* IS_TRUE_SYMOP(result) && */
8002 isOperandInFarSpace(result)) {
8004 genFarFarAssign (result,right,ic);
8008 aopOp(result,ic,TRUE, FALSE);
8010 /* if they are the same registers */
8011 if (sameRegs(AOP(right),AOP(result)))
8014 /* if the result is a bit */
8015 if (AOP_TYPE(result) == AOP_CRY) {
8017 /* if the right size is a literal then
8018 we know what the value is */
8019 if (AOP_TYPE(right) == AOP_LIT) {
8020 if (((int) operandLitValue(right)))
8021 aopPut(AOP(result),one,0);
8023 aopPut(AOP(result),zero,0);
8027 /* the right is also a bit variable */
8028 if (AOP_TYPE(right) == AOP_CRY) {
8029 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8030 aopPut(AOP(result),"c",0);
8036 aopPut(AOP(result),"a",0);
8040 /* bit variables done */
8042 size = AOP_SIZE(result);
8044 if(AOP_TYPE(right) == AOP_LIT)
8045 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8048 (AOP_TYPE(result) != AOP_REG) &&
8049 (AOP_TYPE(right) == AOP_LIT) &&
8050 !IS_FLOAT(operandType(right))
8051 #ifndef LAZY_DPS_OPT
8057 D(emitcode(";", "Kevin's better literal load code"););
8058 _startLazyDPSEvaluation();
8059 while (size && ((unsigned int)(lit >> (offset*8)) != 0))
8062 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
8067 /* And now fill the rest with zeros. */
8070 emitcode("clr","a");
8074 aopPut(AOP(result), "a", offset++);
8076 _endLazyDPSEvaluation();
8078 emitcode("clr","a");
8080 _startLazyDPSEvaluation();
8083 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
8084 aopPut(AOP(result),"a",size);
8087 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
8090 _endLazyDPSEvaluation();
8095 _startLazyDPSEvaluation();
8099 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8103 _endLazyDPSEvaluation();
8107 freeAsmop (right,NULL,ic,FALSE);
8108 freeAsmop (result,NULL,ic,TRUE);
8111 /*-----------------------------------------------------------------*/
8112 /* genJumpTab - generates code for jump table */
8113 /*-----------------------------------------------------------------*/
8114 static void genJumpTab (iCode *ic)
8119 D(emitcode(";", "genJumpTab "););
8121 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
8122 /* get the condition into accumulator */
8123 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
8125 /* multiply by four! */
8126 emitcode("add","a,acc");
8127 emitcode("add","a,acc");
8128 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8130 jtab = newiTempLabel(NULL);
8131 emitcode("mov","dptr,#%05d$",jtab->key+100);
8132 emitcode("jmp","@a+dptr");
8133 emitcode("","%05d$:",jtab->key+100);
8134 /* now generate the jump labels */
8135 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8136 jtab = setNextItem(IC_JTLABELS(ic)))
8137 emitcode("ljmp","%05d$",jtab->key+100);
8141 /*-----------------------------------------------------------------*/
8142 /* genCast - gen code for casting */
8143 /*-----------------------------------------------------------------*/
8144 static void genCast (iCode *ic)
8146 operand *result = IC_RESULT(ic);
8147 sym_link *ctype = operandType(IC_LEFT(ic));
8148 sym_link *rtype = operandType(IC_RIGHT(ic));
8149 operand *right = IC_RIGHT(ic);
8152 D(emitcode(";", "genCast "););
8154 /* if they are equivalent then do nothing */
8155 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8158 aopOp(right,ic,FALSE, FALSE) ;
8159 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
8161 /* if the result is a bit */
8162 if (AOP_TYPE(result) == AOP_CRY) {
8163 /* if the right size is a literal then
8164 we know what the value is */
8165 if (AOP_TYPE(right) == AOP_LIT) {
8166 if (((int) operandLitValue(right)))
8167 aopPut(AOP(result),one,0);
8169 aopPut(AOP(result),zero,0);
8174 /* the right is also a bit variable */
8175 if (AOP_TYPE(right) == AOP_CRY) {
8176 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8177 aopPut(AOP(result),"c",0);
8183 aopPut(AOP(result),"a",0);
8187 /* if they are the same size : or less */
8188 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8190 /* if they are in the same place */
8191 if (sameRegs(AOP(right),AOP(result)))
8194 /* if they in different places then copy */
8195 size = AOP_SIZE(result);
8197 _startLazyDPSEvaluation();
8200 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8204 _endLazyDPSEvaluation();
8209 /* if the result is of type pointer */
8210 if (IS_PTR(ctype)) {
8213 sym_link *type = operandType(right);
8215 /* pointer to generic pointer */
8216 if (IS_GENPTR(ctype)) {
8221 p_type = DCL_TYPE(type);
8225 #if OLD_CAST_BEHAVIOR
8226 /* KV: we are converting a non-pointer type to
8227 * a generic pointer. This (ifdef'd out) code
8228 * says that the resulting generic pointer
8229 * should have the same class as the storage
8230 * location of the non-pointer variable.
8232 * For example, converting an int (which happens
8233 * to be stored in DATA space) to a pointer results
8234 * in a DATA generic pointer; if the original int
8235 * in XDATA space, so will be the resulting pointer.
8237 * I don't like that behavior, and thus this change:
8238 * all such conversions will be forced to XDATA and
8239 * throw a warning. If you want some non-XDATA
8240 * type, or you want to suppress the warning, you
8241 * must go through an intermediate cast, like so:
8243 * char _generic *gp = (char _xdata *)(intVar);
8245 sym_link *etype = getSpec(type);
8247 /* we have to go by the storage class */
8248 if (SPEC_OCLS(etype) != generic)
8250 p_type = PTR_TYPE(SPEC_OCLS(etype));
8255 /* Converting unknown class (i.e. register variable)
8256 * to generic pointer. This is not good, but
8257 * we'll make a guess (and throw a warning).
8260 werror(W_INT_TO_GEN_PTR_CAST);
8264 /* the first two bytes are known */
8265 size = GPTRSIZE - 1;
8267 _startLazyDPSEvaluation();
8270 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8274 _endLazyDPSEvaluation();
8276 /* the last byte depending on type */
8293 /* this should never happen */
8294 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8295 "got unknown pointer type");
8298 aopPut(AOP(result),l, GPTRSIZE - 1);
8302 /* just copy the pointers */
8303 size = AOP_SIZE(result);
8305 _startLazyDPSEvaluation();
8308 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8312 _endLazyDPSEvaluation();
8316 /* so we now know that the size of destination is greater
8317 than the size of the source */
8318 /* we move to result for the size of source */
8319 size = AOP_SIZE(right);
8321 _startLazyDPSEvaluation();
8324 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8328 _endLazyDPSEvaluation();
8330 /* now depending on the sign of the source && destination */
8331 size = AOP_SIZE(result) - AOP_SIZE(right);
8332 /* if unsigned or not an integral type */
8333 /* also, if the source is a bit, we don't need to sign extend, because
8334 * it can't possibly have set the sign bit.
8336 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype) || AOP_TYPE(right) == AOP_CRY)
8340 aopPut(AOP(result),zero,offset++);
8345 /* we need to extend the sign :{ */
8346 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8349 emitcode("rlc","a");
8350 emitcode("subb","a,acc");
8352 aopPut(AOP(result),"a",offset++);
8355 /* we are done hurray !!!! */
8358 freeAsmop(right,NULL,ic,TRUE);
8359 freeAsmop(result,NULL,ic,TRUE);
8363 /*-----------------------------------------------------------------*/
8364 /* genDjnz - generate decrement & jump if not zero instrucion */
8365 /*-----------------------------------------------------------------*/
8366 static int genDjnz (iCode *ic, iCode *ifx)
8372 /* if the if condition has a false label
8373 then we cannot save */
8377 /* if the minus is not of the form
8379 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8380 !IS_OP_LITERAL(IC_RIGHT(ic)))
8383 if (operandLitValue(IC_RIGHT(ic)) != 1)
8386 /* if the size of this greater than one then no
8388 if (getSize(operandType(IC_RESULT(ic))) > 1)
8391 /* otherwise we can save BIG */
8392 lbl = newiTempLabel(NULL);
8393 lbl1= newiTempLabel(NULL);
8395 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8397 if (IS_AOP_PREG(IC_RESULT(ic))) {
8398 emitcode("dec","%s",
8399 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8400 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8401 emitcode("jnz","%05d$",lbl->key+100);
8403 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8406 emitcode ("sjmp","%05d$",lbl1->key+100);
8407 emitcode ("","%05d$:",lbl->key+100);
8408 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8409 emitcode ("","%05d$:",lbl1->key+100);
8411 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8416 /*-----------------------------------------------------------------*/
8417 /* genReceive - generate code for a receive iCode */
8418 /*-----------------------------------------------------------------*/
8419 static void genReceive (iCode *ic)
8422 D(emitcode(";", "genReceive "););
8424 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8425 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8426 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8427 int size = getSize(operandType(IC_RESULT(ic)));
8428 int offset = fReturnSize_390 - size;
8430 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8431 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8434 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8435 size = AOP_SIZE(IC_RESULT(ic));
8438 emitcode ("pop","acc");
8439 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8444 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8446 assignResultValue(IC_RESULT(ic));
8449 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8452 /*-----------------------------------------------------------------*/
8453 /* gen390Code - generate code for Dallas 390 based controllers */
8454 /*-----------------------------------------------------------------*/
8455 void gen390Code (iCode *lic)
8460 lineHead = lineCurr = NULL;
8464 /* print the allocation information */
8466 printAllocInfo( currFunc, codeOutFile);
8468 /* if debug information required */
8469 if (options.debug && currFunc) {
8470 //jwk if (currFunc) {
8471 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8473 if (IS_STATIC(currFunc->etype))
8474 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8476 emitcode("","G$%s$0$0 ==.",currFunc->name);
8479 /* stack pointer name */
8480 if (options.useXstack)
8486 for (ic = lic ; ic ; ic = ic->next ) {
8488 if ( cln != ic->lineno ) {
8489 if ( options.debug ) {
8491 emitcode("","C$%s$%d$%d$%d ==.",
8492 ic->filename,ic->lineno,
8493 ic->level,ic->block);
8496 emitcode(";","%s %d",ic->filename,ic->lineno);
8499 /* if the result is marked as
8500 spilt and rematerializable or code for
8501 this has already been generated then
8503 if (resultRemat(ic) || ic->generated )
8506 /* depending on the operation */
8525 /* IPOP happens only when trying to restore a
8526 spilt live range, if there is an ifx statement
8527 following this pop then the if statement might
8528 be using some of the registers being popped which
8529 would destory the contents of the register so
8530 we need to check for this condition and handle it */
8532 ic->next->op == IFX &&
8533 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8534 genIfx (ic->next,ic);
8552 genEndFunction (ic);
8572 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8589 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8593 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8600 /* note these two are xlated by algebraic equivalence
8601 during parsing SDCC.y */
8602 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8603 "got '>=' or '<=' shouldn't have come here");
8607 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8619 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8623 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8627 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8654 case GET_VALUE_AT_ADDRESS:
8659 if (POINTER_SET(ic))
8686 addSet(&_G.sendSet,ic);
8691 /* piCode(ic,stdout); */
8697 /* now we are ready to call the
8698 peep hole optimizer */
8699 if (!options.nopeep)
8700 peepHole (&lineHead);
8702 /* now do the actual printing */
8703 printLine (lineHead,codeOutFile);