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) */
4248 OP_SYMBOL(result) &&
4249 OP_SYMBOL(result)->regType == REG_CND)
4252 /* if they are both bit variables */
4253 if (AOP_TYPE(left) == AOP_CRY &&
4254 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4255 if(AOP_TYPE(right) == AOP_LIT){
4256 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4258 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4259 emitcode("cpl","c");
4260 } else if(lit == 1L) {
4261 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4263 emitcode("clr","c");
4265 /* AOP_TYPE(right) == AOP_CRY */
4267 symbol *lbl = newiTempLabel(NULL);
4268 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4269 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4270 emitcode("cpl","c");
4271 emitcode("","%05d$:",(lbl->key+100));
4273 /* if true label then we jump if condition
4275 tlbl = newiTempLabel(NULL);
4276 if ( IC_TRUE(ifx) ) {
4277 emitcode("jnc","%05d$",tlbl->key+100);
4278 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4280 emitcode("jc","%05d$",tlbl->key+100);
4281 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4283 emitcode("","%05d$:",tlbl->key+100);
4285 tlbl = newiTempLabel(NULL);
4286 gencjneshort(left, right, tlbl);
4287 if ( IC_TRUE(ifx) ) {
4288 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4289 emitcode("","%05d$:",tlbl->key+100);
4291 symbol *lbl = newiTempLabel(NULL);
4292 emitcode("sjmp","%05d$",lbl->key+100);
4293 emitcode("","%05d$:",tlbl->key+100);
4294 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4295 emitcode("","%05d$:",lbl->key+100);
4298 /* mark the icode as generated */
4301 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4302 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4306 /* if they are both bit variables */
4307 if (AOP_TYPE(left) == AOP_CRY &&
4308 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4309 if(AOP_TYPE(right) == AOP_LIT){
4310 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4312 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4313 emitcode("cpl","c");
4314 } else if(lit == 1L) {
4315 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4317 emitcode("clr","c");
4319 /* AOP_TYPE(right) == AOP_CRY */
4321 symbol *lbl = newiTempLabel(NULL);
4322 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4323 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4324 emitcode("cpl","c");
4325 emitcode("","%05d$:",(lbl->key+100));
4328 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4329 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4331 aopOp(result,ic,TRUE, FALSE);
4334 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4339 genIfxJump (ifx,"c");
4342 /* if the result is used in an arithmetic operation
4343 then put the result in place */
4346 gencjne(left,right,newiTempLabel(NULL));
4348 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4349 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4351 aopOp(result,ic,TRUE, FALSE);
4353 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4354 aopPut(AOP(result),"a",0);
4358 genIfxJump (ifx,"a");
4361 /* if the result is used in an arithmetic operation
4362 then put the result in place */
4363 if (AOP_TYPE(result) != AOP_CRY)
4365 /* leave the result in acc */
4369 freeAsmop(result,NULL,ic,TRUE);
4372 /*-----------------------------------------------------------------*/
4373 /* ifxForOp - returns the icode containing the ifx for operand */
4374 /*-----------------------------------------------------------------*/
4375 static iCode *ifxForOp ( operand *op, iCode *ic )
4377 /* if true symbol then needs to be assigned */
4378 if (IS_TRUE_SYMOP(op))
4381 /* if this has register type condition and
4382 the next instruction is ifx with the same operand
4383 and live to of the operand is upto the ifx only then */
4385 ic->next->op == IFX &&
4386 IC_COND(ic->next)->key == op->key &&
4387 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4392 /*-----------------------------------------------------------------*/
4393 /* genAndOp - for && operation */
4394 /*-----------------------------------------------------------------*/
4395 static void genAndOp (iCode *ic)
4397 operand *left,*right, *result;
4400 D(emitcode(";", "genAndOp "););
4402 /* note here that && operations that are in an
4403 if statement are taken away by backPatchLabels
4404 only those used in arthmetic operations remain */
4408 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4409 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4410 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4413 /* if both are bit variables */
4414 if (AOP_TYPE(left) == AOP_CRY &&
4415 AOP_TYPE(right) == AOP_CRY ) {
4416 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4417 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4420 tlbl = newiTempLabel(NULL);
4422 emitcode("jz","%05d$",tlbl->key+100);
4424 emitcode("","%05d$:",tlbl->key+100);
4428 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4429 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4430 freeAsmop(result,NULL,ic,TRUE);
4434 /*-----------------------------------------------------------------*/
4435 /* genOrOp - for || operation */
4436 /*-----------------------------------------------------------------*/
4437 static void genOrOp (iCode *ic)
4439 operand *left,*right, *result;
4442 D(emitcode(";", "genOrOp "););
4444 /* note here that || operations that are in an
4445 if statement are taken away by backPatchLabels
4446 only those used in arthmetic operations remain */
4450 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4451 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4452 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4455 /* if both are bit variables */
4456 if (AOP_TYPE(left) == AOP_CRY &&
4457 AOP_TYPE(right) == AOP_CRY ) {
4458 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4459 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4462 tlbl = newiTempLabel(NULL);
4464 emitcode("jnz","%05d$",tlbl->key+100);
4466 emitcode("","%05d$:",tlbl->key+100);
4470 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4471 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4472 freeAsmop(result,NULL,ic,TRUE);
4475 /*-----------------------------------------------------------------*/
4476 /* isLiteralBit - test if lit == 2^n */
4477 /*-----------------------------------------------------------------*/
4478 static int isLiteralBit(unsigned long lit)
4480 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4481 0x100L,0x200L,0x400L,0x800L,
4482 0x1000L,0x2000L,0x4000L,0x8000L,
4483 0x10000L,0x20000L,0x40000L,0x80000L,
4484 0x100000L,0x200000L,0x400000L,0x800000L,
4485 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4486 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4489 for(idx = 0; idx < 32; idx++)
4495 /*-----------------------------------------------------------------*/
4496 /* continueIfTrue - */
4497 /*-----------------------------------------------------------------*/
4498 static void continueIfTrue (iCode *ic)
4501 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4505 /*-----------------------------------------------------------------*/
4507 /*-----------------------------------------------------------------*/
4508 static void jumpIfTrue (iCode *ic)
4511 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4515 /*-----------------------------------------------------------------*/
4516 /* jmpTrueOrFalse - */
4517 /*-----------------------------------------------------------------*/
4518 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4520 // ugly but optimized by peephole
4522 symbol *nlbl = newiTempLabel(NULL);
4523 emitcode("sjmp","%05d$",nlbl->key+100);
4524 emitcode("","%05d$:",tlbl->key+100);
4525 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4526 emitcode("","%05d$:",nlbl->key+100);
4529 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4530 emitcode("","%05d$:",tlbl->key+100);
4535 /*-----------------------------------------------------------------*/
4536 /* genAnd - code for and */
4537 /*-----------------------------------------------------------------*/
4538 static void genAnd (iCode *ic, iCode *ifx)
4540 operand *left, *right, *result;
4542 unsigned long lit = 0L;
4546 D(emitcode(";", "genAnd "););
4551 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4552 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4553 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4557 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4559 AOP_TYPE(left), AOP_TYPE(right));
4560 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4562 AOP_SIZE(left), AOP_SIZE(right));
4565 /* if left is a literal & right is not then exchange them */
4566 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4567 AOP_NEEDSACC(left)) {
4568 operand *tmp = right ;
4573 /* if result = right then exchange them */
4574 if(sameRegs(AOP(result),AOP(right))){
4575 operand *tmp = right ;
4580 /* if right is bit then exchange them */
4581 if (AOP_TYPE(right) == AOP_CRY &&
4582 AOP_TYPE(left) != AOP_CRY){
4583 operand *tmp = right ;
4587 if(AOP_TYPE(right) == AOP_LIT)
4588 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4590 size = AOP_SIZE(result);
4593 // result = bit & yy;
4594 if (AOP_TYPE(left) == AOP_CRY){
4595 // c = bit & literal;
4596 if(AOP_TYPE(right) == AOP_LIT){
4598 if(size && sameRegs(AOP(result),AOP(left)))
4601 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4604 if(size && (AOP_TYPE(result) == AOP_CRY)){
4605 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4608 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4612 emitcode("clr","c");
4615 if (AOP_TYPE(right) == AOP_CRY){
4617 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4618 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4621 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4623 emitcode("rrc","a");
4624 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4632 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4633 genIfxJump(ifx, "c");
4637 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4638 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4639 if((AOP_TYPE(right) == AOP_LIT) &&
4640 (AOP_TYPE(result) == AOP_CRY) &&
4641 (AOP_TYPE(left) != AOP_CRY)){
4642 int posbit = isLiteralBit(lit);
4646 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4649 emitcode("mov","c,acc.%d",posbit&0x07);
4653 sprintf(buffer,"acc.%d",posbit&0x07);
4654 genIfxJump(ifx, buffer);
4659 symbol *tlbl = newiTempLabel(NULL);
4660 int sizel = AOP_SIZE(left);
4662 emitcode("setb","c");
4664 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4665 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4667 if((posbit = isLiteralBit(bytelit)) != 0)
4668 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4670 if(bytelit != 0x0FFL)
4671 emitcode("anl","a,%s",
4672 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4673 emitcode("jnz","%05d$",tlbl->key+100);
4678 // bit = left & literal
4680 emitcode("clr","c");
4681 emitcode("","%05d$:",tlbl->key+100);
4683 // if(left & literal)
4686 jmpTrueOrFalse(ifx, tlbl);
4694 /* if left is same as result */
4695 if(sameRegs(AOP(result),AOP(left))){
4696 for(;size--; offset++) {
4697 if(AOP_TYPE(right) == AOP_LIT){
4698 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4702 aopPut(AOP(result),zero,offset);
4704 if (IS_AOP_PREG(result)) {
4705 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4706 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4707 aopPut(AOP(result),"a",offset);
4709 emitcode("anl","%s,%s",
4710 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4711 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4713 if (AOP_TYPE(left) == AOP_ACC)
4714 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4716 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4717 if (IS_AOP_PREG(result)) {
4718 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4719 aopPut(AOP(result),"a",offset);
4722 emitcode("anl","%s,a",
4723 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4728 // left & result in different registers
4729 if(AOP_TYPE(result) == AOP_CRY){
4731 // if(size), result in bit
4732 // if(!size && ifx), conditional oper: if(left & right)
4733 symbol *tlbl = newiTempLabel(NULL);
4734 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4736 emitcode("setb","c");
4738 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4739 emitcode("anl","a,%s",
4740 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4741 emitcode("jnz","%05d$",tlbl->key+100);
4746 emitcode("","%05d$:",tlbl->key+100);
4749 jmpTrueOrFalse(ifx, tlbl);
4752 for(;(size--);offset++)
4755 // result = left & right
4756 if(AOP_TYPE(right) == AOP_LIT)
4758 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4761 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4765 else if (bytelit == 0)
4767 aopPut(AOP(result),zero,offset);
4770 D(emitcode(";", "better literal AND."););
4771 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4772 emitcode("anl", "a, %s", aopGet(AOP(right),offset,
4773 FALSE,FALSE,FALSE));
4778 // faster than result <- left, anl result,right
4779 // and better if result is SFR
4780 if (AOP_TYPE(left) == AOP_ACC)
4782 emitcode("anl","a,%s",aopGet(AOP(right),offset,
4783 FALSE,FALSE,FALSE));
4787 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4788 emitcode("anl","a,%s",
4789 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4792 aopPut(AOP(result),"a",offset);
4798 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4799 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4800 freeAsmop(result,NULL,ic,TRUE);
4803 /*-----------------------------------------------------------------*/
4804 /* genOr - code for or */
4805 /*-----------------------------------------------------------------*/
4806 static void genOr (iCode *ic, iCode *ifx)
4808 operand *left, *right, *result;
4810 unsigned long lit = 0L;
4812 D(emitcode(";", "genOr "););
4817 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4818 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4819 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4823 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4825 AOP_TYPE(left), AOP_TYPE(right));
4826 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4828 AOP_SIZE(left), AOP_SIZE(right));
4831 /* if left is a literal & right is not then exchange them */
4832 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4833 AOP_NEEDSACC(left)) {
4834 operand *tmp = right ;
4839 /* if result = right then exchange them */
4840 if(sameRegs(AOP(result),AOP(right))){
4841 operand *tmp = right ;
4846 /* if right is bit then exchange them */
4847 if (AOP_TYPE(right) == AOP_CRY &&
4848 AOP_TYPE(left) != AOP_CRY){
4849 operand *tmp = right ;
4853 if(AOP_TYPE(right) == AOP_LIT)
4854 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4856 size = AOP_SIZE(result);
4860 if (AOP_TYPE(left) == AOP_CRY){
4861 if(AOP_TYPE(right) == AOP_LIT){
4862 // c = bit & literal;
4864 // lit != 0 => result = 1
4865 if(AOP_TYPE(result) == AOP_CRY){
4867 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4869 continueIfTrue(ifx);
4872 emitcode("setb","c");
4874 // lit == 0 => result = left
4875 if(size && sameRegs(AOP(result),AOP(left)))
4877 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4880 if (AOP_TYPE(right) == AOP_CRY){
4882 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4883 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4887 symbol *tlbl = newiTempLabel(NULL);
4888 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4889 emitcode("setb","c");
4890 emitcode("jb","%s,%05d$",
4891 AOP(left)->aopu.aop_dir,tlbl->key+100);
4893 emitcode("jnz","%05d$",tlbl->key+100);
4894 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4895 jmpTrueOrFalse(ifx, tlbl);
4899 emitcode("","%05d$:",tlbl->key+100);
4908 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4909 genIfxJump(ifx, "c");
4913 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4914 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4915 if((AOP_TYPE(right) == AOP_LIT) &&
4916 (AOP_TYPE(result) == AOP_CRY) &&
4917 (AOP_TYPE(left) != AOP_CRY)){
4921 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4923 continueIfTrue(ifx);
4926 // lit = 0, result = boolean(left)
4928 emitcode("setb","c");
4931 symbol *tlbl = newiTempLabel(NULL);
4932 emitcode("jnz","%05d$",tlbl->key+100);
4934 emitcode("","%05d$:",tlbl->key+100);
4936 genIfxJump (ifx,"a");
4944 /* if left is same as result */
4945 if(sameRegs(AOP(result),AOP(left)))
4947 for(;size--; offset++)
4949 if(AOP_TYPE(right) == AOP_LIT){
4950 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4956 if (IS_AOP_PREG(left))
4958 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4959 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4960 aopPut(AOP(result),"a",offset);
4964 emitcode("orl","%s,%s",
4965 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4966 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4972 if (AOP_TYPE(left) == AOP_ACC)
4974 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4978 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4979 if (IS_AOP_PREG(left))
4981 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4982 aopPut(AOP(result),"a",offset);
4986 emitcode("orl","%s,a",
4987 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4995 // left & result in different registers
4996 if(AOP_TYPE(result) == AOP_CRY)
4999 // if(size), result in bit
5000 // if(!size && ifx), conditional oper: if(left | right)
5001 symbol *tlbl = newiTempLabel(NULL);
5002 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5004 emitcode("setb","c");
5006 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5007 emitcode("orl","a,%s",
5008 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5009 emitcode("jnz","%05d$",tlbl->key+100);
5014 emitcode("","%05d$:",tlbl->key+100);
5017 jmpTrueOrFalse(ifx, tlbl);
5021 for(;(size--);offset++)
5024 // result = left & right
5025 if(AOP_TYPE(right) == AOP_LIT)
5027 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5030 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5034 D(emitcode(";", "better literal OR."););
5035 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5036 emitcode("orl", "a, %s", aopGet(AOP(right),offset,
5037 FALSE,FALSE,FALSE));
5042 // faster than result <- left, anl result,right
5043 // and better if result is SFR
5044 if (AOP_TYPE(left) == AOP_ACC)
5046 emitcode("orl","a,%s",aopGet(AOP(right),offset,
5047 FALSE,FALSE,FALSE));
5051 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5052 emitcode("orl","a,%s",
5053 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5056 aopPut(AOP(result),"a",offset);
5062 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5063 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5064 freeAsmop(result,NULL,ic,TRUE);
5067 /*-----------------------------------------------------------------*/
5068 /* genXor - code for xclusive or */
5069 /*-----------------------------------------------------------------*/
5070 static void genXor (iCode *ic, iCode *ifx)
5072 operand *left, *right, *result;
5074 unsigned long lit = 0L;
5076 D(emitcode(";", "genXor "););
5081 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
5082 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
5083 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
5087 emitcode("","; Type res[%d] = l[%d]&r[%d]",
5089 AOP_TYPE(left), AOP_TYPE(right));
5090 emitcode("","; Size res[%d] = l[%d]&r[%d]",
5092 AOP_SIZE(left), AOP_SIZE(right));
5095 /* if left is a literal & right is not ||
5096 if left needs acc & right does not */
5097 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5098 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5099 operand *tmp = right ;
5104 /* if result = right then exchange them */
5105 if(sameRegs(AOP(result),AOP(right))){
5106 operand *tmp = right ;
5111 /* if right is bit then exchange them */
5112 if (AOP_TYPE(right) == AOP_CRY &&
5113 AOP_TYPE(left) != AOP_CRY){
5114 operand *tmp = right ;
5118 if(AOP_TYPE(right) == AOP_LIT)
5119 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5121 size = AOP_SIZE(result);
5125 if (AOP_TYPE(left) == AOP_CRY){
5126 if(AOP_TYPE(right) == AOP_LIT){
5127 // c = bit & literal;
5129 // lit>>1 != 0 => result = 1
5130 if(AOP_TYPE(result) == AOP_CRY){
5132 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5134 continueIfTrue(ifx);
5137 emitcode("setb","c");
5141 // lit == 0, result = left
5142 if(size && sameRegs(AOP(result),AOP(left)))
5144 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5146 // lit == 1, result = not(left)
5147 if(size && sameRegs(AOP(result),AOP(left))){
5148 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5151 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5152 emitcode("cpl","c");
5159 symbol *tlbl = newiTempLabel(NULL);
5160 if (AOP_TYPE(right) == AOP_CRY){
5162 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5165 int sizer = AOP_SIZE(right);
5167 // if val>>1 != 0, result = 1
5168 emitcode("setb","c");
5170 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5172 // test the msb of the lsb
5173 emitcode("anl","a,#0xfe");
5174 emitcode("jnz","%05d$",tlbl->key+100);
5178 emitcode("rrc","a");
5180 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5181 emitcode("cpl","c");
5182 emitcode("","%05d$:",(tlbl->key+100));
5189 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5190 genIfxJump(ifx, "c");
5194 if(sameRegs(AOP(result),AOP(left))){
5195 /* if left is same as result */
5196 for(;size--; offset++) {
5197 if(AOP_TYPE(right) == AOP_LIT){
5198 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5201 if (IS_AOP_PREG(left)) {
5202 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5203 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5204 aopPut(AOP(result),"a",offset);
5206 emitcode("xrl","%s,%s",
5207 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5208 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5210 if (AOP_TYPE(left) == AOP_ACC)
5211 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5213 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5214 if (IS_AOP_PREG(left)) {
5215 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5216 aopPut(AOP(result),"a",offset);
5218 emitcode("xrl","%s,a",
5219 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5224 // left & result in different registers
5225 if(AOP_TYPE(result) == AOP_CRY){
5227 // if(size), result in bit
5228 // if(!size && ifx), conditional oper: if(left ^ right)
5229 symbol *tlbl = newiTempLabel(NULL);
5230 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5232 emitcode("setb","c");
5234 if((AOP_TYPE(right) == AOP_LIT) &&
5235 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5236 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5238 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5239 emitcode("xrl","a,%s",
5240 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5242 emitcode("jnz","%05d$",tlbl->key+100);
5247 emitcode("","%05d$:",tlbl->key+100);
5250 jmpTrueOrFalse(ifx, tlbl);
5251 } else for(;(size--);offset++)
5254 // result = left & right
5255 if(AOP_TYPE(right) == AOP_LIT)
5257 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5260 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5264 D(emitcode(";", "better literal XOR."););
5265 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5266 emitcode("xrl", "a, %s", aopGet(AOP(right),offset,
5267 FALSE,FALSE,FALSE));
5271 // faster than result <- left, anl result,right
5272 // and better if result is SFR
5273 if (AOP_TYPE(left) == AOP_ACC)
5275 emitcode("xrl","a,%s",aopGet(AOP(right),offset,
5276 FALSE,FALSE,FALSE));
5280 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5281 emitcode("xrl","a,%s",
5282 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5285 aopPut(AOP(result),"a",offset);
5290 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5291 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5292 freeAsmop(result,NULL,ic,TRUE);
5295 /*-----------------------------------------------------------------*/
5296 /* genInline - write the inline code out */
5297 /*-----------------------------------------------------------------*/
5298 static void genInline (iCode *ic)
5300 char buffer[MAX_INLINEASM];
5304 D(emitcode(";", "genInline "););
5306 _G.inLine += (!options.asmpeep);
5307 strcpy(buffer,IC_INLINE(ic));
5309 /* emit each line as a code */
5328 /* emitcode("",buffer); */
5329 _G.inLine -= (!options.asmpeep);
5332 /*-----------------------------------------------------------------*/
5333 /* genRRC - rotate right with carry */
5334 /*-----------------------------------------------------------------*/
5335 static void genRRC (iCode *ic)
5337 operand *left , *result ;
5338 int size, offset = 0;
5341 D(emitcode(";", "genRRC "););
5343 /* rotate right with carry */
5345 result=IC_RESULT(ic);
5346 aopOp (left,ic,FALSE, FALSE);
5347 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5349 /* move it to the result */
5350 size = AOP_SIZE(result);
5354 _startLazyDPSEvaluation();
5356 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5358 emitcode("rrc","a");
5359 if (AOP_SIZE(result) > 1)
5360 aopPut(AOP(result),"a",offset--);
5362 _endLazyDPSEvaluation();
5364 /* now we need to put the carry into the
5365 highest order byte of the result */
5366 if (AOP_SIZE(result) > 1) {
5367 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5370 emitcode("mov","acc.7,c");
5371 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5372 freeAsmop(left,NULL,ic,TRUE);
5373 freeAsmop(result,NULL,ic,TRUE);
5376 /*-----------------------------------------------------------------*/
5377 /* genRLC - generate code for rotate left with carry */
5378 /*-----------------------------------------------------------------*/
5379 static void genRLC (iCode *ic)
5381 operand *left , *result ;
5382 int size, offset = 0;
5385 D(emitcode(";", "genRLC "););
5387 /* rotate right with carry */
5389 result=IC_RESULT(ic);
5390 aopOp (left,ic,FALSE, FALSE);
5391 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5393 /* move it to the result */
5394 size = AOP_SIZE(result);
5397 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5399 emitcode("add","a,acc");
5400 if (AOP_SIZE(result) > 1)
5402 aopPut(AOP(result),"a",offset++);
5405 _startLazyDPSEvaluation();
5407 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5409 emitcode("rlc","a");
5410 if (AOP_SIZE(result) > 1)
5411 aopPut(AOP(result),"a",offset++);
5413 _endLazyDPSEvaluation();
5415 /* now we need to put the carry into the
5416 highest order byte of the result */
5417 if (AOP_SIZE(result) > 1) {
5418 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5421 emitcode("mov","acc.0,c");
5422 aopPut(AOP(result),"a",0);
5423 freeAsmop(left,NULL,ic,TRUE);
5424 freeAsmop(result,NULL,ic,TRUE);
5427 /*-----------------------------------------------------------------*/
5428 /* genGetHbit - generates code get highest order bit */
5429 /*-----------------------------------------------------------------*/
5430 static void genGetHbit (iCode *ic)
5432 operand *left, *result;
5434 result=IC_RESULT(ic);
5435 aopOp (left,ic,FALSE, FALSE);
5436 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5438 D(emitcode(";", "genGetHbit "););
5440 /* get the highest order byte into a */
5441 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5442 if(AOP_TYPE(result) == AOP_CRY){
5443 emitcode("rlc","a");
5448 emitcode("anl","a,#0x01");
5453 freeAsmop(left,NULL,ic,TRUE);
5454 freeAsmop(result,NULL,ic,TRUE);
5457 /*-----------------------------------------------------------------*/
5458 /* AccRol - rotate left accumulator by known count */
5459 /*-----------------------------------------------------------------*/
5460 static void AccRol (int shCount)
5462 shCount &= 0x0007; // shCount : 0..7
5474 emitcode("swap","a");
5478 emitcode("swap","a");
5481 emitcode("swap","a");
5494 /*-----------------------------------------------------------------*/
5495 /* AccLsh - left shift accumulator by known count */
5496 /*-----------------------------------------------------------------*/
5497 static void AccLsh (int shCount)
5501 emitcode("add","a,acc");
5504 emitcode("add","a,acc");
5505 emitcode("add","a,acc");
5507 /* rotate left accumulator */
5509 /* and kill the lower order bits */
5510 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5515 /*-----------------------------------------------------------------*/
5516 /* AccRsh - right shift accumulator by known count */
5517 /*-----------------------------------------------------------------*/
5518 static void AccRsh (int shCount)
5523 emitcode("rrc","a");
5525 /* rotate right accumulator */
5526 AccRol(8 - shCount);
5527 /* and kill the higher order bits */
5528 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5535 /*-----------------------------------------------------------------*/
5536 /* AccSRsh - signed right shift accumulator by known count */
5537 /*-----------------------------------------------------------------*/
5538 static void AccSRsh (int shCount)
5543 emitcode("mov","c,acc.7");
5544 emitcode("rrc","a");
5545 } else if(shCount == 2){
5546 emitcode("mov","c,acc.7");
5547 emitcode("rrc","a");
5548 emitcode("mov","c,acc.7");
5549 emitcode("rrc","a");
5551 tlbl = newiTempLabel(NULL);
5552 /* rotate right accumulator */
5553 AccRol(8 - shCount);
5554 /* and kill the higher order bits */
5555 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5556 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5557 emitcode("orl","a,#0x%02x",
5558 (unsigned char)~SRMask[shCount]);
5559 emitcode("","%05d$:",tlbl->key+100);
5567 /*-----------------------------------------------------------------*/
5568 /* shiftR1Left2Result - shift right one byte from left to result */
5569 /*-----------------------------------------------------------------*/
5570 static void shiftR1Left2Result (operand *left, int offl,
5571 operand *result, int offr,
5572 int shCount, int sign)
5574 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5575 /* shift right accumulator */
5580 aopPut(AOP(result),"a",offr);
5586 /*-----------------------------------------------------------------*/
5587 /* shiftL1Left2Result - shift left one byte from left to result */
5588 /*-----------------------------------------------------------------*/
5589 static void shiftL1Left2Result (operand *left, int offl,
5590 operand *result, int offr, int shCount)
5593 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5595 /* shift left accumulator */
5597 aopPut(AOP(result),"a",offr);
5603 /*-----------------------------------------------------------------*/
5604 /* movLeft2Result - move byte from left to result */
5605 /*-----------------------------------------------------------------*/
5606 static void movLeft2Result (operand *left, int offl,
5607 operand *result, int offr, int sign)
5610 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5611 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5613 if (*l == '@' && (IS_AOP_PREG(result))) {
5614 emitcode("mov","a,%s",l);
5615 aopPut(AOP(result),"a",offr);
5618 aopPut(AOP(result),l,offr);
5620 /* MSB sign in acc.7 ! */
5621 if(getDataSize(left) == offl+1){
5622 emitcode("mov","a,%s",l);
5623 aopPut(AOP(result),"a",offr);
5633 /*-----------------------------------------------------------------*/
5634 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5635 /*-----------------------------------------------------------------*/
5636 static void AccAXRrl1 (char *x)
5638 emitcode("rrc","a");
5639 emitcode("xch","a,%s", x);
5640 emitcode("rrc","a");
5641 emitcode("xch","a,%s", x);
5647 /*-----------------------------------------------------------------*/
5648 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5649 /*-----------------------------------------------------------------*/
5650 static void AccAXLrl1 (char *x)
5652 emitcode("xch","a,%s",x);
5653 emitcode("rlc","a");
5654 emitcode("xch","a,%s",x);
5655 emitcode("rlc","a");
5661 /*-----------------------------------------------------------------*/
5662 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5663 /*-----------------------------------------------------------------*/
5664 static void AccAXLsh1 (char *x)
5666 emitcode("xch","a,%s",x);
5667 emitcode("add","a,acc");
5668 emitcode("xch","a,%s",x);
5669 emitcode("rlc","a");
5675 /*-----------------------------------------------------------------*/
5676 /* AccAXLsh - left shift a:x by known count (0..7) */
5677 /*-----------------------------------------------------------------*/
5678 static void AccAXLsh (char *x, int shCount)
5692 case 5 : // AAAAABBB:CCCCCDDD
5693 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5694 emitcode("anl","a,#0x%02x",
5695 SLMask[shCount]); // BBB00000:CCCCCDDD
5696 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5697 AccRol(shCount); // DDDCCCCC:BBB00000
5698 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5699 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5700 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5701 emitcode("anl","a,#0x%02x",
5702 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5703 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5704 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5706 case 6 : // AAAAAABB:CCCCCCDD
5707 emitcode("anl","a,#0x%02x",
5708 SRMask[shCount]); // 000000BB:CCCCCCDD
5709 emitcode("mov","c,acc.0"); // c = B
5710 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5711 AccAXRrl1(x); // BCCCCCCD:D000000B
5712 AccAXRrl1(x); // BBCCCCCC:DD000000
5714 case 7 : // a:x <<= 7
5715 emitcode("anl","a,#0x%02x",
5716 SRMask[shCount]); // 0000000B:CCCCCCCD
5717 emitcode("mov","c,acc.0"); // c = B
5718 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5719 AccAXRrl1(x); // BCCCCCCC:D0000000
5729 /*-----------------------------------------------------------------*/
5730 /* AccAXRsh - right shift a:x known count (0..7) */
5731 /*-----------------------------------------------------------------*/
5732 static void AccAXRsh (char *x, int shCount)
5739 AccAXRrl1(x); // 0->a:x
5743 AccAXRrl1(x); // 0->a:x
5745 AccAXRrl1(x); // 0->a:x
5749 case 5 : // AAAAABBB:CCCCCDDD = a:x
5750 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5751 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5752 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5753 emitcode("anl","a,#0x%02x",
5754 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5755 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5756 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5757 emitcode("anl","a,#0x%02x",
5758 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5759 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5760 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5761 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5763 case 6 : // AABBBBBB:CCDDDDDD
5764 emitcode("mov","c,acc.7");
5765 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5766 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5767 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5768 emitcode("anl","a,#0x%02x",
5769 SRMask[shCount]); // 000000AA:BBBBBBCC
5771 case 7 : // ABBBBBBB:CDDDDDDD
5772 emitcode("mov","c,acc.7"); // c = A
5773 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5774 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5775 emitcode("anl","a,#0x%02x",
5776 SRMask[shCount]); // 0000000A:BBBBBBBC
5786 /*-----------------------------------------------------------------*/
5787 /* AccAXRshS - right shift signed a:x known count (0..7) */
5788 /*-----------------------------------------------------------------*/
5789 static void AccAXRshS (char *x, int shCount)
5796 emitcode("mov","c,acc.7");
5797 AccAXRrl1(x); // s->a:x
5800 emitcode("mov","c,acc.7");
5801 AccAXRrl1(x); // s->a:x
5802 emitcode("mov","c,acc.7");
5803 AccAXRrl1(x); // s->a:x
5807 case 5 : // AAAAABBB:CCCCCDDD = a:x
5808 tlbl = newiTempLabel(NULL);
5809 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5810 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5811 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5812 emitcode("anl","a,#0x%02x",
5813 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5814 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5815 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5816 emitcode("anl","a,#0x%02x",
5817 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5818 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5819 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5820 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5821 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5822 emitcode("orl","a,#0x%02x",
5823 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5824 emitcode("","%05d$:",tlbl->key+100);
5825 break; // SSSSAAAA:BBBCCCCC
5826 case 6 : // AABBBBBB:CCDDDDDD
5827 tlbl = newiTempLabel(NULL);
5828 emitcode("mov","c,acc.7");
5829 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5830 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5831 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5832 emitcode("anl","a,#0x%02x",
5833 SRMask[shCount]); // 000000AA:BBBBBBCC
5834 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5835 emitcode("orl","a,#0x%02x",
5836 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5837 emitcode("","%05d$:",tlbl->key+100);
5839 case 7 : // ABBBBBBB:CDDDDDDD
5840 tlbl = newiTempLabel(NULL);
5841 emitcode("mov","c,acc.7"); // c = A
5842 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5843 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5844 emitcode("anl","a,#0x%02x",
5845 SRMask[shCount]); // 0000000A:BBBBBBBC
5846 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5847 emitcode("orl","a,#0x%02x",
5848 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5849 emitcode("","%05d$:",tlbl->key+100);
5859 /*-----------------------------------------------------------------*/
5860 /* shiftL2Left2Result - shift left two bytes from left to result */
5861 /*-----------------------------------------------------------------*/
5862 static void shiftL2Left2Result (operand *left, int offl,
5863 operand *result, int offr, int shCount)
5865 if(sameRegs(AOP(result), AOP(left)) &&
5866 ((offl + MSB16) == offr)){
5867 /* don't crash result[offr] */
5868 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5869 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5871 movLeft2Result(left,offl, result, offr, 0);
5872 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5874 /* ax << shCount (x = lsb(result))*/
5875 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5876 aopPut(AOP(result),"a",offr+MSB16);
5882 /*-----------------------------------------------------------------*/
5883 /* shiftR2Left2Result - shift right two bytes from left to result */
5884 /*-----------------------------------------------------------------*/
5885 static void shiftR2Left2Result (operand *left, int offl,
5886 operand *result, int offr,
5887 int shCount, int sign)
5889 if(sameRegs(AOP(result), AOP(left)) &&
5890 ((offl + MSB16) == offr)){
5891 /* don't crash result[offr] */
5892 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5893 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5895 movLeft2Result(left,offl, result, offr, 0);
5896 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5898 /* a:x >> shCount (x = lsb(result))*/
5900 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5902 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5903 if(getDataSize(result) > 1)
5904 aopPut(AOP(result),"a",offr+MSB16);
5910 /*-----------------------------------------------------------------*/
5911 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5912 /*-----------------------------------------------------------------*/
5913 static void shiftLLeftOrResult (operand *left, int offl,
5914 operand *result, int offr, int shCount)
5916 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5917 /* shift left accumulator */
5919 /* or with result */
5920 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5921 /* back to result */
5922 aopPut(AOP(result),"a",offr);
5928 /*-----------------------------------------------------------------*/
5929 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5930 /*-----------------------------------------------------------------*/
5931 static void shiftRLeftOrResult (operand *left, int offl,
5932 operand *result, int offr, int shCount)
5934 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5935 /* shift right accumulator */
5937 /* or with result */
5938 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5939 /* back to result */
5940 aopPut(AOP(result),"a",offr);
5946 /*-----------------------------------------------------------------*/
5947 /* genlshOne - left shift a one byte quantity by known count */
5948 /*-----------------------------------------------------------------*/
5949 static void genlshOne (operand *result, operand *left, int shCount)
5951 D(emitcode(";", "genlshOne "););
5952 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5958 /*-----------------------------------------------------------------*/
5959 /* genlshTwo - left shift two bytes by known amount != 0 */
5960 /*-----------------------------------------------------------------*/
5961 static void genlshTwo (operand *result,operand *left, int shCount)
5965 D(emitcode(";", "genlshTwo "););
5967 size = getDataSize(result);
5969 /* if shCount >= 8 */
5975 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5977 movLeft2Result(left, LSB, result, MSB16, 0);
5979 aopPut(AOP(result),zero,LSB);
5982 /* 1 <= shCount <= 7 */
5985 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5987 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5994 /*-----------------------------------------------------------------*/
5995 /* shiftLLong - shift left one long from left to result */
5996 /* offl = LSB or MSB16 */
5997 /*-----------------------------------------------------------------*/
5998 static void shiftLLong (operand *left, operand *result, int offr )
6001 int size = AOP_SIZE(result);
6003 if(size >= LSB+offr){
6004 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
6006 emitcode("add","a,acc");
6007 if (sameRegs(AOP(left),AOP(result)) &&
6008 size >= MSB16+offr && offr != LSB )
6009 emitcode("xch","a,%s",
6010 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
6012 aopPut(AOP(result),"a",LSB+offr);
6015 if(size >= MSB16+offr){
6016 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6017 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
6020 emitcode("rlc","a");
6021 if (sameRegs(AOP(left),AOP(result)) &&
6022 size >= MSB24+offr && offr != LSB)
6023 emitcode("xch","a,%s",
6024 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
6026 aopPut(AOP(result),"a",MSB16+offr);
6029 if(size >= MSB24+offr){
6030 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6031 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
6034 emitcode("rlc","a");
6035 if (sameRegs(AOP(left),AOP(result)) &&
6036 size >= MSB32+offr && offr != LSB )
6037 emitcode("xch","a,%s",
6038 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
6040 aopPut(AOP(result),"a",MSB24+offr);
6043 if(size > MSB32+offr){
6044 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6045 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
6048 emitcode("rlc","a");
6049 aopPut(AOP(result),"a",MSB32+offr);
6052 aopPut(AOP(result),zero,LSB);
6058 /*-----------------------------------------------------------------*/
6059 /* genlshFour - shift four byte by a known amount != 0 */
6060 /*-----------------------------------------------------------------*/
6061 static void genlshFour (operand *result, operand *left, int shCount)
6065 D(emitcode(";", "genlshFour "););
6067 size = AOP_SIZE(result);
6069 /* if shifting more that 3 bytes */
6070 if (shCount >= 24 ) {
6073 /* lowest order of left goes to the highest
6074 order of the destination */
6075 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6077 movLeft2Result(left, LSB, result, MSB32, 0);
6078 aopPut(AOP(result),zero,LSB);
6079 aopPut(AOP(result),zero,MSB16);
6080 aopPut(AOP(result),zero,MSB32);
6084 /* more than two bytes */
6085 else if ( shCount >= 16 ) {
6086 /* lower order two bytes goes to higher order two bytes */
6088 /* if some more remaining */
6090 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6092 movLeft2Result(left, MSB16, result, MSB32, 0);
6093 movLeft2Result(left, LSB, result, MSB24, 0);
6095 aopPut(AOP(result),zero,MSB16);
6096 aopPut(AOP(result),zero,LSB);
6100 /* if more than 1 byte */
6101 else if ( shCount >= 8 ) {
6102 /* lower order three bytes goes to higher order three bytes */
6106 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6108 movLeft2Result(left, LSB, result, MSB16, 0);
6110 else{ /* size = 4 */
6112 movLeft2Result(left, MSB24, result, MSB32, 0);
6113 movLeft2Result(left, MSB16, result, MSB24, 0);
6114 movLeft2Result(left, LSB, result, MSB16, 0);
6115 aopPut(AOP(result),zero,LSB);
6117 else if(shCount == 1)
6118 shiftLLong(left, result, MSB16);
6120 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6121 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6122 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6123 aopPut(AOP(result),zero,LSB);
6128 /* 1 <= shCount <= 7 */
6129 else if(shCount <= 2){
6130 shiftLLong(left, result, LSB);
6132 shiftLLong(result, result, LSB);
6134 /* 3 <= shCount <= 7, optimize */
6136 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6137 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6138 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6145 /*-----------------------------------------------------------------*/
6146 /* genLeftShiftLiteral - left shifting by known count */
6147 /*-----------------------------------------------------------------*/
6148 static void genLeftShiftLiteral (operand *left,
6153 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6156 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
6158 freeAsmop(right,NULL,ic,TRUE);
6160 aopOp(left,ic,FALSE, FALSE);
6161 aopOp(result,ic,FALSE, TRUE);
6163 size = getSize(operandType(result));
6166 emitcode("; shift left ","result %d, left %d",size,
6170 /* I suppose that the left size >= result size */
6173 movLeft2Result(left, size, result, size, 0);
6177 else if(shCount >= (size * 8))
6179 aopPut(AOP(result),zero,size);
6183 genlshOne (result,left,shCount);
6187 case 3: /* bug: this is for generic pointers, I bet. */
6188 genlshTwo (result,left,shCount);
6192 genlshFour (result,left,shCount);
6196 freeAsmop(left,NULL,ic,TRUE);
6197 freeAsmop(result,NULL,ic,TRUE);
6201 /*-----------------------------------------------------------------*/
6202 /* genLeftShift - generates code for left shifting */
6203 /*-----------------------------------------------------------------*/
6204 static void genLeftShift (iCode *ic)
6206 operand *left,*right, *result;
6209 symbol *tlbl , *tlbl1;
6211 D(emitcode(";", "genLeftShift "););
6213 right = IC_RIGHT(ic);
6215 result = IC_RESULT(ic);
6217 aopOp(right,ic,FALSE, FALSE);
6220 /* if the shift count is known then do it
6221 as efficiently as possible */
6222 if (AOP_TYPE(right) == AOP_LIT) {
6223 genLeftShiftLiteral (left,right,result,ic);
6228 /* shift count is unknown then we have to form
6229 a loop get the loop count in B : Note: we take
6230 only the lower order byte since shifting
6231 more that 32 bits make no sense anyway, ( the
6232 largest size of an object can be only 32 bits ) */
6234 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6235 emitcode("inc","b");
6236 freeAsmop (right,NULL,ic,TRUE);
6237 aopOp(left,ic,FALSE, FALSE);
6238 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6240 /* now move the left to the result if they are not the
6242 if (!sameRegs(AOP(left),AOP(result)) &&
6243 AOP_SIZE(result) > 1) {
6245 size = AOP_SIZE(result);
6247 _startLazyDPSEvaluation();
6249 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6250 if (*l == '@' && (IS_AOP_PREG(result))) {
6252 emitcode("mov","a,%s",l);
6253 aopPut(AOP(result),"a",offset);
6255 aopPut(AOP(result),l,offset);
6258 _endLazyDPSEvaluation();
6261 tlbl = newiTempLabel(NULL);
6262 size = AOP_SIZE(result);
6264 tlbl1 = newiTempLabel(NULL);
6266 /* if it is only one byte then */
6268 symbol *tlbl1 = newiTempLabel(NULL);
6270 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6272 emitcode("sjmp","%05d$",tlbl1->key+100);
6273 emitcode("","%05d$:",tlbl->key+100);
6274 emitcode("add","a,acc");
6275 emitcode("","%05d$:",tlbl1->key+100);
6276 emitcode("djnz","b,%05d$",tlbl->key+100);
6277 aopPut(AOP(result),"a",0);
6281 reAdjustPreg(AOP(result));
6283 emitcode("sjmp","%05d$",tlbl1->key+100);
6284 emitcode("","%05d$:",tlbl->key+100);
6285 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6287 emitcode("add","a,acc");
6288 aopPut(AOP(result),"a",offset++);
6289 _startLazyDPSEvaluation();
6291 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6293 emitcode("rlc","a");
6294 aopPut(AOP(result),"a",offset++);
6296 _endLazyDPSEvaluation();
6297 reAdjustPreg(AOP(result));
6299 emitcode("","%05d$:",tlbl1->key+100);
6300 emitcode("djnz","b,%05d$",tlbl->key+100);
6302 freeAsmop(left,NULL,ic,TRUE);
6303 freeAsmop(result,NULL,ic,TRUE);
6308 /*-----------------------------------------------------------------*/
6309 /* genrshOne - right shift a one byte quantity by known count */
6310 /*-----------------------------------------------------------------*/
6311 static void genrshOne (operand *result, operand *left,
6312 int shCount, int sign)
6314 D(emitcode(";", "genrshOne"););
6315 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6321 /*-----------------------------------------------------------------*/
6322 /* genrshTwo - right shift two bytes by known amount != 0 */
6323 /*-----------------------------------------------------------------*/
6324 static void genrshTwo (operand *result,operand *left,
6325 int shCount, int sign)
6327 D(emitcode(";", "genrshTwo"););
6329 /* if shCount >= 8 */
6333 shiftR1Left2Result(left, MSB16, result, LSB,
6336 movLeft2Result(left, MSB16, result, LSB, sign);
6337 addSign(result, MSB16, sign);
6340 /* 1 <= shCount <= 7 */
6342 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6348 /*-----------------------------------------------------------------*/
6349 /* shiftRLong - shift right one long from left to result */
6350 /* offl = LSB or MSB16 */
6351 /*-----------------------------------------------------------------*/
6352 static void shiftRLong (operand *left, int offl,
6353 operand *result, int sign)
6356 emitcode("clr","c");
6357 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6359 emitcode("mov","c,acc.7");
6360 emitcode("rrc","a");
6361 aopPut(AOP(result),"a",MSB32-offl);
6363 /* add sign of "a" */
6364 addSign(result, MSB32, sign);
6366 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6367 emitcode("rrc","a");
6368 aopPut(AOP(result),"a",MSB24-offl);
6370 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6371 emitcode("rrc","a");
6372 aopPut(AOP(result),"a",MSB16-offl);
6375 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6376 emitcode("rrc","a");
6377 aopPut(AOP(result),"a",LSB);
6384 /*-----------------------------------------------------------------*/
6385 /* genrshFour - shift four byte by a known amount != 0 */
6386 /*-----------------------------------------------------------------*/
6387 static void genrshFour (operand *result, operand *left,
6388 int shCount, int sign)
6390 D(emitcode(";", "genrshFour"););
6392 /* if shifting more that 3 bytes */
6393 if(shCount >= 24 ) {
6396 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6398 movLeft2Result(left, MSB32, result, LSB, sign);
6399 addSign(result, MSB16, sign);
6401 else if(shCount >= 16){
6404 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6406 movLeft2Result(left, MSB24, result, LSB, 0);
6407 movLeft2Result(left, MSB32, result, MSB16, sign);
6409 addSign(result, MSB24, sign);
6411 else if(shCount >= 8){
6414 shiftRLong(left, MSB16, result, sign);
6415 else if(shCount == 0){
6416 movLeft2Result(left, MSB16, result, LSB, 0);
6417 movLeft2Result(left, MSB24, result, MSB16, 0);
6418 movLeft2Result(left, MSB32, result, MSB24, sign);
6419 addSign(result, MSB32, sign);
6422 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6423 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6424 /* the last shift is signed */
6425 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6426 addSign(result, MSB32, sign);
6429 else{ /* 1 <= shCount <= 7 */
6431 shiftRLong(left, LSB, result, sign);
6433 shiftRLong(result, LSB, result, sign);
6436 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6437 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6438 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6446 /*-----------------------------------------------------------------*/
6447 /* genRightShiftLiteral - right shifting by known count */
6448 /*-----------------------------------------------------------------*/
6449 static void genRightShiftLiteral (operand *left,
6455 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6458 D(emitcode(";", "genRightShiftLiteral"););
6460 freeAsmop(right,NULL,ic,TRUE);
6462 aopOp(left,ic,FALSE, FALSE);
6463 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6466 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6470 size = getDataSize(left);
6471 /* test the LEFT size !!! */
6473 /* I suppose that the left size >= result size */
6475 size = getDataSize(result);
6477 movLeft2Result(left, size, result, size, 0);
6480 else if(shCount >= (size * 8)){
6482 /* get sign in acc.7 */
6483 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6484 addSign(result, LSB, sign);
6488 genrshOne (result,left,shCount,sign);
6492 genrshTwo (result,left,shCount,sign);
6496 genrshFour (result,left,shCount,sign);
6502 freeAsmop(left,NULL,ic,TRUE);
6503 freeAsmop(result,NULL,ic,TRUE);
6508 /*-----------------------------------------------------------------*/
6509 /* genSignedRightShift - right shift of signed number */
6510 /*-----------------------------------------------------------------*/
6511 static void genSignedRightShift (iCode *ic)
6513 operand *right, *left, *result;
6516 symbol *tlbl, *tlbl1 ;
6518 D(emitcode(";", "genSignedRightShift "););
6520 /* we do it the hard way put the shift count in b
6521 and loop thru preserving the sign */
6523 right = IC_RIGHT(ic);
6525 result = IC_RESULT(ic);
6527 aopOp(right,ic,FALSE, FALSE);
6530 if ( AOP_TYPE(right) == AOP_LIT) {
6531 genRightShiftLiteral (left,right,result,ic,1);
6535 /* shift count is unknown then we have to form
6536 a loop get the loop count in B : Note: we take
6537 only the lower order byte since shifting
6538 more that 32 bits make no sense anyway, ( the
6539 largest size of an object can be only 32 bits ) */
6541 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6542 emitcode("inc","b");
6543 freeAsmop (right,NULL,ic,TRUE);
6544 aopOp(left,ic,FALSE, FALSE);
6545 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6547 /* now move the left to the result if they are not the
6549 if (!sameRegs(AOP(left),AOP(result)) &&
6550 AOP_SIZE(result) > 1) {
6552 size = AOP_SIZE(result);
6554 _startLazyDPSEvaluation();
6556 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6557 if (*l == '@' && IS_AOP_PREG(result)) {
6559 emitcode("mov","a,%s",l);
6560 aopPut(AOP(result),"a",offset);
6562 aopPut(AOP(result),l,offset);
6565 _endLazyDPSEvaluation();
6568 /* mov the highest order bit to OVR */
6569 tlbl = newiTempLabel(NULL);
6570 tlbl1= newiTempLabel(NULL);
6572 size = AOP_SIZE(result);
6574 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6575 emitcode("rlc","a");
6576 emitcode("mov","ov,c");
6577 /* if it is only one byte then */
6579 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6581 emitcode("sjmp","%05d$",tlbl1->key+100);
6582 emitcode("","%05d$:",tlbl->key+100);
6583 emitcode("mov","c,ov");
6584 emitcode("rrc","a");
6585 emitcode("","%05d$:",tlbl1->key+100);
6586 emitcode("djnz","b,%05d$",tlbl->key+100);
6587 aopPut(AOP(result),"a",0);
6591 reAdjustPreg(AOP(result));
6592 emitcode("sjmp","%05d$",tlbl1->key+100);
6593 emitcode("","%05d$:",tlbl->key+100);
6594 emitcode("mov","c,ov");
6595 _startLazyDPSEvaluation();
6597 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6599 emitcode("rrc","a");
6600 aopPut(AOP(result),"a",offset--);
6602 _endLazyDPSEvaluation();
6603 reAdjustPreg(AOP(result));
6604 emitcode("","%05d$:",tlbl1->key+100);
6605 emitcode("djnz","b,%05d$",tlbl->key+100);
6608 freeAsmop(left,NULL,ic,TRUE);
6609 freeAsmop(result,NULL,ic,TRUE);
6612 /*-----------------------------------------------------------------*/
6613 /* genRightShift - generate code for right shifting */
6614 /*-----------------------------------------------------------------*/
6615 static void genRightShift (iCode *ic)
6617 operand *right, *left, *result;
6621 symbol *tlbl, *tlbl1 ;
6623 D(emitcode(";", "genRightShift "););
6625 /* if signed then we do it the hard way preserve the
6626 sign bit moving it inwards */
6627 retype = getSpec(operandType(IC_RESULT(ic)));
6629 if (!SPEC_USIGN(retype)) {
6630 genSignedRightShift (ic);
6634 /* signed & unsigned types are treated the same : i.e. the
6635 signed is NOT propagated inwards : quoting from the
6636 ANSI - standard : "for E1 >> E2, is equivalent to division
6637 by 2**E2 if unsigned or if it has a non-negative value,
6638 otherwise the result is implementation defined ", MY definition
6639 is that the sign does not get propagated */
6641 right = IC_RIGHT(ic);
6643 result = IC_RESULT(ic);
6645 aopOp(right,ic,FALSE, FALSE);
6648 /* if the shift count is known then do it
6649 as efficiently as possible */
6650 if (AOP_TYPE(right) == AOP_LIT) {
6651 genRightShiftLiteral (left,right,result,ic, 0);
6656 /* shift count is unknown then we have to form
6657 a loop get the loop count in B : Note: we take
6658 only the lower order byte since shifting
6659 more that 32 bits make no sense anyway, ( the
6660 largest size of an object can be only 32 bits ) */
6662 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6663 emitcode("inc","b");
6664 freeAsmop (right,NULL,ic,TRUE);
6665 aopOp(left,ic,FALSE, FALSE);
6666 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6668 /* now move the left to the result if they are not the
6670 if (!sameRegs(AOP(left),AOP(result)) &&
6671 AOP_SIZE(result) > 1) {
6673 size = AOP_SIZE(result);
6675 _startLazyDPSEvaluation();
6677 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6678 if (*l == '@' && IS_AOP_PREG(result)) {
6680 emitcode("mov","a,%s",l);
6681 aopPut(AOP(result),"a",offset);
6683 aopPut(AOP(result),l,offset);
6686 _endLazyDPSEvaluation();
6689 tlbl = newiTempLabel(NULL);
6690 tlbl1= newiTempLabel(NULL);
6691 size = AOP_SIZE(result);
6694 /* if it is only one byte then */
6696 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6698 emitcode("sjmp","%05d$",tlbl1->key+100);
6699 emitcode("","%05d$:",tlbl->key+100);
6701 emitcode("rrc","a");
6702 emitcode("","%05d$:",tlbl1->key+100);
6703 emitcode("djnz","b,%05d$",tlbl->key+100);
6704 aopPut(AOP(result),"a",0);
6708 reAdjustPreg(AOP(result));
6709 emitcode("sjmp","%05d$",tlbl1->key+100);
6710 emitcode("","%05d$:",tlbl->key+100);
6712 _startLazyDPSEvaluation();
6714 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6716 emitcode("rrc","a");
6717 aopPut(AOP(result),"a",offset--);
6719 _endLazyDPSEvaluation();
6720 reAdjustPreg(AOP(result));
6722 emitcode("","%05d$:",tlbl1->key+100);
6723 emitcode("djnz","b,%05d$",tlbl->key+100);
6726 freeAsmop(left,NULL,ic,TRUE);
6727 freeAsmop(result,NULL,ic,TRUE);
6730 /*-----------------------------------------------------------------*/
6731 /* genUnpackBits - generates code for unpacking bits */
6732 /*-----------------------------------------------------------------*/
6733 static void genUnpackBits (operand *result, char *rname, int ptype)
6740 D(emitcode(";", "genUnpackBits "););
6742 etype = getSpec(operandType(result));
6744 /* read the first byte */
6749 emitcode("mov","a,@%s",rname);
6753 emitcode("movx","a,@%s",rname);
6757 emitcode("movx","a,@dptr");
6761 emitcode("clr","a");
6762 emitcode("movc","a","@a+dptr");
6766 emitcode("lcall","__gptrget");
6770 /* if we have bitdisplacement then it fits */
6771 /* into this byte completely or if length is */
6772 /* less than a byte */
6773 if ((shCnt = SPEC_BSTR(etype)) ||
6774 (SPEC_BLEN(etype) <= 8)) {
6776 /* shift right acc */
6779 emitcode("anl","a,#0x%02x",
6780 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6781 aopPut(AOP(result),"a",offset);
6785 /* bit field did not fit in a byte */
6786 rlen = SPEC_BLEN(etype) - 8;
6787 aopPut(AOP(result),"a",offset++);
6794 emitcode("inc","%s",rname);
6795 emitcode("mov","a,@%s",rname);
6799 emitcode("inc","%s",rname);
6800 emitcode("movx","a,@%s",rname);
6804 emitcode("inc","dptr");
6805 emitcode("movx","a,@dptr");
6809 emitcode("clr","a");
6810 emitcode("inc","dptr");
6811 emitcode("movc","a","@a+dptr");
6815 emitcode("inc","dptr");
6816 emitcode("lcall","__gptrget");
6821 /* if we are done */
6825 aopPut(AOP(result),"a",offset++);
6830 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6831 aopPut(AOP(result),"a",offset);
6838 /*-----------------------------------------------------------------*/
6839 /* genDataPointerGet - generates code when ptr offset is known */
6840 /*-----------------------------------------------------------------*/
6841 static void genDataPointerGet (operand *left,
6847 int size , offset = 0;
6848 aopOp(result,ic,TRUE, FALSE);
6850 /* get the string representation of the name */
6851 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6852 size = AOP_SIZE(result);
6853 _startLazyDPSEvaluation();
6856 sprintf(buffer,"(%s + %d)",l+1,offset);
6858 sprintf(buffer,"%s",l+1);
6859 aopPut(AOP(result),buffer,offset++);
6861 _endLazyDPSEvaluation();
6863 freeAsmop(left,NULL,ic,TRUE);
6864 freeAsmop(result,NULL,ic,TRUE);
6867 /*-----------------------------------------------------------------*/
6868 /* genNearPointerGet - emitcode for near pointer fetch */
6869 /*-----------------------------------------------------------------*/
6870 static void genNearPointerGet (operand *left,
6877 sym_link *rtype, *retype, *letype;
6878 sym_link *ltype = operandType(left);
6881 rtype = operandType(result);
6882 retype= getSpec(rtype);
6883 letype= getSpec(ltype);
6885 aopOp(left,ic,FALSE, FALSE);
6887 /* if left is rematerialisable and
6888 result is not bit variable type and
6889 the left is pointer to data space i.e
6890 lower 128 bytes of space */
6891 if (AOP_TYPE(left) == AOP_IMMD &&
6892 !IS_BITVAR(retype) &&
6893 !IS_BITVAR(letype) &&
6894 DCL_TYPE(ltype) == POINTER) {
6895 genDataPointerGet (left,result,ic);
6899 /* if the value is already in a pointer register
6900 then don't need anything more */
6901 if (!AOP_INPREG(AOP(left))) {
6902 /* otherwise get a free pointer register */
6904 preg = getFreePtr(ic,&aop,FALSE);
6905 emitcode("mov","%s,%s",
6907 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6908 rname = preg->name ;
6910 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6912 freeAsmop(left,NULL,ic,TRUE);
6913 aopOp (result,ic,FALSE, FALSE);
6915 /* if bitfield then unpack the bits */
6916 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6917 genUnpackBits (result,rname,POINTER);
6919 /* we have can just get the values */
6920 int size = AOP_SIZE(result);
6924 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6926 emitcode("mov","a,@%s",rname);
6927 aopPut(AOP(result),"a",offset);
6929 sprintf(buffer,"@%s",rname);
6930 aopPut(AOP(result),buffer,offset);
6934 emitcode("inc","%s",rname);
6938 /* now some housekeeping stuff */
6940 /* we had to allocate for this iCode */
6941 freeAsmop(NULL,aop,ic,TRUE);
6943 /* we did not allocate which means left
6944 already in a pointer register, then
6945 if size > 0 && this could be used again
6946 we have to point it back to where it
6948 if (AOP_SIZE(result) > 1 &&
6949 !OP_SYMBOL(left)->remat &&
6950 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6952 int size = AOP_SIZE(result) - 1;
6954 emitcode("dec","%s",rname);
6959 freeAsmop(result,NULL,ic,TRUE);
6963 /*-----------------------------------------------------------------*/
6964 /* genPagedPointerGet - emitcode for paged pointer fetch */
6965 /*-----------------------------------------------------------------*/
6966 static void genPagedPointerGet (operand *left,
6973 sym_link *rtype, *retype, *letype;
6975 rtype = operandType(result);
6976 retype= getSpec(rtype);
6977 letype= getSpec(operandType(left));
6978 aopOp(left,ic,FALSE, FALSE);
6980 /* if the value is already in a pointer register
6981 then don't need anything more */
6982 if (!AOP_INPREG(AOP(left))) {
6983 /* otherwise get a free pointer register */
6985 preg = getFreePtr(ic,&aop,FALSE);
6986 emitcode("mov","%s,%s",
6988 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6989 rname = preg->name ;
6991 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6993 freeAsmop(left,NULL,ic,TRUE);
6994 aopOp (result,ic,FALSE, FALSE);
6996 /* if bitfield then unpack the bits */
6997 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6998 genUnpackBits (result,rname,PPOINTER);
7000 /* we have can just get the values */
7001 int size = AOP_SIZE(result);
7006 emitcode("movx","a,@%s",rname);
7007 aopPut(AOP(result),"a",offset);
7012 emitcode("inc","%s",rname);
7016 /* now some housekeeping stuff */
7018 /* we had to allocate for this iCode */
7019 freeAsmop(NULL,aop,ic,TRUE);
7021 /* we did not allocate which means left
7022 already in a pointer register, then
7023 if size > 0 && this could be used again
7024 we have to point it back to where it
7026 if (AOP_SIZE(result) > 1 &&
7027 !OP_SYMBOL(left)->remat &&
7028 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7030 int size = AOP_SIZE(result) - 1;
7032 emitcode("dec","%s",rname);
7037 freeAsmop(result,NULL,ic,TRUE);
7042 /*-----------------------------------------------------------------*/
7043 /* genFarPointerGet - gget value from far space */
7044 /*-----------------------------------------------------------------*/
7045 static void genFarPointerGet (operand *left,
7046 operand *result, iCode *ic)
7049 sym_link *retype = getSpec(operandType(result));
7050 sym_link *letype = getSpec(operandType(left));
7051 D(emitcode(";", "genFarPointerGet"););
7053 aopOp(left,ic,FALSE, FALSE);
7055 /* if the operand is already in dptr
7056 then we do nothing else we move the value to dptr */
7057 if (AOP_TYPE(left) != AOP_STR) {
7058 /* if this is remateriazable */
7059 if (AOP_TYPE(left) == AOP_IMMD)
7061 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7065 /* we need to get it byte by byte */
7066 _startLazyDPSEvaluation();
7067 if (AOP_TYPE(left) != AOP_DPTR)
7069 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7070 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7071 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7075 /* We need to generate a load to DPTR indirect through DPTR. */
7076 D(emitcode(";", "genFarPointerGet -- indirection special case."););
7077 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7078 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7079 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7080 emitcode("pop", "dph");
7081 emitcode("pop", "dpl");
7083 _endLazyDPSEvaluation();
7086 /* so dptr know contains the address */
7087 freeAsmop(left,NULL,ic,TRUE);
7088 aopOp(result,ic,FALSE, TRUE);
7090 /* if bit then unpack */
7091 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7092 genUnpackBits(result,"dptr",FPOINTER);
7094 size = AOP_SIZE(result);
7097 _startLazyDPSEvaluation();
7103 emitcode("movx","a,@dptr");
7105 emitcode("inc","dptr");
7107 aopPut(AOP(result),"a",offset++);
7109 _endLazyDPSEvaluation();
7112 freeAsmop(result,NULL,ic,TRUE);
7115 /*-----------------------------------------------------------------*/
7116 /* emitcodePointerGet - gget value from code space */
7117 /*-----------------------------------------------------------------*/
7118 static void emitcodePointerGet (operand *left,
7119 operand *result, iCode *ic)
7122 sym_link *retype = getSpec(operandType(result));
7124 aopOp(left,ic,FALSE, FALSE);
7126 /* if the operand is already in dptr
7127 then we do nothing else we move the value to dptr */
7128 if (AOP_TYPE(left) != AOP_STR) {
7129 /* if this is remateriazable */
7130 if (AOP_TYPE(left) == AOP_IMMD)
7132 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7135 { /* we need to get it byte by byte */
7136 _startLazyDPSEvaluation();
7137 if (AOP_TYPE(left) != AOP_DPTR)
7139 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7140 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7141 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7145 /* We need to generate a load to DPTR indirect through DPTR. */
7146 D(emitcode(";", "gencodePointerGet -- indirection special case."););
7147 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7148 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7149 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7150 emitcode("pop", "dph");
7151 emitcode("pop", "dpl");
7153 _endLazyDPSEvaluation();
7156 /* so dptr know contains the address */
7157 freeAsmop(left,NULL,ic,TRUE);
7158 aopOp(result,ic,FALSE, TRUE);
7160 /* if bit then unpack */
7161 if (IS_BITVAR(retype))
7162 genUnpackBits(result,"dptr",CPOINTER);
7164 size = AOP_SIZE(result);
7167 _startLazyDPSEvaluation();
7173 emitcode("clr","a");
7174 emitcode("movc","a,@a+dptr");
7176 emitcode("inc","dptr");
7177 aopPut(AOP(result),"a",offset++);
7179 _endLazyDPSEvaluation();
7182 freeAsmop(result,NULL,ic,TRUE);
7185 /*-----------------------------------------------------------------*/
7186 /* genGenPointerGet - gget value from generic pointer space */
7187 /*-----------------------------------------------------------------*/
7188 static void genGenPointerGet (operand *left,
7189 operand *result, iCode *ic)
7192 sym_link *retype = getSpec(operandType(result));
7193 sym_link *letype = getSpec(operandType(left));
7195 aopOp(left,ic,FALSE, TRUE);
7197 /* if the operand is already in dptr
7198 then we do nothing else we move the value to dptr */
7199 if (AOP_TYPE(left) != AOP_STR) {
7200 /* if this is remateriazable */
7201 if (AOP_TYPE(left) == AOP_IMMD) {
7202 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7203 emitcode("mov","b,#%d",pointerCode(retype));
7205 else { /* we need to get it byte by byte */
7206 _startLazyDPSEvaluation();
7207 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7208 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7209 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7210 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7211 _endLazyDPSEvaluation();
7214 /* so dptr know contains the address */
7215 freeAsmop(left,NULL,ic,TRUE);
7216 aopOp(result,ic,FALSE, TRUE);
7218 /* if bit then unpack */
7219 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7220 genUnpackBits(result,"dptr",GPOINTER);
7222 size = AOP_SIZE(result);
7226 emitcode("lcall","__gptrget");
7227 aopPut(AOP(result),"a",offset++);
7229 emitcode("inc","dptr");
7233 freeAsmop(result,NULL,ic,TRUE);
7236 /*-----------------------------------------------------------------*/
7237 /* genPointerGet - generate code for pointer get */
7238 /*-----------------------------------------------------------------*/
7239 static void genPointerGet (iCode *ic)
7241 operand *left, *result ;
7242 sym_link *type, *etype;
7245 D(emitcode(";", "genPointerGet "););
7248 result = IC_RESULT(ic) ;
7250 /* depending on the type of pointer we need to
7251 move it to the correct pointer register */
7252 type = operandType(left);
7253 etype = getSpec(type);
7254 /* if left is of type of pointer then it is simple */
7255 if (IS_PTR(type) && !IS_FUNC(type->next))
7256 p_type = DCL_TYPE(type);
7258 /* we have to go by the storage class */
7259 p_type = PTR_TYPE(SPEC_OCLS(etype));
7262 /* now that we have the pointer type we assign
7263 the pointer values */
7268 genNearPointerGet (left,result,ic);
7272 genPagedPointerGet(left,result,ic);
7276 genFarPointerGet (left,result,ic);
7280 emitcodePointerGet (left,result,ic);
7284 genGenPointerGet (left,result,ic);
7290 /*-----------------------------------------------------------------*/
7291 /* genPackBits - generates code for packed bit storage */
7292 /*-----------------------------------------------------------------*/
7293 static void genPackBits (sym_link *etype ,
7295 char *rname, int p_type)
7303 blen = SPEC_BLEN(etype);
7304 bstr = SPEC_BSTR(etype);
7306 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7309 /* if the bit lenth is less than or */
7310 /* it exactly fits a byte then */
7311 if (SPEC_BLEN(etype) <= 8 ) {
7312 shCount = SPEC_BSTR(etype) ;
7314 /* shift left acc */
7317 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7322 emitcode ("mov","b,a");
7323 emitcode("mov","a,@%s",rname);
7327 emitcode ("mov","b,a");
7328 emitcode("movx","a,@dptr");
7332 emitcode ("push","b");
7333 emitcode ("push","acc");
7334 emitcode ("lcall","__gptrget");
7335 emitcode ("pop","b");
7339 emitcode ("anl","a,#0x%02x",(unsigned char)
7340 ((unsigned char)(0xFF << (blen+bstr)) |
7341 (unsigned char)(0xFF >> (8-bstr)) ) );
7342 emitcode ("orl","a,b");
7343 if (p_type == GPOINTER)
7344 emitcode("pop","b");
7350 emitcode("mov","@%s,a",rname);
7354 emitcode("movx","@dptr,a");
7358 emitcode("lcall","__gptrput");
7363 if ( SPEC_BLEN(etype) <= 8 )
7366 emitcode("inc","%s",rname);
7367 rLen = SPEC_BLEN(etype) ;
7369 /* now generate for lengths greater than one byte */
7372 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7382 emitcode("mov","@%s,a",rname);
7384 emitcode("mov","@%s,%s",rname,l);
7389 emitcode("movx","@dptr,a");
7394 emitcode("lcall","__gptrput");
7397 emitcode ("inc","%s",rname);
7402 /* last last was not complete */
7404 /* save the byte & read byte */
7407 emitcode ("mov","b,a");
7408 emitcode("mov","a,@%s",rname);
7412 emitcode ("mov","b,a");
7413 emitcode("movx","a,@dptr");
7417 emitcode ("push","b");
7418 emitcode ("push","acc");
7419 emitcode ("lcall","__gptrget");
7420 emitcode ("pop","b");
7424 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << rLen) );
7425 emitcode ("orl","a,b");
7428 if (p_type == GPOINTER)
7429 emitcode("pop","b");
7434 emitcode("mov","@%s,a",rname);
7438 emitcode("movx","@dptr,a");
7442 emitcode("lcall","__gptrput");
7446 /*-----------------------------------------------------------------*/
7447 /* genDataPointerSet - remat pointer to data space */
7448 /*-----------------------------------------------------------------*/
7449 static void genDataPointerSet(operand *right,
7453 int size, offset = 0 ;
7454 char *l, buffer[256];
7456 aopOp(right,ic,FALSE, FALSE);
7458 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7459 size = AOP_SIZE(right);
7462 sprintf(buffer,"(%s + %d)",l+1,offset);
7464 sprintf(buffer,"%s",l+1);
7465 emitcode("mov","%s,%s",buffer,
7466 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7469 freeAsmop(right,NULL,ic,TRUE);
7470 freeAsmop(result,NULL,ic,TRUE);
7473 /*-----------------------------------------------------------------*/
7474 /* genNearPointerSet - emitcode for near pointer put */
7475 /*-----------------------------------------------------------------*/
7476 static void genNearPointerSet (operand *right,
7483 sym_link *retype, *letype;
7484 sym_link *ptype = operandType(result);
7486 retype= getSpec(operandType(right));
7487 letype= getSpec(ptype);
7489 aopOp(result,ic,FALSE, FALSE);
7491 /* if the result is rematerializable &
7492 in data space & not a bit variable */
7493 if (AOP_TYPE(result) == AOP_IMMD &&
7494 DCL_TYPE(ptype) == POINTER &&
7495 !IS_BITVAR(retype) &&
7496 !IS_BITVAR(letype)) {
7497 genDataPointerSet (right,result,ic);
7501 /* if the value is already in a pointer register
7502 then don't need anything more */
7503 if (!AOP_INPREG(AOP(result))) {
7504 /* otherwise get a free pointer register */
7506 preg = getFreePtr(ic,&aop,FALSE);
7507 emitcode("mov","%s,%s",
7509 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7510 rname = preg->name ;
7512 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7514 freeAsmop(result,NULL,ic,TRUE);
7515 aopOp (right,ic,FALSE, FALSE);
7517 /* if bitfield then unpack the bits */
7518 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7519 genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
7521 /* we have can just get the values */
7522 int size = AOP_SIZE(right);
7526 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7529 emitcode("mov","@%s,a",rname);
7531 emitcode("mov","@%s,%s",rname,l);
7533 emitcode("inc","%s",rname);
7538 /* now some housekeeping stuff */
7540 /* we had to allocate for this iCode */
7541 freeAsmop(NULL,aop,ic,TRUE);
7543 /* we did not allocate which means left
7544 already in a pointer register, then
7545 if size > 0 && this could be used again
7546 we have to point it back to where it
7548 if (AOP_SIZE(right) > 1 &&
7549 !OP_SYMBOL(result)->remat &&
7550 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7552 int size = AOP_SIZE(right) - 1;
7554 emitcode("dec","%s",rname);
7559 freeAsmop(right,NULL,ic,TRUE);
7564 /*-----------------------------------------------------------------*/
7565 /* genPagedPointerSet - emitcode for Paged pointer put */
7566 /*-----------------------------------------------------------------*/
7567 static void genPagedPointerSet (operand *right,
7574 sym_link *retype, *letype;
7576 retype= getSpec(operandType(right));
7577 letype= getSpec(operandType(result));
7579 aopOp(result,ic,FALSE, FALSE);
7581 /* if the value is already in a pointer register
7582 then don't need anything more */
7583 if (!AOP_INPREG(AOP(result))) {
7584 /* otherwise get a free pointer register */
7586 preg = getFreePtr(ic,&aop,FALSE);
7587 emitcode("mov","%s,%s",
7589 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7590 rname = preg->name ;
7592 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7594 freeAsmop(result,NULL,ic,TRUE);
7595 aopOp (right,ic,FALSE, FALSE);
7597 /* if bitfield then unpack the bits */
7598 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7599 genPackBits ((IS_BITVAR(retype) ? retype : letype) ,right,rname,PPOINTER);
7601 /* we have can just get the values */
7602 int size = AOP_SIZE(right);
7606 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7609 emitcode("movx","@%s,a",rname);
7612 emitcode("inc","%s",rname);
7618 /* now some housekeeping stuff */
7620 /* we had to allocate for this iCode */
7621 freeAsmop(NULL,aop,ic,TRUE);
7623 /* we did not allocate which means left
7624 already in a pointer register, then
7625 if size > 0 && this could be used again
7626 we have to point it back to where it
7628 if (AOP_SIZE(right) > 1 &&
7629 !OP_SYMBOL(result)->remat &&
7630 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7632 int size = AOP_SIZE(right) - 1;
7634 emitcode("dec","%s",rname);
7639 freeAsmop(right,NULL,ic,TRUE);
7644 /*-----------------------------------------------------------------*/
7645 /* genFarPointerSet - set value from far space */
7646 /*-----------------------------------------------------------------*/
7647 static void genFarPointerSet (operand *right,
7648 operand *result, iCode *ic)
7651 sym_link *retype = getSpec(operandType(right));
7652 sym_link *letype = getSpec(operandType(result));
7654 aopOp(result,ic,FALSE, FALSE);
7656 /* if the operand is already in dptr
7657 then we do nothing else we move the value to dptr */
7658 if (AOP_TYPE(result) != AOP_STR) {
7659 /* if this is remateriazable */
7660 if (AOP_TYPE(result) == AOP_IMMD)
7661 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7664 /* we need to get it byte by byte */
7665 _startLazyDPSEvaluation();
7666 if (AOP_TYPE(result) != AOP_DPTR)
7668 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7669 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7670 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7674 /* We need to generate a load to DPTR indirect through DPTR. */
7675 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7676 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7677 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7678 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7679 emitcode("pop", "dph");
7680 emitcode("pop", "dpl");
7682 _endLazyDPSEvaluation();
7685 /* so dptr know contains the address */
7686 freeAsmop(result,NULL,ic,TRUE);
7687 aopOp(right,ic,FALSE, TRUE);
7689 /* if bit then unpack */
7690 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7691 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",FPOINTER);
7693 size = AOP_SIZE(right);
7696 _startLazyDPSEvaluation();
7698 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7704 emitcode("movx","@dptr,a");
7706 emitcode("inc","dptr");
7708 _endLazyDPSEvaluation();
7711 freeAsmop(right,NULL,ic,TRUE);
7714 /*-----------------------------------------------------------------*/
7715 /* genGenPointerSet - set value from generic pointer space */
7716 /*-----------------------------------------------------------------*/
7717 static void genGenPointerSet (operand *right,
7718 operand *result, iCode *ic)
7721 sym_link *retype = getSpec(operandType(right));
7722 sym_link *letype = getSpec(operandType(result));
7724 aopOp(result,ic,FALSE, TRUE);
7726 /* if the operand is already in dptr
7727 then we do nothing else we move the value to dptr */
7728 if (AOP_TYPE(result) != AOP_STR) {
7729 _startLazyDPSEvaluation();
7730 /* if this is remateriazable */
7731 if (AOP_TYPE(result) == AOP_IMMD) {
7732 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7733 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7735 else { /* we need to get it byte by byte */
7736 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7737 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7738 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7739 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7741 _endLazyDPSEvaluation();
7743 /* so dptr know contains the address */
7744 freeAsmop(result,NULL,ic,TRUE);
7745 aopOp(right,ic,FALSE, TRUE);
7747 /* if bit then unpack */
7748 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7749 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",GPOINTER);
7751 size = AOP_SIZE(right);
7754 _startLazyDPSEvaluation();
7756 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7762 emitcode("lcall","__gptrput");
7764 emitcode("inc","dptr");
7766 _endLazyDPSEvaluation();
7769 freeAsmop(right,NULL,ic,TRUE);
7772 /*-----------------------------------------------------------------*/
7773 /* genPointerSet - stores the value into a pointer location */
7774 /*-----------------------------------------------------------------*/
7775 static void genPointerSet (iCode *ic)
7777 operand *right, *result ;
7778 sym_link *type, *etype;
7781 D(emitcode(";", "genPointerSet "););
7783 right = IC_RIGHT(ic);
7784 result = IC_RESULT(ic) ;
7786 /* depending on the type of pointer we need to
7787 move it to the correct pointer register */
7788 type = operandType(result);
7789 etype = getSpec(type);
7790 /* if left is of type of pointer then it is simple */
7791 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7792 p_type = DCL_TYPE(type);
7795 /* we have to go by the storage class */
7796 p_type = PTR_TYPE(SPEC_OCLS(etype));
7799 /* now that we have the pointer type we assign
7800 the pointer values */
7805 genNearPointerSet (right,result,ic);
7809 genPagedPointerSet (right,result,ic);
7813 genFarPointerSet (right,result,ic);
7817 genGenPointerSet (right,result,ic);
7823 /*-----------------------------------------------------------------*/
7824 /* genIfx - generate code for Ifx statement */
7825 /*-----------------------------------------------------------------*/
7826 static void genIfx (iCode *ic, iCode *popIc)
7828 operand *cond = IC_COND(ic);
7831 D(emitcode(";", "genIfx "););
7833 aopOp(cond,ic,FALSE, FALSE);
7835 /* get the value into acc */
7836 if (AOP_TYPE(cond) != AOP_CRY)
7840 /* the result is now in the accumulator */
7841 freeAsmop(cond,NULL,ic,TRUE);
7843 /* if there was something to be popped then do it */
7847 /* if the condition is a bit variable */
7848 if (isbit && IS_ITEMP(cond) &&
7850 genIfxJump(ic,SPIL_LOC(cond)->rname);
7852 if (isbit && !IS_ITEMP(cond))
7853 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7860 /*-----------------------------------------------------------------*/
7861 /* genAddrOf - generates code for address of */
7862 /*-----------------------------------------------------------------*/
7863 static void genAddrOf (iCode *ic)
7865 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7868 D(emitcode(";", "genAddrOf "););
7870 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7872 /* if the operand is on the stack then we
7873 need to get the stack offset of this
7876 /* if it has an offset then we need to compute
7879 emitcode("mov","a,_bp");
7880 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7881 aopPut(AOP(IC_RESULT(ic)),"a",0);
7883 /* we can just move _bp */
7884 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7886 /* fill the result with zero */
7887 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7890 if (options.stack10bit && size < (FPTRSIZE - 1))
7893 "*** warning: pointer to stack var truncated.\n");
7900 if (options.stack10bit && offset == 2)
7902 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7906 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7913 /* object not on stack then we need the name */
7914 size = AOP_SIZE(IC_RESULT(ic));
7918 char s[SDCC_NAME_MAX];
7920 sprintf(s,"#(%s >> %d)",
7924 sprintf(s,"#%s",sym->rname);
7925 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7929 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7933 /*-----------------------------------------------------------------*/
7934 /* genFarFarAssign - assignment when both are in far space */
7935 /*-----------------------------------------------------------------*/
7936 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7938 int size = AOP_SIZE(right);
7945 /* This is a net loss for size == 1, but a big gain
7948 D(emitcode(";", "genFarFarAssign (improved)"););
7950 aopOp(result,ic,TRUE, TRUE);
7952 _startLazyDPSEvaluation();
7956 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7960 _endLazyDPSEvaluation();
7961 freeAsmop(result,NULL,ic,FALSE);
7962 freeAsmop(right,NULL,ic,FALSE);
7967 D(emitcode(";", "genFarFarAssign "););
7969 /* first push the right side on to the stack */
7970 _startLazyDPSEvaluation();
7972 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7974 emitcode ("push","acc");
7977 freeAsmop(right,NULL,ic,FALSE);
7978 /* now assign DPTR to result */
7979 aopOp(result,ic,FALSE, FALSE);
7980 size = AOP_SIZE(result);
7982 emitcode ("pop","acc");
7983 aopPut(AOP(result),"a",--offset);
7985 freeAsmop(result,NULL,ic,FALSE);
7986 _endLazyDPSEvaluation();
7990 /*-----------------------------------------------------------------*/
7991 /* genAssign - generate code for assignment */
7992 /*-----------------------------------------------------------------*/
7993 static void genAssign (iCode *ic)
7995 operand *result, *right;
7997 unsigned long lit = 0L;
7999 D(emitcode(";", "genAssign "););
8001 result = IC_RESULT(ic);
8002 right = IC_RIGHT(ic) ;
8004 /* if they are the same */
8005 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8008 aopOp(right,ic,FALSE, FALSE);
8010 emitcode(";", "genAssign: resultIsFar = %s",
8011 isOperandInFarSpace(result) ?
8014 /* special case both in far space */
8015 if ((AOP_TYPE(right) == AOP_DPTR ||
8016 AOP_TYPE(right) == AOP_DPTR2) &&
8017 /* IS_TRUE_SYMOP(result) && */
8018 isOperandInFarSpace(result)) {
8020 genFarFarAssign (result,right,ic);
8024 aopOp(result,ic,TRUE, FALSE);
8026 /* if they are the same registers */
8027 if (sameRegs(AOP(right),AOP(result)))
8030 /* if the result is a bit */
8031 if (AOP_TYPE(result) == AOP_CRY) {
8033 /* if the right size is a literal then
8034 we know what the value is */
8035 if (AOP_TYPE(right) == AOP_LIT) {
8036 if (((int) operandLitValue(right)))
8037 aopPut(AOP(result),one,0);
8039 aopPut(AOP(result),zero,0);
8043 /* the right is also a bit variable */
8044 if (AOP_TYPE(right) == AOP_CRY) {
8045 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8046 aopPut(AOP(result),"c",0);
8052 aopPut(AOP(result),"a",0);
8056 /* bit variables done */
8058 size = AOP_SIZE(result);
8060 if(AOP_TYPE(right) == AOP_LIT)
8061 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8064 (AOP_TYPE(result) != AOP_REG) &&
8065 (AOP_TYPE(right) == AOP_LIT) &&
8066 !IS_FLOAT(operandType(right))
8067 #ifndef LAZY_DPS_OPT
8073 D(emitcode(";", "Kevin's better literal load code"););
8074 _startLazyDPSEvaluation();
8075 while (size && ((unsigned int)(lit >> (offset*8)) != 0))
8078 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
8083 /* And now fill the rest with zeros. */
8086 emitcode("clr","a");
8090 aopPut(AOP(result), "a", offset++);
8092 _endLazyDPSEvaluation();
8094 emitcode("clr","a");
8096 _startLazyDPSEvaluation();
8099 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
8100 aopPut(AOP(result),"a",size);
8103 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
8106 _endLazyDPSEvaluation();
8111 _startLazyDPSEvaluation();
8115 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8119 _endLazyDPSEvaluation();
8123 freeAsmop (right,NULL,ic,FALSE);
8124 freeAsmop (result,NULL,ic,TRUE);
8127 /*-----------------------------------------------------------------*/
8128 /* genJumpTab - generates code for jump table */
8129 /*-----------------------------------------------------------------*/
8130 static void genJumpTab (iCode *ic)
8135 D(emitcode(";", "genJumpTab "););
8137 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
8138 /* get the condition into accumulator */
8139 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
8141 /* multiply by four! */
8142 emitcode("add","a,acc");
8143 emitcode("add","a,acc");
8144 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8146 jtab = newiTempLabel(NULL);
8147 emitcode("mov","dptr,#%05d$",jtab->key+100);
8148 emitcode("jmp","@a+dptr");
8149 emitcode("","%05d$:",jtab->key+100);
8150 /* now generate the jump labels */
8151 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8152 jtab = setNextItem(IC_JTLABELS(ic)))
8153 emitcode("ljmp","%05d$",jtab->key+100);
8157 /*-----------------------------------------------------------------*/
8158 /* genCast - gen code for casting */
8159 /*-----------------------------------------------------------------*/
8160 static void genCast (iCode *ic)
8162 operand *result = IC_RESULT(ic);
8163 sym_link *ctype = operandType(IC_LEFT(ic));
8164 sym_link *rtype = operandType(IC_RIGHT(ic));
8165 operand *right = IC_RIGHT(ic);
8168 D(emitcode(";", "genCast "););
8170 /* if they are equivalent then do nothing */
8171 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8174 aopOp(right,ic,FALSE, FALSE) ;
8175 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
8177 /* if the result is a bit */
8178 if (AOP_TYPE(result) == AOP_CRY) {
8179 /* if the right size is a literal then
8180 we know what the value is */
8181 if (AOP_TYPE(right) == AOP_LIT) {
8182 if (((int) operandLitValue(right)))
8183 aopPut(AOP(result),one,0);
8185 aopPut(AOP(result),zero,0);
8190 /* the right is also a bit variable */
8191 if (AOP_TYPE(right) == AOP_CRY) {
8192 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8193 aopPut(AOP(result),"c",0);
8199 aopPut(AOP(result),"a",0);
8203 /* if they are the same size : or less */
8204 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8206 /* if they are in the same place */
8207 if (sameRegs(AOP(right),AOP(result)))
8210 /* if they in different places then copy */
8211 size = AOP_SIZE(result);
8213 _startLazyDPSEvaluation();
8216 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8220 _endLazyDPSEvaluation();
8225 /* if the result is of type pointer */
8226 if (IS_PTR(ctype)) {
8229 sym_link *type = operandType(right);
8231 /* pointer to generic pointer */
8232 if (IS_GENPTR(ctype)) {
8237 p_type = DCL_TYPE(type);
8241 #if OLD_CAST_BEHAVIOR
8242 /* KV: we are converting a non-pointer type to
8243 * a generic pointer. This (ifdef'd out) code
8244 * says that the resulting generic pointer
8245 * should have the same class as the storage
8246 * location of the non-pointer variable.
8248 * For example, converting an int (which happens
8249 * to be stored in DATA space) to a pointer results
8250 * in a DATA generic pointer; if the original int
8251 * in XDATA space, so will be the resulting pointer.
8253 * I don't like that behavior, and thus this change:
8254 * all such conversions will be forced to XDATA and
8255 * throw a warning. If you want some non-XDATA
8256 * type, or you want to suppress the warning, you
8257 * must go through an intermediate cast, like so:
8259 * char _generic *gp = (char _xdata *)(intVar);
8261 sym_link *etype = getSpec(type);
8263 /* we have to go by the storage class */
8264 if (SPEC_OCLS(etype) != generic)
8266 p_type = PTR_TYPE(SPEC_OCLS(etype));
8271 /* Converting unknown class (i.e. register variable)
8272 * to generic pointer. This is not good, but
8273 * we'll make a guess (and throw a warning).
8276 werror(W_INT_TO_GEN_PTR_CAST);
8280 /* the first two bytes are known */
8281 size = GPTRSIZE - 1;
8283 _startLazyDPSEvaluation();
8286 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8290 _endLazyDPSEvaluation();
8292 /* the last byte depending on type */
8309 /* this should never happen */
8310 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8311 "got unknown pointer type");
8314 aopPut(AOP(result),l, GPTRSIZE - 1);
8318 /* just copy the pointers */
8319 size = AOP_SIZE(result);
8321 _startLazyDPSEvaluation();
8324 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8328 _endLazyDPSEvaluation();
8332 /* so we now know that the size of destination is greater
8333 than the size of the source */
8334 /* we move to result for the size of source */
8335 size = AOP_SIZE(right);
8337 _startLazyDPSEvaluation();
8340 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8344 _endLazyDPSEvaluation();
8346 /* now depending on the sign of the source && destination */
8347 size = AOP_SIZE(result) - AOP_SIZE(right);
8348 /* if unsigned or not an integral type */
8349 /* also, if the source is a bit, we don't need to sign extend, because
8350 * it can't possibly have set the sign bit.
8352 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype) || AOP_TYPE(right) == AOP_CRY)
8356 aopPut(AOP(result),zero,offset++);
8361 /* we need to extend the sign :{ */
8362 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8365 emitcode("rlc","a");
8366 emitcode("subb","a,acc");
8368 aopPut(AOP(result),"a",offset++);
8371 /* we are done hurray !!!! */
8374 freeAsmop(right,NULL,ic,TRUE);
8375 freeAsmop(result,NULL,ic,TRUE);
8379 /*-----------------------------------------------------------------*/
8380 /* genDjnz - generate decrement & jump if not zero instrucion */
8381 /*-----------------------------------------------------------------*/
8382 static int genDjnz (iCode *ic, iCode *ifx)
8388 /* if the if condition has a false label
8389 then we cannot save */
8393 /* if the minus is not of the form
8395 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8396 !IS_OP_LITERAL(IC_RIGHT(ic)))
8399 if (operandLitValue(IC_RIGHT(ic)) != 1)
8402 /* if the size of this greater than one then no
8404 if (getSize(operandType(IC_RESULT(ic))) > 1)
8407 /* otherwise we can save BIG */
8408 lbl = newiTempLabel(NULL);
8409 lbl1= newiTempLabel(NULL);
8411 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8413 if (IS_AOP_PREG(IC_RESULT(ic))) {
8414 emitcode("dec","%s",
8415 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8416 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8417 emitcode("jnz","%05d$",lbl->key+100);
8419 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8422 emitcode ("sjmp","%05d$",lbl1->key+100);
8423 emitcode ("","%05d$:",lbl->key+100);
8424 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8425 emitcode ("","%05d$:",lbl1->key+100);
8427 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8432 /*-----------------------------------------------------------------*/
8433 /* genReceive - generate code for a receive iCode */
8434 /*-----------------------------------------------------------------*/
8435 static void genReceive (iCode *ic)
8438 D(emitcode(";", "genReceive "););
8440 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8441 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8442 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8443 int size = getSize(operandType(IC_RESULT(ic)));
8444 int offset = fReturnSize_390 - size;
8446 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8447 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8450 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8451 size = AOP_SIZE(IC_RESULT(ic));
8454 emitcode ("pop","acc");
8455 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8460 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8462 assignResultValue(IC_RESULT(ic));
8465 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8468 /*-----------------------------------------------------------------*/
8469 /* gen390Code - generate code for Dallas 390 based controllers */
8470 /*-----------------------------------------------------------------*/
8471 void gen390Code (iCode *lic)
8476 lineHead = lineCurr = NULL;
8480 /* print the allocation information */
8482 printAllocInfo( currFunc, codeOutFile);
8484 /* if debug information required */
8485 if (options.debug && currFunc) {
8486 //jwk if (currFunc) {
8487 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8489 if (IS_STATIC(currFunc->etype))
8490 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8492 emitcode("","G$%s$0$0 ==.",currFunc->name);
8495 /* stack pointer name */
8496 if (options.useXstack)
8502 for (ic = lic ; ic ; ic = ic->next ) {
8504 if ( cln != ic->lineno ) {
8505 if ( options.debug ) {
8507 emitcode("","C$%s$%d$%d$%d ==.",
8508 ic->filename,ic->lineno,
8509 ic->level,ic->block);
8512 emitcode(";","%s %d",ic->filename,ic->lineno);
8515 /* if the result is marked as
8516 spilt and rematerializable or code for
8517 this has already been generated then
8519 if (resultRemat(ic) || ic->generated )
8522 /* depending on the operation */
8541 /* IPOP happens only when trying to restore a
8542 spilt live range, if there is an ifx statement
8543 following this pop then the if statement might
8544 be using some of the registers being popped which
8545 would destory the contents of the register so
8546 we need to check for this condition and handle it */
8548 ic->next->op == IFX &&
8549 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8550 genIfx (ic->next,ic);
8568 genEndFunction (ic);
8588 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8605 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8609 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8616 /* note these two are xlated by algebraic equivalence
8617 during parsing SDCC.y */
8618 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8619 "got '>=' or '<=' shouldn't have come here");
8623 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8635 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8639 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8643 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8670 case GET_VALUE_AT_ADDRESS:
8675 if (POINTER_SET(ic))
8702 addSet(&_G.sendSet,ic);
8707 /* piCode(ic,stdout); */
8713 /* now we are ready to call the
8714 peep hole optimizer */
8715 if (!options.nopeep)
8716 peepHole (&lineHead);
8718 /* now do the actual printing */
8719 printLine (lineHead,codeOutFile);