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 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2973 isOperandInFarSpace(IC_RESULT(ic))) \
2975 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
2980 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
2981 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2983 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2984 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2986 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2988 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2992 #define AOP_OP_2(ic) \
2993 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2994 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
2999 #define AOP_SET_LOCALS(ic) \
3000 left = IC_LEFT(ic); \
3001 right = IC_RIGHT(ic); \
3002 result = IC_RESULT(ic);
3004 /*-----------------------------------------------------------------*/
3005 /* genPlus - generates code for addition */
3006 /*-----------------------------------------------------------------*/
3007 static void genPlus (iCode *ic)
3009 int size, offset = 0;
3010 bool pushResult = FALSE;
3013 D(emitcode(";", "genPlus "););
3015 /* special cases :- */
3018 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
3019 aopOp (IC_LEFT(ic),ic,FALSE,
3020 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3021 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
3022 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
3028 aopOp (IC_RESULT(ic),ic,TRUE,
3029 ((AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)
3030 || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR)));
3033 AOP_OP_3_NOFATAL(ic, pushResult);
3036 D(emitcode(";", "genPlus: must push result: 3 ops in far space"););
3042 /* if literal, literal on the right or
3043 if left requires ACC or right is already
3045 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)
3046 || ((AOP_NEEDSACC(IC_LEFT(ic))) && !(AOP_NEEDSACC(IC_RIGHT(ic))))
3047 || AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC )
3049 operand *t = IC_RIGHT(ic);
3050 IC_RIGHT(ic) = IC_LEFT(ic);
3052 emitcode(";", "Swapped plus args.");
3055 /* if both left & right are in bit
3057 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3058 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3063 /* if left in bit space & right literal */
3064 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3065 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3066 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3067 /* if result in bit space */
3068 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3069 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
3070 emitcode("cpl","c");
3071 outBitC(IC_RESULT(ic));
3073 size = getDataSize(IC_RESULT(ic));
3074 _startLazyDPSEvaluation();
3076 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3077 emitcode("addc","a,#00");
3078 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3080 _endLazyDPSEvaluation();
3085 /* if I can do an increment instead
3086 of add then GOOD for ME */
3087 if (genPlusIncr (ic) == TRUE)
3089 emitcode(";", "did genPlusIncr");
3094 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3096 _startLazyDPSEvaluation();
3099 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3101 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3103 emitcode("add","a,%s",
3104 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3106 emitcode("addc","a,%s",
3107 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3109 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3111 emitcode("add","a,%s",
3112 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3114 emitcode("addc","a,%s",
3115 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3119 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3123 emitcode("push", "acc");
3127 _endLazyDPSEvaluation();
3131 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3133 size = getDataSize(IC_LEFT(ic));
3134 rSize = getDataSize(IC_RESULT(ic));
3136 /* If the pushed data is bigger than the result,
3137 * simply discard unused bytes. Icky, but works.
3139 * Should we throw a warning here? We're losing data...
3141 while (size > rSize)
3143 D(emitcode(";", "discarding unused result byte."););
3144 emitcode("pop", "acc");
3150 emitcode("clr", "a");
3151 /* Conversly, we haven't pushed enough here.
3152 * just zero-pad, and all is well.
3154 while (size < rSize)
3156 emitcode("push", "acc");
3162 _startLazyDPSEvaluation();
3165 emitcode("pop", "acc");
3166 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3168 _endLazyDPSEvaluation();
3171 adjustArithmeticResult(ic);
3174 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3175 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3176 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3179 /*-----------------------------------------------------------------*/
3180 /* genMinusDec :- does subtraction with deccrement if possible */
3181 /*-----------------------------------------------------------------*/
3182 static bool genMinusDec (iCode *ic)
3184 unsigned int icount ;
3185 unsigned int size = getDataSize(IC_RESULT(ic));
3187 /* will try to generate an increment */
3188 /* if the right side is not a literal
3190 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3193 /* if the literal value of the right hand side
3194 is greater than 4 then it is not worth it */
3195 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3198 /* if decrement 16 bits in register */
3199 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3200 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3201 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3208 /* If the next instruction is a goto and the goto target
3209 * is <= 5 instructions previous to this, we can generate
3210 * jumps straight to that target.
3212 if (ic->next && ic->next->op == GOTO
3213 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3214 && labelRange <= 5 )
3216 emitcode(";", "tail decrement optimized (range %d)", labelRange);
3217 tlbl = IC_LABEL(ic->next);
3222 tlbl = newiTempLabel(NULL);
3226 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3227 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3228 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3229 IS_AOP_PREG(IC_RESULT(ic)))
3230 emitcode("cjne","%s,#0xff,%05d$"
3231 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3234 emitcode("mov","a,#0xff");
3235 emitcode("cjne","a,%s,%05d$"
3236 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3239 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3242 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3243 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3244 IS_AOP_PREG(IC_RESULT(ic)))
3245 emitcode("cjne","%s,#0xff,%05d$"
3246 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3249 emitcode("cjne","a,%s,%05d$"
3250 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3253 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3257 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3258 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3259 IS_AOP_PREG(IC_RESULT(ic)))
3260 emitcode("cjne","%s,#0xff,%05d$"
3261 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3264 emitcode("cjne","a,%s,%05d$"
3265 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3268 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3272 emitcode("","%05d$:",tlbl->key+100);
3277 /* if the sizes are greater than 1 then we cannot */
3278 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3279 AOP_SIZE(IC_LEFT(ic)) > 1 )
3282 /* we can if the aops of the left & result match or
3283 if they are in registers and the registers are the
3286 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3287 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3288 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3290 _startLazyDPSEvaluation();
3293 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3295 _endLazyDPSEvaluation();
3303 /*-----------------------------------------------------------------*/
3304 /* addSign - complete with sign */
3305 /*-----------------------------------------------------------------*/
3306 static void addSign(operand *result, int offset, int sign)
3308 int size = (getDataSize(result) - offset);
3311 emitcode("rlc","a");
3312 emitcode("subb","a,acc");
3314 aopPut(AOP(result),"a",offset++);
3317 aopPut(AOP(result),zero,offset++);
3321 /*-----------------------------------------------------------------*/
3322 /* genMinusBits - generates code for subtraction of two bits */
3323 /*-----------------------------------------------------------------*/
3324 static void genMinusBits (iCode *ic)
3326 symbol *lbl = newiTempLabel(NULL);
3328 D(emitcode(";", "genMinusBits "););
3330 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3331 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3332 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3333 emitcode("cpl","c");
3334 emitcode("","%05d$:",(lbl->key+100));
3335 outBitC(IC_RESULT(ic));
3338 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3339 emitcode("subb","a,acc");
3340 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3341 emitcode("inc","a");
3342 emitcode("","%05d$:",(lbl->key+100));
3343 aopPut(AOP(IC_RESULT(ic)),"a",0);
3344 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3348 /*-----------------------------------------------------------------*/
3349 /* genMinus - generates code for subtraction */
3350 /*-----------------------------------------------------------------*/
3351 static void genMinus (iCode *ic)
3353 int size, offset = 0;
3355 unsigned long lit = 0L;
3356 bool pushResult = FALSE;
3358 D(emitcode(";", "genMinus "););
3360 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3361 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3362 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3363 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3369 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3371 /* special cases :- */
3372 /* if both left & right are in bit space */
3373 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3374 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3379 /* if I can do an decrement instead
3380 of subtract then GOOD for ME */
3381 if (genMinusDec (ic) == TRUE)
3386 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3388 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3392 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3397 /* if literal, add a,#-lit, else normal subb */
3398 _startLazyDPSEvaluation();
3400 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3401 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3402 emitcode("subb","a,%s",
3403 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3405 /* first add without previous c */
3407 emitcode("add","a,#0x%02x",
3408 (unsigned int)(lit & 0x0FFL));
3410 emitcode("addc","a,#0x%02x",
3411 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3416 emitcode("push", "acc");
3420 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3424 _endLazyDPSEvaluation();
3428 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3430 size = getDataSize(IC_LEFT(ic));
3431 rSize = getDataSize(IC_RESULT(ic));
3433 /* If the pushed data is bigger than the result,
3434 * simply discard unused bytes. Icky, but works.
3436 * Should we throw a warning here? We're losing data...
3438 while (size > getDataSize(IC_RESULT(ic)))
3440 emitcode(";", "discarding unused result byte.");
3441 emitcode("pop", "acc");
3447 emitcode("clr", "a");
3448 /* Conversly, we haven't pushed enough here.
3449 * just zero-pad, and all is well.
3451 while (size < rSize)
3453 emitcode("push", "acc");
3461 emitcode("pop", "acc");
3462 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3466 adjustArithmeticResult(ic);
3469 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3470 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3471 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3475 /*-----------------------------------------------------------------*/
3476 /* genMultbits :- multiplication of bits */
3477 /*-----------------------------------------------------------------*/
3478 static void genMultbits (operand *left,
3482 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3483 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3488 /*-----------------------------------------------------------------*/
3489 /* genMultOneByte : 8 bit multiplication & division */
3490 /*-----------------------------------------------------------------*/
3491 static void genMultOneByte (operand *left,
3495 sym_link *opetype = operandType(result);
3500 /* (if two literals, the value is computed before) */
3501 /* if one literal, literal on the right */
3502 if (AOP_TYPE(left) == AOP_LIT){
3508 size = AOP_SIZE(result);
3509 /* signed or unsigned */
3510 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3511 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3513 emitcode("mul","ab");
3514 /* if result size = 1, mul signed = mul unsigned */
3515 aopPut(AOP(result),"a",0);
3517 if (SPEC_USIGN(opetype)){
3518 aopPut(AOP(result),"b",1);
3520 /* for filling the MSBs */
3521 emitcode("clr","a");
3524 emitcode("mov","a,b");
3526 /* adjust the MSB if left or right neg */
3528 /* if one literal */
3529 if (AOP_TYPE(right) == AOP_LIT){
3530 /* AND literal negative */
3531 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3532 /* adjust MSB (c==0 after mul) */
3533 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3537 lbl = newiTempLabel(NULL);
3538 emitcode("xch","a,%s",aopGet(AOP(right),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(right),0,FALSE,FALSE,FALSE));
3542 lbl = newiTempLabel(NULL);
3543 emitcode("jc","%05d$",(lbl->key+100));
3544 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3545 emitcode("","%05d$:",(lbl->key+100));
3548 lbl = newiTempLabel(NULL);
3549 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3550 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3551 emitcode("","%05d$:",(lbl->key+100));
3552 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3553 lbl = newiTempLabel(NULL);
3554 emitcode("jc","%05d$",(lbl->key+100));
3555 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3556 emitcode("","%05d$:",(lbl->key+100));
3558 aopPut(AOP(result),"a",1);
3561 emitcode("rlc","a");
3562 emitcode("subb","a,acc");
3569 aopPut(AOP(result),"a",offset++);
3573 /*-----------------------------------------------------------------*/
3574 /* genMult - generates code for multiplication */
3575 /*-----------------------------------------------------------------*/
3576 static void genMult (iCode *ic)
3578 operand *left = IC_LEFT(ic);
3579 operand *right = IC_RIGHT(ic);
3580 operand *result= IC_RESULT(ic);
3582 D(emitcode(";", "genMult "););
3584 /* assign the amsops */
3587 aopOp (left,ic,FALSE, FALSE);
3588 aopOp (right,ic,FALSE, TRUE);
3589 aopOp (result,ic,TRUE, FALSE);
3592 /* special cases first */
3594 if (AOP_TYPE(left) == AOP_CRY &&
3595 AOP_TYPE(right)== AOP_CRY) {
3596 genMultbits(left,right,result);
3600 /* if both are of size == 1 */
3601 if (AOP_SIZE(left) == 1 &&
3602 AOP_SIZE(right) == 1 ) {
3603 genMultOneByte(left,right,result);
3607 /* should have been converted to function call */
3611 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3612 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3613 freeAsmop(result,NULL,ic,TRUE);
3616 /*-----------------------------------------------------------------*/
3617 /* genDivbits :- division of bits */
3618 /*-----------------------------------------------------------------*/
3619 static void genDivbits (operand *left,
3626 /* the result must be bit */
3627 LOAD_AB_FOR_DIV(left, right, l);
3628 emitcode("div","ab");
3629 emitcode("rrc","a");
3630 aopPut(AOP(result),"c",0);
3633 /*-----------------------------------------------------------------*/
3634 /* genDivOneByte : 8 bit division */
3635 /*-----------------------------------------------------------------*/
3636 static void genDivOneByte (operand *left,
3640 sym_link *opetype = operandType(result);
3645 size = AOP_SIZE(result) - 1;
3647 /* signed or unsigned */
3648 if (SPEC_USIGN(opetype)) {
3649 /* unsigned is easy */
3650 LOAD_AB_FOR_DIV(left, right, l);
3651 emitcode("div","ab");
3652 aopPut(AOP(result),"a",0);
3654 aopPut(AOP(result),zero,offset++);
3658 /* signed is a little bit more difficult */
3660 /* save the signs of the operands */
3661 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3663 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3664 emitcode("push","acc"); /* save it on the stack */
3666 /* now sign adjust for both left & right */
3667 l = aopGet(AOP(right),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));
3674 emitcode("mov","b,a");
3676 /* sign adjust left side */
3677 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3680 lbl = newiTempLabel(NULL);
3681 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3682 emitcode("cpl","a");
3683 emitcode("inc","a");
3684 emitcode("","%05d$:",(lbl->key+100));
3686 /* now the division */
3687 emitcode("nop", "; workaround for DS80C390 div bug.");
3688 emitcode("div","ab");
3689 /* we are interested in the lower order
3691 emitcode("mov","b,a");
3692 lbl = newiTempLabel(NULL);
3693 emitcode("pop","acc");
3694 /* if there was an over flow we don't
3695 adjust the sign of the result */
3696 emitcode("jb","ov,%05d$",(lbl->key+100));
3697 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3699 emitcode("clr","a");
3700 emitcode("subb","a,b");
3701 emitcode("mov","b,a");
3702 emitcode("","%05d$:",(lbl->key+100));
3704 /* now we are done */
3705 aopPut(AOP(result),"b",0);
3707 emitcode("mov","c,b.7");
3708 emitcode("subb","a,acc");
3711 aopPut(AOP(result),"a",offset++);
3715 /*-----------------------------------------------------------------*/
3716 /* genDiv - generates code for division */
3717 /*-----------------------------------------------------------------*/
3718 static void genDiv (iCode *ic)
3720 operand *left = IC_LEFT(ic);
3721 operand *right = IC_RIGHT(ic);
3722 operand *result= IC_RESULT(ic);
3724 D(emitcode(";", "genDiv "););
3726 /* assign the amsops */
3729 aopOp (left,ic,FALSE, FALSE);
3730 aopOp (right,ic,FALSE, TRUE);
3731 aopOp (result,ic,TRUE, FALSE);
3734 /* special cases first */
3736 if (AOP_TYPE(left) == AOP_CRY &&
3737 AOP_TYPE(right)== AOP_CRY) {
3738 genDivbits(left,right,result);
3742 /* if both are of size == 1 */
3743 if (AOP_SIZE(left) == 1 &&
3744 AOP_SIZE(right) == 1 ) {
3745 genDivOneByte(left,right,result);
3749 /* should have been converted to function call */
3752 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3753 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3754 freeAsmop(result,NULL,ic,TRUE);
3757 /*-----------------------------------------------------------------*/
3758 /* genModbits :- modulus of bits */
3759 /*-----------------------------------------------------------------*/
3760 static void genModbits (operand *left,
3767 /* the result must be bit */
3768 LOAD_AB_FOR_DIV(left, right, l);
3769 emitcode("div","ab");
3770 emitcode("mov","a,b");
3771 emitcode("rrc","a");
3772 aopPut(AOP(result),"c",0);
3775 /*-----------------------------------------------------------------*/
3776 /* genModOneByte : 8 bit modulus */
3777 /*-----------------------------------------------------------------*/
3778 static void genModOneByte (operand *left,
3782 sym_link *opetype = operandType(result);
3786 /* signed or unsigned */
3787 if (SPEC_USIGN(opetype)) {
3788 /* unsigned is easy */
3789 LOAD_AB_FOR_DIV(left, right, l);
3790 emitcode("div","ab");
3791 aopPut(AOP(result),"b",0);
3795 /* signed is a little bit more difficult */
3797 /* save the signs of the operands */
3798 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3801 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3802 emitcode("push","acc"); /* save it on the stack */
3804 /* now sign adjust for both left & right */
3805 l = aopGet(AOP(right),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));
3813 emitcode("mov","b,a");
3815 /* sign adjust left side */
3816 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3819 lbl = newiTempLabel(NULL);
3820 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3821 emitcode("cpl","a");
3822 emitcode("inc","a");
3823 emitcode("","%05d$:",(lbl->key+100));
3825 /* now the multiplication */
3826 emitcode("nop", "; workaround for DS80C390 div bug.");
3827 emitcode("div","ab");
3828 /* we are interested in the lower order
3830 lbl = newiTempLabel(NULL);
3831 emitcode("pop","acc");
3832 /* if there was an over flow we don't
3833 adjust the sign of the result */
3834 emitcode("jb","ov,%05d$",(lbl->key+100));
3835 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3837 emitcode("clr","a");
3838 emitcode("subb","a,b");
3839 emitcode("mov","b,a");
3840 emitcode("","%05d$:",(lbl->key+100));
3842 /* now we are done */
3843 aopPut(AOP(result),"b",0);
3847 /*-----------------------------------------------------------------*/
3848 /* genMod - generates code for division */
3849 /*-----------------------------------------------------------------*/
3850 static void genMod (iCode *ic)
3852 operand *left = IC_LEFT(ic);
3853 operand *right = IC_RIGHT(ic);
3854 operand *result= IC_RESULT(ic);
3856 D(emitcode(";", "genMod "););
3858 /* assign the amsops */
3861 aopOp (left,ic,FALSE, FALSE);
3862 aopOp (right,ic,FALSE, TRUE);
3863 aopOp (result,ic,TRUE, FALSE);
3866 /* special cases first */
3868 if (AOP_TYPE(left) == AOP_CRY &&
3869 AOP_TYPE(right)== AOP_CRY) {
3870 genModbits(left,right,result);
3874 /* if both are of size == 1 */
3875 if (AOP_SIZE(left) == 1 &&
3876 AOP_SIZE(right) == 1 ) {
3877 genModOneByte(left,right,result);
3881 /* should have been converted to function call */
3885 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3886 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3887 freeAsmop(result,NULL,ic,TRUE);
3890 /*-----------------------------------------------------------------*/
3891 /* genIfxJump :- will create a jump depending on the ifx */
3892 /*-----------------------------------------------------------------*/
3893 static void genIfxJump (iCode *ic, char *jval)
3896 symbol *tlbl = newiTempLabel(NULL);
3899 D(emitcode(";", "genIfxJump "););
3901 /* if true label then we jump if condition
3903 if ( IC_TRUE(ic) ) {
3905 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3906 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3909 /* false label is present */
3910 jlbl = IC_FALSE(ic) ;
3911 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3912 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3914 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3915 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3917 emitcode(inst,"%05d$",tlbl->key+100);
3918 emitcode("ljmp","%05d$",jlbl->key+100);
3919 emitcode("","%05d$:",tlbl->key+100);
3921 /* mark the icode as generated */
3925 /*-----------------------------------------------------------------*/
3926 /* genCmp :- greater or less than comparison */
3927 /*-----------------------------------------------------------------*/
3928 static void genCmp (operand *left,operand *right,
3929 iCode *ic, iCode *ifx, int sign)
3931 int size, offset = 0 ;
3932 unsigned long lit = 0L;
3935 D(emitcode(";", "genCmp"););
3937 result = IC_RESULT(ic);
3939 /* if left & right are bit variables */
3940 if (AOP_TYPE(left) == AOP_CRY &&
3941 AOP_TYPE(right) == AOP_CRY ) {
3942 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3943 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3945 /* subtract right from left if at the
3946 end the carry flag is set then we know that
3947 left is greater than right */
3948 size = max(AOP_SIZE(left),AOP_SIZE(right));
3950 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3951 if((size == 1) && !sign &&
3952 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3953 symbol *lbl = newiTempLabel(NULL);
3954 emitcode("cjne","%s,%s,%05d$",
3955 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3956 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3958 emitcode("","%05d$:",lbl->key+100);
3960 if (AOP_TYPE(right) == AOP_LIT)
3962 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3963 /* optimize if(x < 0) or if(x >= 0) */
3972 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3974 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3975 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3977 aopOp(result,ic,FALSE, FALSE);
3979 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx)
3981 freeAsmop(result,NULL,ic,TRUE);
3982 genIfxJump (ifx,"acc.7");
3987 emitcode("rlc","a");
3989 goto release_freedLR;
3997 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3998 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3999 emitcode(";", "genCmp #2");
4000 if (sign && (size == 0))
4002 emitcode(";", "genCmp #3");
4003 emitcode("xrl","a,#0x80");
4004 if (AOP_TYPE(right) == AOP_LIT)
4006 unsigned long lit = (unsigned long)
4007 floatFromVal(AOP(right)->aopu.aop_lit);
4008 emitcode(";", "genCmp #3.1");
4009 emitcode("subb","a,#0x%02x",
4010 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
4014 emitcode(";", "genCmp #3.2");
4015 if (AOP_NEEDSACC(right))
4017 emitcode("push", "acc");
4019 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
4020 FALSE,FALSE,FALSE));
4021 emitcode("xrl","b,#0x80");
4022 if (AOP_NEEDSACC(right))
4024 emitcode("pop", "acc");
4026 emitcode("subb","a,b");
4033 emitcode(";", "genCmp #4");
4034 if (AOP_NEEDSACC(right))
4037 emitcode(";", "genCmp #4.1");
4038 emitcode("xch", "a, b");
4039 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
4040 emitcode("xch", "a, b");
4045 emitcode(";", "genCmp #4.2");
4046 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
4049 emitcode("subb","a,%s",s);
4056 /* Don't need the left & right operands any more; do need the result. */
4057 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4058 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4060 aopOp(result,ic,FALSE, FALSE);
4064 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result))
4070 /* if the result is used in the next
4071 ifx conditional branch then generate
4072 code a little differently */
4075 genIfxJump (ifx,"c");
4081 /* leave the result in acc */
4083 freeAsmop(result,NULL,ic,TRUE);
4086 /*-----------------------------------------------------------------*/
4087 /* genCmpGt :- greater than comparison */
4088 /*-----------------------------------------------------------------*/
4089 static void genCmpGt (iCode *ic, iCode *ifx)
4091 operand *left, *right;
4092 sym_link *letype , *retype;
4095 D(emitcode(";", "genCmpGt "););
4098 right= IC_RIGHT(ic);
4100 letype = getSpec(operandType(left));
4101 retype =getSpec(operandType(right));
4102 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4104 /* assign the left & right amsops */
4107 genCmp(right, left, ic, ifx, sign);
4110 /*-----------------------------------------------------------------*/
4111 /* genCmpLt - less than comparisons */
4112 /*-----------------------------------------------------------------*/
4113 static void genCmpLt (iCode *ic, iCode *ifx)
4115 operand *left, *right;
4116 sym_link *letype , *retype;
4119 D(emitcode(";", "genCmpLt "););
4122 right= IC_RIGHT(ic);
4124 letype = getSpec(operandType(left));
4125 retype =getSpec(operandType(right));
4126 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4128 /* assign the left & right amsops */
4131 genCmp(left, right, ic, ifx, sign);
4134 /*-----------------------------------------------------------------*/
4135 /* gencjneshort - compare and jump if not equal */
4136 /*-----------------------------------------------------------------*/
4137 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4139 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4141 unsigned long lit = 0L;
4143 D(emitcode(";", "gencjneshort"););
4145 /* if the left side is a literal or
4146 if the right is in a pointer register and left
4148 if ((AOP_TYPE(left) == AOP_LIT) ||
4149 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4155 if(AOP_TYPE(right) == AOP_LIT)
4156 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4158 if (opIsGptr(left) || opIsGptr(right))
4160 /* We are comparing a generic pointer to something.
4161 * Exclude the generic type byte from the comparison.
4164 D(emitcode(";", "cjneshort: generic ptr special case.");)
4168 /* if the right side is a literal then anything goes */
4169 if (AOP_TYPE(right) == AOP_LIT &&
4170 AOP_TYPE(left) != AOP_DIR ) {
4172 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4174 emitcode("cjne","a,%s,%05d$",
4175 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4181 /* if the right side is in a register or in direct space or
4182 if the left is a pointer register & right is not */
4183 else if (AOP_TYPE(right) == AOP_REG ||
4184 AOP_TYPE(right) == AOP_DIR ||
4185 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4186 (IS_AOP_PREG(left) && !IS_AOP_PREG(right)))
4190 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4191 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4192 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4193 emitcode("jnz","%05d$",lbl->key+100);
4195 emitcode("cjne","a,%s,%05d$",
4196 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4201 /* right is a pointer reg need both a & b */
4203 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4205 emitcode("mov","b,%s",l);
4206 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4207 emitcode("cjne","a,b,%05d$",lbl->key+100);
4213 /*-----------------------------------------------------------------*/
4214 /* gencjne - compare and jump if not equal */
4215 /*-----------------------------------------------------------------*/
4216 static void gencjne(operand *left, operand *right, symbol *lbl)
4218 symbol *tlbl = newiTempLabel(NULL);
4220 D(emitcode(";", "gencjne"););
4222 gencjneshort(left, right, lbl);
4224 emitcode("mov","a,%s",one);
4225 emitcode("sjmp","%05d$",tlbl->key+100);
4226 emitcode("","%05d$:",lbl->key+100);
4227 emitcode("clr","a");
4228 emitcode("","%05d$:",tlbl->key+100);
4231 /*-----------------------------------------------------------------*/
4232 /* genCmpEq - generates code for equal to */
4233 /*-----------------------------------------------------------------*/
4234 static void genCmpEq (iCode *ic, iCode *ifx)
4236 operand *left, *right, *result;
4238 D(emitcode(";", "genCmpEq "););
4243 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4244 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4245 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4248 /* if literal, literal on the right or
4249 if the right is in a pointer register and left
4251 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4252 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4253 operand *t = IC_RIGHT(ic);
4254 IC_RIGHT(ic) = IC_LEFT(ic);
4258 if (ifx && /* !AOP_SIZE(result) */
4259 OP_SYMBOL(result) &&
4260 OP_SYMBOL(result)->regType == REG_CND)
4263 /* if they are both bit variables */
4264 if (AOP_TYPE(left) == AOP_CRY &&
4265 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4266 if(AOP_TYPE(right) == AOP_LIT){
4267 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4269 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4270 emitcode("cpl","c");
4271 } else if(lit == 1L) {
4272 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4274 emitcode("clr","c");
4276 /* AOP_TYPE(right) == AOP_CRY */
4278 symbol *lbl = newiTempLabel(NULL);
4279 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4280 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4281 emitcode("cpl","c");
4282 emitcode("","%05d$:",(lbl->key+100));
4284 /* if true label then we jump if condition
4286 tlbl = newiTempLabel(NULL);
4287 if ( IC_TRUE(ifx) ) {
4288 emitcode("jnc","%05d$",tlbl->key+100);
4289 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4291 emitcode("jc","%05d$",tlbl->key+100);
4292 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4294 emitcode("","%05d$:",tlbl->key+100);
4296 tlbl = newiTempLabel(NULL);
4297 gencjneshort(left, right, tlbl);
4298 if ( IC_TRUE(ifx) ) {
4299 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4300 emitcode("","%05d$:",tlbl->key+100);
4302 symbol *lbl = newiTempLabel(NULL);
4303 emitcode("sjmp","%05d$",lbl->key+100);
4304 emitcode("","%05d$:",tlbl->key+100);
4305 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4306 emitcode("","%05d$:",lbl->key+100);
4309 /* mark the icode as generated */
4312 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4313 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4317 /* if they are both bit variables */
4318 if (AOP_TYPE(left) == AOP_CRY &&
4319 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4320 if(AOP_TYPE(right) == AOP_LIT){
4321 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4323 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4324 emitcode("cpl","c");
4325 } else if(lit == 1L) {
4326 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4328 emitcode("clr","c");
4330 /* AOP_TYPE(right) == AOP_CRY */
4332 symbol *lbl = newiTempLabel(NULL);
4333 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4334 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4335 emitcode("cpl","c");
4336 emitcode("","%05d$:",(lbl->key+100));
4339 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4340 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4342 aopOp(result,ic,TRUE, FALSE);
4345 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4350 genIfxJump (ifx,"c");
4353 /* if the result is used in an arithmetic operation
4354 then put the result in place */
4357 gencjne(left,right,newiTempLabel(NULL));
4359 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4360 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4362 aopOp(result,ic,TRUE, FALSE);
4364 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4365 aopPut(AOP(result),"a",0);
4369 genIfxJump (ifx,"a");
4372 /* if the result is used in an arithmetic operation
4373 then put the result in place */
4374 if (AOP_TYPE(result) != AOP_CRY)
4376 /* leave the result in acc */
4380 freeAsmop(result,NULL,ic,TRUE);
4383 /*-----------------------------------------------------------------*/
4384 /* ifxForOp - returns the icode containing the ifx for operand */
4385 /*-----------------------------------------------------------------*/
4386 static iCode *ifxForOp ( operand *op, iCode *ic )
4388 /* if true symbol then needs to be assigned */
4389 if (IS_TRUE_SYMOP(op))
4392 /* if this has register type condition and
4393 the next instruction is ifx with the same operand
4394 and live to of the operand is upto the ifx only then */
4396 ic->next->op == IFX &&
4397 IC_COND(ic->next)->key == op->key &&
4398 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4403 /*-----------------------------------------------------------------*/
4404 /* genAndOp - for && operation */
4405 /*-----------------------------------------------------------------*/
4406 static void genAndOp (iCode *ic)
4408 operand *left,*right, *result;
4411 D(emitcode(";", "genAndOp "););
4413 /* note here that && operations that are in an
4414 if statement are taken away by backPatchLabels
4415 only those used in arthmetic operations remain */
4419 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4420 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4421 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4424 /* if both are bit variables */
4425 if (AOP_TYPE(left) == AOP_CRY &&
4426 AOP_TYPE(right) == AOP_CRY ) {
4427 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4428 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4431 tlbl = newiTempLabel(NULL);
4433 emitcode("jz","%05d$",tlbl->key+100);
4435 emitcode("","%05d$:",tlbl->key+100);
4439 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4440 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4441 freeAsmop(result,NULL,ic,TRUE);
4445 /*-----------------------------------------------------------------*/
4446 /* genOrOp - for || operation */
4447 /*-----------------------------------------------------------------*/
4448 static void genOrOp (iCode *ic)
4450 operand *left,*right, *result;
4453 D(emitcode(";", "genOrOp "););
4455 /* note here that || operations that are in an
4456 if statement are taken away by backPatchLabels
4457 only those used in arthmetic operations remain */
4461 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4462 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4463 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4466 /* if both are bit variables */
4467 if (AOP_TYPE(left) == AOP_CRY &&
4468 AOP_TYPE(right) == AOP_CRY ) {
4469 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4470 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4473 tlbl = newiTempLabel(NULL);
4475 emitcode("jnz","%05d$",tlbl->key+100);
4477 emitcode("","%05d$:",tlbl->key+100);
4481 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4482 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4483 freeAsmop(result,NULL,ic,TRUE);
4486 /*-----------------------------------------------------------------*/
4487 /* isLiteralBit - test if lit == 2^n */
4488 /*-----------------------------------------------------------------*/
4489 static int isLiteralBit(unsigned long lit)
4491 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4492 0x100L,0x200L,0x400L,0x800L,
4493 0x1000L,0x2000L,0x4000L,0x8000L,
4494 0x10000L,0x20000L,0x40000L,0x80000L,
4495 0x100000L,0x200000L,0x400000L,0x800000L,
4496 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4497 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4500 for(idx = 0; idx < 32; idx++)
4506 /*-----------------------------------------------------------------*/
4507 /* continueIfTrue - */
4508 /*-----------------------------------------------------------------*/
4509 static void continueIfTrue (iCode *ic)
4512 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4516 /*-----------------------------------------------------------------*/
4518 /*-----------------------------------------------------------------*/
4519 static void jumpIfTrue (iCode *ic)
4522 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4526 /*-----------------------------------------------------------------*/
4527 /* jmpTrueOrFalse - */
4528 /*-----------------------------------------------------------------*/
4529 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4531 // ugly but optimized by peephole
4533 symbol *nlbl = newiTempLabel(NULL);
4534 emitcode("sjmp","%05d$",nlbl->key+100);
4535 emitcode("","%05d$:",tlbl->key+100);
4536 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4537 emitcode("","%05d$:",nlbl->key+100);
4540 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4541 emitcode("","%05d$:",tlbl->key+100);
4546 /*-----------------------------------------------------------------*/
4547 /* genAnd - code for and */
4548 /*-----------------------------------------------------------------*/
4549 static void genAnd (iCode *ic, iCode *ifx)
4551 operand *left, *right, *result;
4553 unsigned long lit = 0L;
4557 D(emitcode(";", "genAnd "););
4562 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4563 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4564 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4568 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4570 AOP_TYPE(left), AOP_TYPE(right));
4571 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4573 AOP_SIZE(left), AOP_SIZE(right));
4576 /* if left is a literal & right is not then exchange them */
4577 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4578 AOP_NEEDSACC(left)) {
4579 operand *tmp = right ;
4584 /* if result = right then exchange them */
4585 if(sameRegs(AOP(result),AOP(right))){
4586 operand *tmp = right ;
4591 /* if right is bit then exchange them */
4592 if (AOP_TYPE(right) == AOP_CRY &&
4593 AOP_TYPE(left) != AOP_CRY){
4594 operand *tmp = right ;
4598 if(AOP_TYPE(right) == AOP_LIT)
4599 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4601 size = AOP_SIZE(result);
4604 // result = bit & yy;
4605 if (AOP_TYPE(left) == AOP_CRY){
4606 // c = bit & literal;
4607 if(AOP_TYPE(right) == AOP_LIT){
4609 if(size && sameRegs(AOP(result),AOP(left)))
4612 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4615 if(size && (AOP_TYPE(result) == AOP_CRY)){
4616 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4619 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4623 emitcode("clr","c");
4626 if (AOP_TYPE(right) == AOP_CRY){
4628 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4629 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4632 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4634 emitcode("rrc","a");
4635 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4643 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4644 genIfxJump(ifx, "c");
4648 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4649 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4650 if((AOP_TYPE(right) == AOP_LIT) &&
4651 (AOP_TYPE(result) == AOP_CRY) &&
4652 (AOP_TYPE(left) != AOP_CRY)){
4653 int posbit = isLiteralBit(lit);
4657 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4660 emitcode("mov","c,acc.%d",posbit&0x07);
4664 sprintf(buffer,"acc.%d",posbit&0x07);
4665 genIfxJump(ifx, buffer);
4670 symbol *tlbl = newiTempLabel(NULL);
4671 int sizel = AOP_SIZE(left);
4673 emitcode("setb","c");
4675 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4676 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4678 if((posbit = isLiteralBit(bytelit)) != 0)
4679 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4681 if(bytelit != 0x0FFL)
4682 emitcode("anl","a,%s",
4683 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4684 emitcode("jnz","%05d$",tlbl->key+100);
4689 // bit = left & literal
4691 emitcode("clr","c");
4692 emitcode("","%05d$:",tlbl->key+100);
4694 // if(left & literal)
4697 jmpTrueOrFalse(ifx, tlbl);
4705 /* if left is same as result */
4706 if(sameRegs(AOP(result),AOP(left))){
4707 for(;size--; offset++) {
4708 if(AOP_TYPE(right) == AOP_LIT){
4709 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4713 aopPut(AOP(result),zero,offset);
4715 if (IS_AOP_PREG(result)) {
4716 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4717 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4718 aopPut(AOP(result),"a",offset);
4720 emitcode("anl","%s,%s",
4721 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4722 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4724 if (AOP_TYPE(left) == AOP_ACC)
4725 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4727 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4728 if (IS_AOP_PREG(result)) {
4729 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4730 aopPut(AOP(result),"a",offset);
4733 emitcode("anl","%s,a",
4734 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4739 // left & result in different registers
4740 if(AOP_TYPE(result) == AOP_CRY){
4742 // if(size), result in bit
4743 // if(!size && ifx), conditional oper: if(left & right)
4744 symbol *tlbl = newiTempLabel(NULL);
4745 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4747 emitcode("setb","c");
4749 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4750 emitcode("anl","a,%s",
4751 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4752 emitcode("jnz","%05d$",tlbl->key+100);
4757 emitcode("","%05d$:",tlbl->key+100);
4760 jmpTrueOrFalse(ifx, tlbl);
4763 for(;(size--);offset++)
4766 // result = left & right
4767 if(AOP_TYPE(right) == AOP_LIT)
4769 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4772 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4776 else if (bytelit == 0)
4778 aopPut(AOP(result),zero,offset);
4781 D(emitcode(";", "better literal AND."););
4782 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4783 emitcode("anl", "a, %s", aopGet(AOP(right),offset,
4784 FALSE,FALSE,FALSE));
4789 // faster than result <- left, anl result,right
4790 // and better if result is SFR
4791 if (AOP_TYPE(left) == AOP_ACC)
4793 emitcode("anl","a,%s",aopGet(AOP(right),offset,
4794 FALSE,FALSE,FALSE));
4798 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4799 emitcode("anl","a,%s",
4800 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4803 aopPut(AOP(result),"a",offset);
4809 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4810 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4811 freeAsmop(result,NULL,ic,TRUE);
4814 /*-----------------------------------------------------------------*/
4815 /* genOr - code for or */
4816 /*-----------------------------------------------------------------*/
4817 static void genOr (iCode *ic, iCode *ifx)
4819 operand *left, *right, *result;
4821 unsigned long lit = 0L;
4823 D(emitcode(";", "genOr "););
4828 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4829 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4830 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4834 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4836 AOP_TYPE(left), AOP_TYPE(right));
4837 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4839 AOP_SIZE(left), AOP_SIZE(right));
4842 /* if left is a literal & right is not then exchange them */
4843 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4844 AOP_NEEDSACC(left)) {
4845 operand *tmp = right ;
4850 /* if result = right then exchange them */
4851 if(sameRegs(AOP(result),AOP(right))){
4852 operand *tmp = right ;
4857 /* if right is bit then exchange them */
4858 if (AOP_TYPE(right) == AOP_CRY &&
4859 AOP_TYPE(left) != AOP_CRY){
4860 operand *tmp = right ;
4864 if(AOP_TYPE(right) == AOP_LIT)
4865 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4867 size = AOP_SIZE(result);
4871 if (AOP_TYPE(left) == AOP_CRY){
4872 if(AOP_TYPE(right) == AOP_LIT){
4873 // c = bit & literal;
4875 // lit != 0 => result = 1
4876 if(AOP_TYPE(result) == AOP_CRY){
4878 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4880 continueIfTrue(ifx);
4883 emitcode("setb","c");
4885 // lit == 0 => result = left
4886 if(size && sameRegs(AOP(result),AOP(left)))
4888 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4891 if (AOP_TYPE(right) == AOP_CRY){
4893 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4894 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4898 symbol *tlbl = newiTempLabel(NULL);
4899 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4900 emitcode("setb","c");
4901 emitcode("jb","%s,%05d$",
4902 AOP(left)->aopu.aop_dir,tlbl->key+100);
4904 emitcode("jnz","%05d$",tlbl->key+100);
4905 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4906 jmpTrueOrFalse(ifx, tlbl);
4910 emitcode("","%05d$:",tlbl->key+100);
4919 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4920 genIfxJump(ifx, "c");
4924 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4925 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4926 if((AOP_TYPE(right) == AOP_LIT) &&
4927 (AOP_TYPE(result) == AOP_CRY) &&
4928 (AOP_TYPE(left) != AOP_CRY)){
4932 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4934 continueIfTrue(ifx);
4937 // lit = 0, result = boolean(left)
4939 emitcode("setb","c");
4942 symbol *tlbl = newiTempLabel(NULL);
4943 emitcode("jnz","%05d$",tlbl->key+100);
4945 emitcode("","%05d$:",tlbl->key+100);
4947 genIfxJump (ifx,"a");
4955 /* if left is same as result */
4956 if(sameRegs(AOP(result),AOP(left)))
4958 for(;size--; offset++)
4960 if(AOP_TYPE(right) == AOP_LIT){
4961 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4967 if (IS_AOP_PREG(left))
4969 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4970 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4971 aopPut(AOP(result),"a",offset);
4975 emitcode("orl","%s,%s",
4976 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4977 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4983 if (AOP_TYPE(left) == AOP_ACC)
4985 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4989 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4990 if (IS_AOP_PREG(left))
4992 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4993 aopPut(AOP(result),"a",offset);
4997 emitcode("orl","%s,a",
4998 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5006 // left & result in different registers
5007 if(AOP_TYPE(result) == AOP_CRY)
5010 // if(size), result in bit
5011 // if(!size && ifx), conditional oper: if(left | right)
5012 symbol *tlbl = newiTempLabel(NULL);
5013 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5015 emitcode("setb","c");
5017 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5018 emitcode("orl","a,%s",
5019 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5020 emitcode("jnz","%05d$",tlbl->key+100);
5025 emitcode("","%05d$:",tlbl->key+100);
5028 jmpTrueOrFalse(ifx, tlbl);
5032 for(;(size--);offset++)
5035 // result = left & right
5036 if(AOP_TYPE(right) == AOP_LIT)
5038 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5041 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5045 D(emitcode(";", "better literal OR."););
5046 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5047 emitcode("orl", "a, %s", aopGet(AOP(right),offset,
5048 FALSE,FALSE,FALSE));
5053 // faster than result <- left, anl result,right
5054 // and better if result is SFR
5055 if (AOP_TYPE(left) == AOP_ACC)
5057 emitcode("orl","a,%s",aopGet(AOP(right),offset,
5058 FALSE,FALSE,FALSE));
5062 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5063 emitcode("orl","a,%s",
5064 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5067 aopPut(AOP(result),"a",offset);
5073 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5074 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5075 freeAsmop(result,NULL,ic,TRUE);
5078 /*-----------------------------------------------------------------*/
5079 /* genXor - code for xclusive or */
5080 /*-----------------------------------------------------------------*/
5081 static void genXor (iCode *ic, iCode *ifx)
5083 operand *left, *right, *result;
5085 unsigned long lit = 0L;
5087 D(emitcode(";", "genXor "););
5092 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
5093 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
5094 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
5098 emitcode("","; Type res[%d] = l[%d]&r[%d]",
5100 AOP_TYPE(left), AOP_TYPE(right));
5101 emitcode("","; Size res[%d] = l[%d]&r[%d]",
5103 AOP_SIZE(left), AOP_SIZE(right));
5106 /* if left is a literal & right is not ||
5107 if left needs acc & right does not */
5108 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5109 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5110 operand *tmp = right ;
5115 /* if result = right then exchange them */
5116 if(sameRegs(AOP(result),AOP(right))){
5117 operand *tmp = right ;
5122 /* if right is bit then exchange them */
5123 if (AOP_TYPE(right) == AOP_CRY &&
5124 AOP_TYPE(left) != AOP_CRY){
5125 operand *tmp = right ;
5129 if(AOP_TYPE(right) == AOP_LIT)
5130 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5132 size = AOP_SIZE(result);
5136 if (AOP_TYPE(left) == AOP_CRY){
5137 if(AOP_TYPE(right) == AOP_LIT){
5138 // c = bit & literal;
5140 // lit>>1 != 0 => result = 1
5141 if(AOP_TYPE(result) == AOP_CRY){
5143 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5145 continueIfTrue(ifx);
5148 emitcode("setb","c");
5152 // lit == 0, result = left
5153 if(size && sameRegs(AOP(result),AOP(left)))
5155 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5157 // lit == 1, result = not(left)
5158 if(size && sameRegs(AOP(result),AOP(left))){
5159 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5162 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5163 emitcode("cpl","c");
5170 symbol *tlbl = newiTempLabel(NULL);
5171 if (AOP_TYPE(right) == AOP_CRY){
5173 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5176 int sizer = AOP_SIZE(right);
5178 // if val>>1 != 0, result = 1
5179 emitcode("setb","c");
5181 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5183 // test the msb of the lsb
5184 emitcode("anl","a,#0xfe");
5185 emitcode("jnz","%05d$",tlbl->key+100);
5189 emitcode("rrc","a");
5191 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5192 emitcode("cpl","c");
5193 emitcode("","%05d$:",(tlbl->key+100));
5200 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5201 genIfxJump(ifx, "c");
5205 if(sameRegs(AOP(result),AOP(left))){
5206 /* if left is same as result */
5207 for(;size--; offset++) {
5208 if(AOP_TYPE(right) == AOP_LIT){
5209 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5212 if (IS_AOP_PREG(left)) {
5213 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5214 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5215 aopPut(AOP(result),"a",offset);
5217 emitcode("xrl","%s,%s",
5218 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5219 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5221 if (AOP_TYPE(left) == AOP_ACC)
5222 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5224 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5225 if (IS_AOP_PREG(left)) {
5226 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5227 aopPut(AOP(result),"a",offset);
5229 emitcode("xrl","%s,a",
5230 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5235 // left & result in different registers
5236 if(AOP_TYPE(result) == AOP_CRY){
5238 // if(size), result in bit
5239 // if(!size && ifx), conditional oper: if(left ^ right)
5240 symbol *tlbl = newiTempLabel(NULL);
5241 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5243 emitcode("setb","c");
5245 if((AOP_TYPE(right) == AOP_LIT) &&
5246 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5247 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5249 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5250 emitcode("xrl","a,%s",
5251 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5253 emitcode("jnz","%05d$",tlbl->key+100);
5258 emitcode("","%05d$:",tlbl->key+100);
5261 jmpTrueOrFalse(ifx, tlbl);
5262 } else for(;(size--);offset++)
5265 // result = left & right
5266 if(AOP_TYPE(right) == AOP_LIT)
5268 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5271 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5275 D(emitcode(";", "better literal XOR."););
5276 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5277 emitcode("xrl", "a, %s", aopGet(AOP(right),offset,
5278 FALSE,FALSE,FALSE));
5282 // faster than result <- left, anl result,right
5283 // and better if result is SFR
5284 if (AOP_TYPE(left) == AOP_ACC)
5286 emitcode("xrl","a,%s",aopGet(AOP(right),offset,
5287 FALSE,FALSE,FALSE));
5291 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5292 emitcode("xrl","a,%s",
5293 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5296 aopPut(AOP(result),"a",offset);
5301 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5302 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5303 freeAsmop(result,NULL,ic,TRUE);
5306 /*-----------------------------------------------------------------*/
5307 /* genInline - write the inline code out */
5308 /*-----------------------------------------------------------------*/
5309 static void genInline (iCode *ic)
5311 char buffer[MAX_INLINEASM];
5315 D(emitcode(";", "genInline "););
5317 _G.inLine += (!options.asmpeep);
5318 strcpy(buffer,IC_INLINE(ic));
5320 /* emit each line as a code */
5339 /* emitcode("",buffer); */
5340 _G.inLine -= (!options.asmpeep);
5343 /*-----------------------------------------------------------------*/
5344 /* genRRC - rotate right with carry */
5345 /*-----------------------------------------------------------------*/
5346 static void genRRC (iCode *ic)
5348 operand *left , *result ;
5349 int size, offset = 0;
5352 D(emitcode(";", "genRRC "););
5354 /* rotate right with carry */
5356 result=IC_RESULT(ic);
5357 aopOp (left,ic,FALSE, FALSE);
5358 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5360 /* move it to the result */
5361 size = AOP_SIZE(result);
5365 _startLazyDPSEvaluation();
5367 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5369 emitcode("rrc","a");
5370 if (AOP_SIZE(result) > 1)
5371 aopPut(AOP(result),"a",offset--);
5373 _endLazyDPSEvaluation();
5375 /* now we need to put the carry into the
5376 highest order byte of the result */
5377 if (AOP_SIZE(result) > 1) {
5378 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5381 emitcode("mov","acc.7,c");
5382 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5383 freeAsmop(left,NULL,ic,TRUE);
5384 freeAsmop(result,NULL,ic,TRUE);
5387 /*-----------------------------------------------------------------*/
5388 /* genRLC - generate code for rotate left with carry */
5389 /*-----------------------------------------------------------------*/
5390 static void genRLC (iCode *ic)
5392 operand *left , *result ;
5393 int size, offset = 0;
5396 D(emitcode(";", "genRLC "););
5398 /* rotate right with carry */
5400 result=IC_RESULT(ic);
5401 aopOp (left,ic,FALSE, FALSE);
5402 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5404 /* move it to the result */
5405 size = AOP_SIZE(result);
5408 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5410 emitcode("add","a,acc");
5411 if (AOP_SIZE(result) > 1)
5413 aopPut(AOP(result),"a",offset++);
5416 _startLazyDPSEvaluation();
5418 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5420 emitcode("rlc","a");
5421 if (AOP_SIZE(result) > 1)
5422 aopPut(AOP(result),"a",offset++);
5424 _endLazyDPSEvaluation();
5426 /* now we need to put the carry into the
5427 highest order byte of the result */
5428 if (AOP_SIZE(result) > 1) {
5429 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5432 emitcode("mov","acc.0,c");
5433 aopPut(AOP(result),"a",0);
5434 freeAsmop(left,NULL,ic,TRUE);
5435 freeAsmop(result,NULL,ic,TRUE);
5438 /*-----------------------------------------------------------------*/
5439 /* genGetHbit - generates code get highest order bit */
5440 /*-----------------------------------------------------------------*/
5441 static void genGetHbit (iCode *ic)
5443 operand *left, *result;
5445 result=IC_RESULT(ic);
5446 aopOp (left,ic,FALSE, FALSE);
5447 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5449 D(emitcode(";", "genGetHbit "););
5451 /* get the highest order byte into a */
5452 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5453 if(AOP_TYPE(result) == AOP_CRY){
5454 emitcode("rlc","a");
5459 emitcode("anl","a,#0x01");
5464 freeAsmop(left,NULL,ic,TRUE);
5465 freeAsmop(result,NULL,ic,TRUE);
5468 /*-----------------------------------------------------------------*/
5469 /* AccRol - rotate left accumulator by known count */
5470 /*-----------------------------------------------------------------*/
5471 static void AccRol (int shCount)
5473 shCount &= 0x0007; // shCount : 0..7
5485 emitcode("swap","a");
5489 emitcode("swap","a");
5492 emitcode("swap","a");
5505 /*-----------------------------------------------------------------*/
5506 /* AccLsh - left shift accumulator by known count */
5507 /*-----------------------------------------------------------------*/
5508 static void AccLsh (int shCount)
5512 emitcode("add","a,acc");
5515 emitcode("add","a,acc");
5516 emitcode("add","a,acc");
5518 /* rotate left accumulator */
5520 /* and kill the lower order bits */
5521 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5526 /*-----------------------------------------------------------------*/
5527 /* AccRsh - right shift accumulator by known count */
5528 /*-----------------------------------------------------------------*/
5529 static void AccRsh (int shCount)
5534 emitcode("rrc","a");
5536 /* rotate right accumulator */
5537 AccRol(8 - shCount);
5538 /* and kill the higher order bits */
5539 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5546 /*-----------------------------------------------------------------*/
5547 /* AccSRsh - signed right shift accumulator by known count */
5548 /*-----------------------------------------------------------------*/
5549 static void AccSRsh (int shCount)
5554 emitcode("mov","c,acc.7");
5555 emitcode("rrc","a");
5556 } else if(shCount == 2){
5557 emitcode("mov","c,acc.7");
5558 emitcode("rrc","a");
5559 emitcode("mov","c,acc.7");
5560 emitcode("rrc","a");
5562 tlbl = newiTempLabel(NULL);
5563 /* rotate right accumulator */
5564 AccRol(8 - shCount);
5565 /* and kill the higher order bits */
5566 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5567 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5568 emitcode("orl","a,#0x%02x",
5569 (unsigned char)~SRMask[shCount]);
5570 emitcode("","%05d$:",tlbl->key+100);
5578 /*-----------------------------------------------------------------*/
5579 /* shiftR1Left2Result - shift right one byte from left to result */
5580 /*-----------------------------------------------------------------*/
5581 static void shiftR1Left2Result (operand *left, int offl,
5582 operand *result, int offr,
5583 int shCount, int sign)
5585 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5586 /* shift right accumulator */
5591 aopPut(AOP(result),"a",offr);
5597 /*-----------------------------------------------------------------*/
5598 /* shiftL1Left2Result - shift left one byte from left to result */
5599 /*-----------------------------------------------------------------*/
5600 static void shiftL1Left2Result (operand *left, int offl,
5601 operand *result, int offr, int shCount)
5604 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5606 /* shift left accumulator */
5608 aopPut(AOP(result),"a",offr);
5614 /*-----------------------------------------------------------------*/
5615 /* movLeft2Result - move byte from left to result */
5616 /*-----------------------------------------------------------------*/
5617 static void movLeft2Result (operand *left, int offl,
5618 operand *result, int offr, int sign)
5621 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5622 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5624 if (*l == '@' && (IS_AOP_PREG(result))) {
5625 emitcode("mov","a,%s",l);
5626 aopPut(AOP(result),"a",offr);
5629 aopPut(AOP(result),l,offr);
5631 /* MSB sign in acc.7 ! */
5632 if(getDataSize(left) == offl+1){
5633 emitcode("mov","a,%s",l);
5634 aopPut(AOP(result),"a",offr);
5644 /*-----------------------------------------------------------------*/
5645 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5646 /*-----------------------------------------------------------------*/
5647 static void AccAXRrl1 (char *x)
5649 emitcode("rrc","a");
5650 emitcode("xch","a,%s", x);
5651 emitcode("rrc","a");
5652 emitcode("xch","a,%s", x);
5658 /*-----------------------------------------------------------------*/
5659 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5660 /*-----------------------------------------------------------------*/
5661 static void AccAXLrl1 (char *x)
5663 emitcode("xch","a,%s",x);
5664 emitcode("rlc","a");
5665 emitcode("xch","a,%s",x);
5666 emitcode("rlc","a");
5672 /*-----------------------------------------------------------------*/
5673 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5674 /*-----------------------------------------------------------------*/
5675 static void AccAXLsh1 (char *x)
5677 emitcode("xch","a,%s",x);
5678 emitcode("add","a,acc");
5679 emitcode("xch","a,%s",x);
5680 emitcode("rlc","a");
5686 /*-----------------------------------------------------------------*/
5687 /* AccAXLsh - left shift a:x by known count (0..7) */
5688 /*-----------------------------------------------------------------*/
5689 static void AccAXLsh (char *x, int shCount)
5703 case 5 : // AAAAABBB:CCCCCDDD
5704 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5705 emitcode("anl","a,#0x%02x",
5706 SLMask[shCount]); // BBB00000:CCCCCDDD
5707 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5708 AccRol(shCount); // DDDCCCCC:BBB00000
5709 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5710 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5711 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5712 emitcode("anl","a,#0x%02x",
5713 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5714 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5715 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5717 case 6 : // AAAAAABB:CCCCCCDD
5718 emitcode("anl","a,#0x%02x",
5719 SRMask[shCount]); // 000000BB:CCCCCCDD
5720 emitcode("mov","c,acc.0"); // c = B
5721 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5722 AccAXRrl1(x); // BCCCCCCD:D000000B
5723 AccAXRrl1(x); // BBCCCCCC:DD000000
5725 case 7 : // a:x <<= 7
5726 emitcode("anl","a,#0x%02x",
5727 SRMask[shCount]); // 0000000B:CCCCCCCD
5728 emitcode("mov","c,acc.0"); // c = B
5729 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5730 AccAXRrl1(x); // BCCCCCCC:D0000000
5740 /*-----------------------------------------------------------------*/
5741 /* AccAXRsh - right shift a:x known count (0..7) */
5742 /*-----------------------------------------------------------------*/
5743 static void AccAXRsh (char *x, int shCount)
5750 AccAXRrl1(x); // 0->a:x
5754 AccAXRrl1(x); // 0->a:x
5756 AccAXRrl1(x); // 0->a:x
5760 case 5 : // AAAAABBB:CCCCCDDD = a:x
5761 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5762 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5763 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5764 emitcode("anl","a,#0x%02x",
5765 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5766 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5767 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5768 emitcode("anl","a,#0x%02x",
5769 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5770 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5771 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5772 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5774 case 6 : // AABBBBBB:CCDDDDDD
5775 emitcode("mov","c,acc.7");
5776 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5777 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5778 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5779 emitcode("anl","a,#0x%02x",
5780 SRMask[shCount]); // 000000AA:BBBBBBCC
5782 case 7 : // ABBBBBBB:CDDDDDDD
5783 emitcode("mov","c,acc.7"); // c = A
5784 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5785 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5786 emitcode("anl","a,#0x%02x",
5787 SRMask[shCount]); // 0000000A:BBBBBBBC
5797 /*-----------------------------------------------------------------*/
5798 /* AccAXRshS - right shift signed a:x known count (0..7) */
5799 /*-----------------------------------------------------------------*/
5800 static void AccAXRshS (char *x, int shCount)
5807 emitcode("mov","c,acc.7");
5808 AccAXRrl1(x); // s->a:x
5811 emitcode("mov","c,acc.7");
5812 AccAXRrl1(x); // s->a:x
5813 emitcode("mov","c,acc.7");
5814 AccAXRrl1(x); // s->a:x
5818 case 5 : // AAAAABBB:CCCCCDDD = a:x
5819 tlbl = newiTempLabel(NULL);
5820 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5821 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5822 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5823 emitcode("anl","a,#0x%02x",
5824 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5825 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5826 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5827 emitcode("anl","a,#0x%02x",
5828 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5829 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5830 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5831 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5832 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5833 emitcode("orl","a,#0x%02x",
5834 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5835 emitcode("","%05d$:",tlbl->key+100);
5836 break; // SSSSAAAA:BBBCCCCC
5837 case 6 : // AABBBBBB:CCDDDDDD
5838 tlbl = newiTempLabel(NULL);
5839 emitcode("mov","c,acc.7");
5840 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5841 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5842 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5843 emitcode("anl","a,#0x%02x",
5844 SRMask[shCount]); // 000000AA:BBBBBBCC
5845 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5846 emitcode("orl","a,#0x%02x",
5847 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5848 emitcode("","%05d$:",tlbl->key+100);
5850 case 7 : // ABBBBBBB:CDDDDDDD
5851 tlbl = newiTempLabel(NULL);
5852 emitcode("mov","c,acc.7"); // c = A
5853 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5854 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5855 emitcode("anl","a,#0x%02x",
5856 SRMask[shCount]); // 0000000A:BBBBBBBC
5857 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5858 emitcode("orl","a,#0x%02x",
5859 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5860 emitcode("","%05d$:",tlbl->key+100);
5870 /*-----------------------------------------------------------------*/
5871 /* shiftL2Left2Result - shift left two bytes from left to result */
5872 /*-----------------------------------------------------------------*/
5873 static void shiftL2Left2Result (operand *left, int offl,
5874 operand *result, int offr, int shCount)
5876 if(sameRegs(AOP(result), AOP(left)) &&
5877 ((offl + MSB16) == offr)){
5878 /* don't crash result[offr] */
5879 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5880 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5882 movLeft2Result(left,offl, result, offr, 0);
5883 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5885 /* ax << shCount (x = lsb(result))*/
5886 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5887 aopPut(AOP(result),"a",offr+MSB16);
5893 /*-----------------------------------------------------------------*/
5894 /* shiftR2Left2Result - shift right two bytes from left to result */
5895 /*-----------------------------------------------------------------*/
5896 static void shiftR2Left2Result (operand *left, int offl,
5897 operand *result, int offr,
5898 int shCount, int sign)
5900 if(sameRegs(AOP(result), AOP(left)) &&
5901 ((offl + MSB16) == offr)){
5902 /* don't crash result[offr] */
5903 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5904 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5906 movLeft2Result(left,offl, result, offr, 0);
5907 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5909 /* a:x >> shCount (x = lsb(result))*/
5911 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5913 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5914 if(getDataSize(result) > 1)
5915 aopPut(AOP(result),"a",offr+MSB16);
5921 /*-----------------------------------------------------------------*/
5922 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5923 /*-----------------------------------------------------------------*/
5924 static void shiftLLeftOrResult (operand *left, int offl,
5925 operand *result, int offr, int shCount)
5927 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5928 /* shift left accumulator */
5930 /* or with result */
5931 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5932 /* back to result */
5933 aopPut(AOP(result),"a",offr);
5939 /*-----------------------------------------------------------------*/
5940 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5941 /*-----------------------------------------------------------------*/
5942 static void shiftRLeftOrResult (operand *left, int offl,
5943 operand *result, int offr, int shCount)
5945 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5946 /* shift right accumulator */
5948 /* or with result */
5949 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5950 /* back to result */
5951 aopPut(AOP(result),"a",offr);
5957 /*-----------------------------------------------------------------*/
5958 /* genlshOne - left shift a one byte quantity by known count */
5959 /*-----------------------------------------------------------------*/
5960 static void genlshOne (operand *result, operand *left, int shCount)
5962 D(emitcode(";", "genlshOne "););
5963 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5969 /*-----------------------------------------------------------------*/
5970 /* genlshTwo - left shift two bytes by known amount != 0 */
5971 /*-----------------------------------------------------------------*/
5972 static void genlshTwo (operand *result,operand *left, int shCount)
5976 D(emitcode(";", "genlshTwo "););
5978 size = getDataSize(result);
5980 /* if shCount >= 8 */
5986 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5988 movLeft2Result(left, LSB, result, MSB16, 0);
5990 aopPut(AOP(result),zero,LSB);
5993 /* 1 <= shCount <= 7 */
5996 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5998 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6005 /*-----------------------------------------------------------------*/
6006 /* shiftLLong - shift left one long from left to result */
6007 /* offl = LSB or MSB16 */
6008 /*-----------------------------------------------------------------*/
6009 static void shiftLLong (operand *left, operand *result, int offr )
6012 int size = AOP_SIZE(result);
6014 if(size >= LSB+offr){
6015 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
6017 emitcode("add","a,acc");
6018 if (sameRegs(AOP(left),AOP(result)) &&
6019 size >= MSB16+offr && offr != LSB )
6020 emitcode("xch","a,%s",
6021 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
6023 aopPut(AOP(result),"a",LSB+offr);
6026 if(size >= MSB16+offr){
6027 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6028 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
6031 emitcode("rlc","a");
6032 if (sameRegs(AOP(left),AOP(result)) &&
6033 size >= MSB24+offr && offr != LSB)
6034 emitcode("xch","a,%s",
6035 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
6037 aopPut(AOP(result),"a",MSB16+offr);
6040 if(size >= MSB24+offr){
6041 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6042 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
6045 emitcode("rlc","a");
6046 if (sameRegs(AOP(left),AOP(result)) &&
6047 size >= MSB32+offr && offr != LSB )
6048 emitcode("xch","a,%s",
6049 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
6051 aopPut(AOP(result),"a",MSB24+offr);
6054 if(size > MSB32+offr){
6055 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6056 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
6059 emitcode("rlc","a");
6060 aopPut(AOP(result),"a",MSB32+offr);
6063 aopPut(AOP(result),zero,LSB);
6069 /*-----------------------------------------------------------------*/
6070 /* genlshFour - shift four byte by a known amount != 0 */
6071 /*-----------------------------------------------------------------*/
6072 static void genlshFour (operand *result, operand *left, int shCount)
6076 D(emitcode(";", "genlshFour "););
6078 size = AOP_SIZE(result);
6080 /* if shifting more that 3 bytes */
6081 if (shCount >= 24 ) {
6084 /* lowest order of left goes to the highest
6085 order of the destination */
6086 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6088 movLeft2Result(left, LSB, result, MSB32, 0);
6089 aopPut(AOP(result),zero,LSB);
6090 aopPut(AOP(result),zero,MSB16);
6091 aopPut(AOP(result),zero,MSB32);
6095 /* more than two bytes */
6096 else if ( shCount >= 16 ) {
6097 /* lower order two bytes goes to higher order two bytes */
6099 /* if some more remaining */
6101 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6103 movLeft2Result(left, MSB16, result, MSB32, 0);
6104 movLeft2Result(left, LSB, result, MSB24, 0);
6106 aopPut(AOP(result),zero,MSB16);
6107 aopPut(AOP(result),zero,LSB);
6111 /* if more than 1 byte */
6112 else if ( shCount >= 8 ) {
6113 /* lower order three bytes goes to higher order three bytes */
6117 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6119 movLeft2Result(left, LSB, result, MSB16, 0);
6121 else{ /* size = 4 */
6123 movLeft2Result(left, MSB24, result, MSB32, 0);
6124 movLeft2Result(left, MSB16, result, MSB24, 0);
6125 movLeft2Result(left, LSB, result, MSB16, 0);
6126 aopPut(AOP(result),zero,LSB);
6128 else if(shCount == 1)
6129 shiftLLong(left, result, MSB16);
6131 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6132 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6133 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6134 aopPut(AOP(result),zero,LSB);
6139 /* 1 <= shCount <= 7 */
6140 else if(shCount <= 2){
6141 shiftLLong(left, result, LSB);
6143 shiftLLong(result, result, LSB);
6145 /* 3 <= shCount <= 7, optimize */
6147 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6148 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6149 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6156 /*-----------------------------------------------------------------*/
6157 /* genLeftShiftLiteral - left shifting by known count */
6158 /*-----------------------------------------------------------------*/
6159 static void genLeftShiftLiteral (operand *left,
6164 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6167 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
6169 freeAsmop(right,NULL,ic,TRUE);
6171 aopOp(left,ic,FALSE, FALSE);
6172 aopOp(result,ic,FALSE, TRUE);
6174 size = getSize(operandType(result));
6177 emitcode("; shift left ","result %d, left %d",size,
6181 /* I suppose that the left size >= result size */
6184 movLeft2Result(left, size, result, size, 0);
6188 else if(shCount >= (size * 8))
6190 aopPut(AOP(result),zero,size);
6194 genlshOne (result,left,shCount);
6198 case 3: /* bug: this is for generic pointers, I bet. */
6199 genlshTwo (result,left,shCount);
6203 genlshFour (result,left,shCount);
6207 freeAsmop(left,NULL,ic,TRUE);
6208 freeAsmop(result,NULL,ic,TRUE);
6212 /*-----------------------------------------------------------------*/
6213 /* genLeftShift - generates code for left shifting */
6214 /*-----------------------------------------------------------------*/
6215 static void genLeftShift (iCode *ic)
6217 operand *left,*right, *result;
6220 symbol *tlbl , *tlbl1;
6222 D(emitcode(";", "genLeftShift "););
6224 right = IC_RIGHT(ic);
6226 result = IC_RESULT(ic);
6228 aopOp(right,ic,FALSE, FALSE);
6231 /* if the shift count is known then do it
6232 as efficiently as possible */
6233 if (AOP_TYPE(right) == AOP_LIT) {
6234 genLeftShiftLiteral (left,right,result,ic);
6239 /* shift count is unknown then we have to form
6240 a loop get the loop count in B : Note: we take
6241 only the lower order byte since shifting
6242 more that 32 bits make no sense anyway, ( the
6243 largest size of an object can be only 32 bits ) */
6245 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6246 emitcode("inc","b");
6247 freeAsmop (right,NULL,ic,TRUE);
6248 aopOp(left,ic,FALSE, FALSE);
6249 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6251 /* now move the left to the result if they are not the
6253 if (!sameRegs(AOP(left),AOP(result)) &&
6254 AOP_SIZE(result) > 1) {
6256 size = AOP_SIZE(result);
6258 _startLazyDPSEvaluation();
6260 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6261 if (*l == '@' && (IS_AOP_PREG(result))) {
6263 emitcode("mov","a,%s",l);
6264 aopPut(AOP(result),"a",offset);
6266 aopPut(AOP(result),l,offset);
6269 _endLazyDPSEvaluation();
6272 tlbl = newiTempLabel(NULL);
6273 size = AOP_SIZE(result);
6275 tlbl1 = newiTempLabel(NULL);
6277 /* if it is only one byte then */
6279 symbol *tlbl1 = newiTempLabel(NULL);
6281 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6283 emitcode("sjmp","%05d$",tlbl1->key+100);
6284 emitcode("","%05d$:",tlbl->key+100);
6285 emitcode("add","a,acc");
6286 emitcode("","%05d$:",tlbl1->key+100);
6287 emitcode("djnz","b,%05d$",tlbl->key+100);
6288 aopPut(AOP(result),"a",0);
6292 reAdjustPreg(AOP(result));
6294 emitcode("sjmp","%05d$",tlbl1->key+100);
6295 emitcode("","%05d$:",tlbl->key+100);
6296 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6298 emitcode("add","a,acc");
6299 aopPut(AOP(result),"a",offset++);
6300 _startLazyDPSEvaluation();
6302 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6304 emitcode("rlc","a");
6305 aopPut(AOP(result),"a",offset++);
6307 _endLazyDPSEvaluation();
6308 reAdjustPreg(AOP(result));
6310 emitcode("","%05d$:",tlbl1->key+100);
6311 emitcode("djnz","b,%05d$",tlbl->key+100);
6313 freeAsmop(left,NULL,ic,TRUE);
6314 freeAsmop(result,NULL,ic,TRUE);
6319 /*-----------------------------------------------------------------*/
6320 /* genrshOne - right shift a one byte quantity by known count */
6321 /*-----------------------------------------------------------------*/
6322 static void genrshOne (operand *result, operand *left,
6323 int shCount, int sign)
6325 D(emitcode(";", "genrshOne"););
6326 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6332 /*-----------------------------------------------------------------*/
6333 /* genrshTwo - right shift two bytes by known amount != 0 */
6334 /*-----------------------------------------------------------------*/
6335 static void genrshTwo (operand *result,operand *left,
6336 int shCount, int sign)
6338 D(emitcode(";", "genrshTwo"););
6340 /* if shCount >= 8 */
6344 shiftR1Left2Result(left, MSB16, result, LSB,
6347 movLeft2Result(left, MSB16, result, LSB, sign);
6348 addSign(result, MSB16, sign);
6351 /* 1 <= shCount <= 7 */
6353 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6359 /*-----------------------------------------------------------------*/
6360 /* shiftRLong - shift right one long from left to result */
6361 /* offl = LSB or MSB16 */
6362 /*-----------------------------------------------------------------*/
6363 static void shiftRLong (operand *left, int offl,
6364 operand *result, int sign)
6367 emitcode("clr","c");
6368 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6370 emitcode("mov","c,acc.7");
6371 emitcode("rrc","a");
6372 aopPut(AOP(result),"a",MSB32-offl);
6374 /* add sign of "a" */
6375 addSign(result, MSB32, sign);
6377 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6378 emitcode("rrc","a");
6379 aopPut(AOP(result),"a",MSB24-offl);
6381 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6382 emitcode("rrc","a");
6383 aopPut(AOP(result),"a",MSB16-offl);
6386 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6387 emitcode("rrc","a");
6388 aopPut(AOP(result),"a",LSB);
6395 /*-----------------------------------------------------------------*/
6396 /* genrshFour - shift four byte by a known amount != 0 */
6397 /*-----------------------------------------------------------------*/
6398 static void genrshFour (operand *result, operand *left,
6399 int shCount, int sign)
6401 D(emitcode(";", "genrshFour"););
6403 /* if shifting more that 3 bytes */
6404 if(shCount >= 24 ) {
6407 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6409 movLeft2Result(left, MSB32, result, LSB, sign);
6410 addSign(result, MSB16, sign);
6412 else if(shCount >= 16){
6415 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6417 movLeft2Result(left, MSB24, result, LSB, 0);
6418 movLeft2Result(left, MSB32, result, MSB16, sign);
6420 addSign(result, MSB24, sign);
6422 else if(shCount >= 8){
6425 shiftRLong(left, MSB16, result, sign);
6426 else if(shCount == 0){
6427 movLeft2Result(left, MSB16, result, LSB, 0);
6428 movLeft2Result(left, MSB24, result, MSB16, 0);
6429 movLeft2Result(left, MSB32, result, MSB24, sign);
6430 addSign(result, MSB32, sign);
6433 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6434 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6435 /* the last shift is signed */
6436 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6437 addSign(result, MSB32, sign);
6440 else{ /* 1 <= shCount <= 7 */
6442 shiftRLong(left, LSB, result, sign);
6444 shiftRLong(result, LSB, result, sign);
6447 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6448 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6449 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6457 /*-----------------------------------------------------------------*/
6458 /* genRightShiftLiteral - right shifting by known count */
6459 /*-----------------------------------------------------------------*/
6460 static void genRightShiftLiteral (operand *left,
6466 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6469 D(emitcode(";", "genRightShiftLiteral"););
6471 freeAsmop(right,NULL,ic,TRUE);
6473 aopOp(left,ic,FALSE, FALSE);
6474 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6477 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6481 size = getDataSize(left);
6482 /* test the LEFT size !!! */
6484 /* I suppose that the left size >= result size */
6486 size = getDataSize(result);
6488 movLeft2Result(left, size, result, size, 0);
6491 else if(shCount >= (size * 8)){
6493 /* get sign in acc.7 */
6494 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6495 addSign(result, LSB, sign);
6499 genrshOne (result,left,shCount,sign);
6503 genrshTwo (result,left,shCount,sign);
6507 genrshFour (result,left,shCount,sign);
6513 freeAsmop(left,NULL,ic,TRUE);
6514 freeAsmop(result,NULL,ic,TRUE);
6519 /*-----------------------------------------------------------------*/
6520 /* genSignedRightShift - right shift of signed number */
6521 /*-----------------------------------------------------------------*/
6522 static void genSignedRightShift (iCode *ic)
6524 operand *right, *left, *result;
6527 symbol *tlbl, *tlbl1 ;
6529 D(emitcode(";", "genSignedRightShift "););
6531 /* we do it the hard way put the shift count in b
6532 and loop thru preserving the sign */
6534 right = IC_RIGHT(ic);
6536 result = IC_RESULT(ic);
6538 aopOp(right,ic,FALSE, FALSE);
6541 if ( AOP_TYPE(right) == AOP_LIT) {
6542 genRightShiftLiteral (left,right,result,ic,1);
6546 /* shift count is unknown then we have to form
6547 a loop get the loop count in B : Note: we take
6548 only the lower order byte since shifting
6549 more that 32 bits make no sense anyway, ( the
6550 largest size of an object can be only 32 bits ) */
6552 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6553 emitcode("inc","b");
6554 freeAsmop (right,NULL,ic,TRUE);
6555 aopOp(left,ic,FALSE, FALSE);
6556 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6558 /* now move the left to the result if they are not the
6560 if (!sameRegs(AOP(left),AOP(result)) &&
6561 AOP_SIZE(result) > 1) {
6563 size = AOP_SIZE(result);
6565 _startLazyDPSEvaluation();
6567 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6568 if (*l == '@' && IS_AOP_PREG(result)) {
6570 emitcode("mov","a,%s",l);
6571 aopPut(AOP(result),"a",offset);
6573 aopPut(AOP(result),l,offset);
6576 _endLazyDPSEvaluation();
6579 /* mov the highest order bit to OVR */
6580 tlbl = newiTempLabel(NULL);
6581 tlbl1= newiTempLabel(NULL);
6583 size = AOP_SIZE(result);
6585 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6586 emitcode("rlc","a");
6587 emitcode("mov","ov,c");
6588 /* if it is only one byte then */
6590 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6592 emitcode("sjmp","%05d$",tlbl1->key+100);
6593 emitcode("","%05d$:",tlbl->key+100);
6594 emitcode("mov","c,ov");
6595 emitcode("rrc","a");
6596 emitcode("","%05d$:",tlbl1->key+100);
6597 emitcode("djnz","b,%05d$",tlbl->key+100);
6598 aopPut(AOP(result),"a",0);
6602 reAdjustPreg(AOP(result));
6603 emitcode("sjmp","%05d$",tlbl1->key+100);
6604 emitcode("","%05d$:",tlbl->key+100);
6605 emitcode("mov","c,ov");
6606 _startLazyDPSEvaluation();
6608 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6610 emitcode("rrc","a");
6611 aopPut(AOP(result),"a",offset--);
6613 _endLazyDPSEvaluation();
6614 reAdjustPreg(AOP(result));
6615 emitcode("","%05d$:",tlbl1->key+100);
6616 emitcode("djnz","b,%05d$",tlbl->key+100);
6619 freeAsmop(left,NULL,ic,TRUE);
6620 freeAsmop(result,NULL,ic,TRUE);
6623 /*-----------------------------------------------------------------*/
6624 /* genRightShift - generate code for right shifting */
6625 /*-----------------------------------------------------------------*/
6626 static void genRightShift (iCode *ic)
6628 operand *right, *left, *result;
6632 symbol *tlbl, *tlbl1 ;
6634 D(emitcode(";", "genRightShift "););
6636 /* if signed then we do it the hard way preserve the
6637 sign bit moving it inwards */
6638 retype = getSpec(operandType(IC_RESULT(ic)));
6640 if (!SPEC_USIGN(retype)) {
6641 genSignedRightShift (ic);
6645 /* signed & unsigned types are treated the same : i.e. the
6646 signed is NOT propagated inwards : quoting from the
6647 ANSI - standard : "for E1 >> E2, is equivalent to division
6648 by 2**E2 if unsigned or if it has a non-negative value,
6649 otherwise the result is implementation defined ", MY definition
6650 is that the sign does not get propagated */
6652 right = IC_RIGHT(ic);
6654 result = IC_RESULT(ic);
6656 aopOp(right,ic,FALSE, FALSE);
6659 /* if the shift count is known then do it
6660 as efficiently as possible */
6661 if (AOP_TYPE(right) == AOP_LIT) {
6662 genRightShiftLiteral (left,right,result,ic, 0);
6667 /* shift count is unknown then we have to form
6668 a loop get the loop count in B : Note: we take
6669 only the lower order byte since shifting
6670 more that 32 bits make no sense anyway, ( the
6671 largest size of an object can be only 32 bits ) */
6673 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6674 emitcode("inc","b");
6675 freeAsmop (right,NULL,ic,TRUE);
6676 aopOp(left,ic,FALSE, FALSE);
6677 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6679 /* now move the left to the result if they are not the
6681 if (!sameRegs(AOP(left),AOP(result)) &&
6682 AOP_SIZE(result) > 1) {
6684 size = AOP_SIZE(result);
6686 _startLazyDPSEvaluation();
6688 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6689 if (*l == '@' && IS_AOP_PREG(result)) {
6691 emitcode("mov","a,%s",l);
6692 aopPut(AOP(result),"a",offset);
6694 aopPut(AOP(result),l,offset);
6697 _endLazyDPSEvaluation();
6700 tlbl = newiTempLabel(NULL);
6701 tlbl1= newiTempLabel(NULL);
6702 size = AOP_SIZE(result);
6705 /* if it is only one byte then */
6707 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6709 emitcode("sjmp","%05d$",tlbl1->key+100);
6710 emitcode("","%05d$:",tlbl->key+100);
6712 emitcode("rrc","a");
6713 emitcode("","%05d$:",tlbl1->key+100);
6714 emitcode("djnz","b,%05d$",tlbl->key+100);
6715 aopPut(AOP(result),"a",0);
6719 reAdjustPreg(AOP(result));
6720 emitcode("sjmp","%05d$",tlbl1->key+100);
6721 emitcode("","%05d$:",tlbl->key+100);
6723 _startLazyDPSEvaluation();
6725 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6727 emitcode("rrc","a");
6728 aopPut(AOP(result),"a",offset--);
6730 _endLazyDPSEvaluation();
6731 reAdjustPreg(AOP(result));
6733 emitcode("","%05d$:",tlbl1->key+100);
6734 emitcode("djnz","b,%05d$",tlbl->key+100);
6737 freeAsmop(left,NULL,ic,TRUE);
6738 freeAsmop(result,NULL,ic,TRUE);
6741 /*-----------------------------------------------------------------*/
6742 /* genUnpackBits - generates code for unpacking bits */
6743 /*-----------------------------------------------------------------*/
6744 static void genUnpackBits (operand *result, char *rname, int ptype)
6751 D(emitcode(";", "genUnpackBits "););
6753 etype = getSpec(operandType(result));
6755 /* read the first byte */
6760 emitcode("mov","a,@%s",rname);
6764 emitcode("movx","a,@%s",rname);
6768 emitcode("movx","a,@dptr");
6772 emitcode("clr","a");
6773 emitcode("movc","a","@a+dptr");
6777 emitcode("lcall","__gptrget");
6781 /* if we have bitdisplacement then it fits */
6782 /* into this byte completely or if length is */
6783 /* less than a byte */
6784 if ((shCnt = SPEC_BSTR(etype)) ||
6785 (SPEC_BLEN(etype) <= 8)) {
6787 /* shift right acc */
6790 emitcode("anl","a,#0x%02x",
6791 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6792 aopPut(AOP(result),"a",offset);
6796 /* bit field did not fit in a byte */
6797 rlen = SPEC_BLEN(etype) - 8;
6798 aopPut(AOP(result),"a",offset++);
6805 emitcode("inc","%s",rname);
6806 emitcode("mov","a,@%s",rname);
6810 emitcode("inc","%s",rname);
6811 emitcode("movx","a,@%s",rname);
6815 emitcode("inc","dptr");
6816 emitcode("movx","a,@dptr");
6820 emitcode("clr","a");
6821 emitcode("inc","dptr");
6822 emitcode("movc","a","@a+dptr");
6826 emitcode("inc","dptr");
6827 emitcode("lcall","__gptrget");
6832 /* if we are done */
6836 aopPut(AOP(result),"a",offset++);
6841 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6842 aopPut(AOP(result),"a",offset);
6849 /*-----------------------------------------------------------------*/
6850 /* genDataPointerGet - generates code when ptr offset is known */
6851 /*-----------------------------------------------------------------*/
6852 static void genDataPointerGet (operand *left,
6858 int size , offset = 0;
6859 aopOp(result,ic,TRUE, FALSE);
6861 /* get the string representation of the name */
6862 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6863 size = AOP_SIZE(result);
6864 _startLazyDPSEvaluation();
6867 sprintf(buffer,"(%s + %d)",l+1,offset);
6869 sprintf(buffer,"%s",l+1);
6870 aopPut(AOP(result),buffer,offset++);
6872 _endLazyDPSEvaluation();
6874 freeAsmop(left,NULL,ic,TRUE);
6875 freeAsmop(result,NULL,ic,TRUE);
6878 /*-----------------------------------------------------------------*/
6879 /* genNearPointerGet - emitcode for near pointer fetch */
6880 /*-----------------------------------------------------------------*/
6881 static void genNearPointerGet (operand *left,
6888 sym_link *rtype, *retype, *letype;
6889 sym_link *ltype = operandType(left);
6892 rtype = operandType(result);
6893 retype= getSpec(rtype);
6894 letype= getSpec(ltype);
6896 aopOp(left,ic,FALSE, FALSE);
6898 /* if left is rematerialisable and
6899 result is not bit variable type and
6900 the left is pointer to data space i.e
6901 lower 128 bytes of space */
6902 if (AOP_TYPE(left) == AOP_IMMD &&
6903 !IS_BITVAR(retype) &&
6904 !IS_BITVAR(letype) &&
6905 DCL_TYPE(ltype) == POINTER) {
6906 genDataPointerGet (left,result,ic);
6910 /* if the value is already in a pointer register
6911 then don't need anything more */
6912 if (!AOP_INPREG(AOP(left))) {
6913 /* otherwise get a free pointer register */
6915 preg = getFreePtr(ic,&aop,FALSE);
6916 emitcode("mov","%s,%s",
6918 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6919 rname = preg->name ;
6921 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6923 freeAsmop(left,NULL,ic,TRUE);
6924 aopOp (result,ic,FALSE, FALSE);
6926 /* if bitfield then unpack the bits */
6927 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6928 genUnpackBits (result,rname,POINTER);
6930 /* we have can just get the values */
6931 int size = AOP_SIZE(result);
6935 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6937 emitcode("mov","a,@%s",rname);
6938 aopPut(AOP(result),"a",offset);
6940 sprintf(buffer,"@%s",rname);
6941 aopPut(AOP(result),buffer,offset);
6945 emitcode("inc","%s",rname);
6949 /* now some housekeeping stuff */
6951 /* we had to allocate for this iCode */
6952 freeAsmop(NULL,aop,ic,TRUE);
6954 /* we did not allocate which means left
6955 already in a pointer register, then
6956 if size > 0 && this could be used again
6957 we have to point it back to where it
6959 if (AOP_SIZE(result) > 1 &&
6960 !OP_SYMBOL(left)->remat &&
6961 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6963 int size = AOP_SIZE(result) - 1;
6965 emitcode("dec","%s",rname);
6970 freeAsmop(result,NULL,ic,TRUE);
6974 /*-----------------------------------------------------------------*/
6975 /* genPagedPointerGet - emitcode for paged pointer fetch */
6976 /*-----------------------------------------------------------------*/
6977 static void genPagedPointerGet (operand *left,
6984 sym_link *rtype, *retype, *letype;
6986 rtype = operandType(result);
6987 retype= getSpec(rtype);
6988 letype= getSpec(operandType(left));
6989 aopOp(left,ic,FALSE, FALSE);
6991 /* if the value is already in a pointer register
6992 then don't need anything more */
6993 if (!AOP_INPREG(AOP(left))) {
6994 /* otherwise get a free pointer register */
6996 preg = getFreePtr(ic,&aop,FALSE);
6997 emitcode("mov","%s,%s",
6999 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
7000 rname = preg->name ;
7002 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
7004 freeAsmop(left,NULL,ic,TRUE);
7005 aopOp (result,ic,FALSE, FALSE);
7007 /* if bitfield then unpack the bits */
7008 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7009 genUnpackBits (result,rname,PPOINTER);
7011 /* we have can just get the values */
7012 int size = AOP_SIZE(result);
7017 emitcode("movx","a,@%s",rname);
7018 aopPut(AOP(result),"a",offset);
7023 emitcode("inc","%s",rname);
7027 /* now some housekeeping stuff */
7029 /* we had to allocate for this iCode */
7030 freeAsmop(NULL,aop,ic,TRUE);
7032 /* we did not allocate which means left
7033 already in a pointer register, then
7034 if size > 0 && this could be used again
7035 we have to point it back to where it
7037 if (AOP_SIZE(result) > 1 &&
7038 !OP_SYMBOL(left)->remat &&
7039 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7041 int size = AOP_SIZE(result) - 1;
7043 emitcode("dec","%s",rname);
7048 freeAsmop(result,NULL,ic,TRUE);
7053 /*-----------------------------------------------------------------*/
7054 /* genFarPointerGet - gget value from far space */
7055 /*-----------------------------------------------------------------*/
7056 static void genFarPointerGet (operand *left,
7057 operand *result, iCode *ic)
7060 sym_link *retype = getSpec(operandType(result));
7061 sym_link *letype = getSpec(operandType(left));
7062 D(emitcode(";", "genFarPointerGet"););
7064 aopOp(left,ic,FALSE, FALSE);
7066 /* if the operand is already in dptr
7067 then we do nothing else we move the value to dptr */
7068 if (AOP_TYPE(left) != AOP_STR) {
7069 /* if this is remateriazable */
7070 if (AOP_TYPE(left) == AOP_IMMD)
7072 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7076 /* we need to get it byte by byte */
7077 _startLazyDPSEvaluation();
7078 if (AOP_TYPE(left) != AOP_DPTR)
7080 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7081 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7082 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7086 /* We need to generate a load to DPTR indirect through DPTR. */
7087 D(emitcode(";", "genFarPointerGet -- indirection special case."););
7088 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7089 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7090 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7091 emitcode("pop", "dph");
7092 emitcode("pop", "dpl");
7094 _endLazyDPSEvaluation();
7097 /* so dptr know contains the address */
7098 freeAsmop(left,NULL,ic,TRUE);
7099 aopOp(result,ic,FALSE, TRUE);
7101 /* if bit then unpack */
7102 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7103 genUnpackBits(result,"dptr",FPOINTER);
7105 size = AOP_SIZE(result);
7108 _startLazyDPSEvaluation();
7114 emitcode("movx","a,@dptr");
7116 emitcode("inc","dptr");
7118 aopPut(AOP(result),"a",offset++);
7120 _endLazyDPSEvaluation();
7123 freeAsmop(result,NULL,ic,TRUE);
7126 /*-----------------------------------------------------------------*/
7127 /* emitcodePointerGet - gget value from code space */
7128 /*-----------------------------------------------------------------*/
7129 static void emitcodePointerGet (operand *left,
7130 operand *result, iCode *ic)
7133 sym_link *retype = getSpec(operandType(result));
7135 aopOp(left,ic,FALSE, FALSE);
7137 /* if the operand is already in dptr
7138 then we do nothing else we move the value to dptr */
7139 if (AOP_TYPE(left) != AOP_STR) {
7140 /* if this is remateriazable */
7141 if (AOP_TYPE(left) == AOP_IMMD)
7143 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7146 { /* we need to get it byte by byte */
7147 _startLazyDPSEvaluation();
7148 if (AOP_TYPE(left) != AOP_DPTR)
7150 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7151 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7152 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7156 /* We need to generate a load to DPTR indirect through DPTR. */
7157 D(emitcode(";", "gencodePointerGet -- indirection special case."););
7158 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7159 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7160 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7161 emitcode("pop", "dph");
7162 emitcode("pop", "dpl");
7164 _endLazyDPSEvaluation();
7167 /* so dptr know contains the address */
7168 freeAsmop(left,NULL,ic,TRUE);
7169 aopOp(result,ic,FALSE, TRUE);
7171 /* if bit then unpack */
7172 if (IS_BITVAR(retype))
7173 genUnpackBits(result,"dptr",CPOINTER);
7175 size = AOP_SIZE(result);
7178 _startLazyDPSEvaluation();
7184 emitcode("clr","a");
7185 emitcode("movc","a,@a+dptr");
7187 emitcode("inc","dptr");
7188 aopPut(AOP(result),"a",offset++);
7190 _endLazyDPSEvaluation();
7193 freeAsmop(result,NULL,ic,TRUE);
7196 /*-----------------------------------------------------------------*/
7197 /* genGenPointerGet - gget value from generic pointer space */
7198 /*-----------------------------------------------------------------*/
7199 static void genGenPointerGet (operand *left,
7200 operand *result, iCode *ic)
7203 sym_link *retype = getSpec(operandType(result));
7204 sym_link *letype = getSpec(operandType(left));
7206 aopOp(left,ic,FALSE, TRUE);
7208 /* if the operand is already in dptr
7209 then we do nothing else we move the value to dptr */
7210 if (AOP_TYPE(left) != AOP_STR) {
7211 /* if this is remateriazable */
7212 if (AOP_TYPE(left) == AOP_IMMD) {
7213 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7214 emitcode("mov","b,#%d",pointerCode(retype));
7216 else { /* we need to get it byte by byte */
7217 _startLazyDPSEvaluation();
7218 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7219 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7220 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7221 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7222 _endLazyDPSEvaluation();
7225 /* so dptr know contains the address */
7226 freeAsmop(left,NULL,ic,TRUE);
7227 aopOp(result,ic,FALSE, TRUE);
7229 /* if bit then unpack */
7230 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7231 genUnpackBits(result,"dptr",GPOINTER);
7233 size = AOP_SIZE(result);
7237 emitcode("lcall","__gptrget");
7238 aopPut(AOP(result),"a",offset++);
7240 emitcode("inc","dptr");
7244 freeAsmop(result,NULL,ic,TRUE);
7247 /*-----------------------------------------------------------------*/
7248 /* genPointerGet - generate code for pointer get */
7249 /*-----------------------------------------------------------------*/
7250 static void genPointerGet (iCode *ic)
7252 operand *left, *result ;
7253 sym_link *type, *etype;
7256 D(emitcode(";", "genPointerGet "););
7259 result = IC_RESULT(ic) ;
7261 /* depending on the type of pointer we need to
7262 move it to the correct pointer register */
7263 type = operandType(left);
7264 etype = getSpec(type);
7265 /* if left is of type of pointer then it is simple */
7266 if (IS_PTR(type) && !IS_FUNC(type->next))
7267 p_type = DCL_TYPE(type);
7269 /* we have to go by the storage class */
7270 p_type = PTR_TYPE(SPEC_OCLS(etype));
7273 /* now that we have the pointer type we assign
7274 the pointer values */
7279 genNearPointerGet (left,result,ic);
7283 genPagedPointerGet(left,result,ic);
7287 genFarPointerGet (left,result,ic);
7291 emitcodePointerGet (left,result,ic);
7295 genGenPointerGet (left,result,ic);
7301 /*-----------------------------------------------------------------*/
7302 /* genPackBits - generates code for packed bit storage */
7303 /*-----------------------------------------------------------------*/
7304 static void genPackBits (sym_link *etype ,
7306 char *rname, int p_type)
7314 blen = SPEC_BLEN(etype);
7315 bstr = SPEC_BSTR(etype);
7317 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7320 /* if the bit lenth is less than or */
7321 /* it exactly fits a byte then */
7322 if (SPEC_BLEN(etype) <= 8 ) {
7323 shCount = SPEC_BSTR(etype) ;
7325 /* shift left acc */
7328 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7333 emitcode ("mov","b,a");
7334 emitcode("mov","a,@%s",rname);
7338 emitcode ("mov","b,a");
7339 emitcode("movx","a,@dptr");
7343 emitcode ("push","b");
7344 emitcode ("push","acc");
7345 emitcode ("lcall","__gptrget");
7346 emitcode ("pop","b");
7350 emitcode ("anl","a,#0x%02x",(unsigned char)
7351 ((unsigned char)(0xFF << (blen+bstr)) |
7352 (unsigned char)(0xFF >> (8-bstr)) ) );
7353 emitcode ("orl","a,b");
7354 if (p_type == GPOINTER)
7355 emitcode("pop","b");
7361 emitcode("mov","@%s,a",rname);
7365 emitcode("movx","@dptr,a");
7369 emitcode("lcall","__gptrput");
7374 if ( SPEC_BLEN(etype) <= 8 )
7377 emitcode("inc","%s",rname);
7378 rLen = SPEC_BLEN(etype) ;
7380 /* now generate for lengths greater than one byte */
7383 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7393 emitcode("mov","@%s,a",rname);
7395 emitcode("mov","@%s,%s",rname,l);
7400 emitcode("movx","@dptr,a");
7405 emitcode("lcall","__gptrput");
7408 emitcode ("inc","%s",rname);
7413 /* last last was not complete */
7415 /* save the byte & read byte */
7418 emitcode ("mov","b,a");
7419 emitcode("mov","a,@%s",rname);
7423 emitcode ("mov","b,a");
7424 emitcode("movx","a,@dptr");
7428 emitcode ("push","b");
7429 emitcode ("push","acc");
7430 emitcode ("lcall","__gptrget");
7431 emitcode ("pop","b");
7435 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << rLen) );
7436 emitcode ("orl","a,b");
7439 if (p_type == GPOINTER)
7440 emitcode("pop","b");
7445 emitcode("mov","@%s,a",rname);
7449 emitcode("movx","@dptr,a");
7453 emitcode("lcall","__gptrput");
7457 /*-----------------------------------------------------------------*/
7458 /* genDataPointerSet - remat pointer to data space */
7459 /*-----------------------------------------------------------------*/
7460 static void genDataPointerSet(operand *right,
7464 int size, offset = 0 ;
7465 char *l, buffer[256];
7467 aopOp(right,ic,FALSE, FALSE);
7469 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7470 size = AOP_SIZE(right);
7473 sprintf(buffer,"(%s + %d)",l+1,offset);
7475 sprintf(buffer,"%s",l+1);
7476 emitcode("mov","%s,%s",buffer,
7477 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7480 freeAsmop(right,NULL,ic,TRUE);
7481 freeAsmop(result,NULL,ic,TRUE);
7484 /*-----------------------------------------------------------------*/
7485 /* genNearPointerSet - emitcode for near pointer put */
7486 /*-----------------------------------------------------------------*/
7487 static void genNearPointerSet (operand *right,
7494 sym_link *retype, *letype;
7495 sym_link *ptype = operandType(result);
7497 retype= getSpec(operandType(right));
7498 letype= getSpec(ptype);
7500 aopOp(result,ic,FALSE, FALSE);
7502 /* if the result is rematerializable &
7503 in data space & not a bit variable */
7504 if (AOP_TYPE(result) == AOP_IMMD &&
7505 DCL_TYPE(ptype) == POINTER &&
7506 !IS_BITVAR(retype) &&
7507 !IS_BITVAR(letype)) {
7508 genDataPointerSet (right,result,ic);
7512 /* if the value is already in a pointer register
7513 then don't need anything more */
7514 if (!AOP_INPREG(AOP(result))) {
7515 /* otherwise get a free pointer register */
7517 preg = getFreePtr(ic,&aop,FALSE);
7518 emitcode("mov","%s,%s",
7520 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7521 rname = preg->name ;
7523 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7525 freeAsmop(result,NULL,ic,TRUE);
7526 aopOp (right,ic,FALSE, FALSE);
7528 /* if bitfield then unpack the bits */
7529 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7530 genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
7532 /* we have can just get the values */
7533 int size = AOP_SIZE(right);
7537 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7540 emitcode("mov","@%s,a",rname);
7542 emitcode("mov","@%s,%s",rname,l);
7544 emitcode("inc","%s",rname);
7549 /* now some housekeeping stuff */
7551 /* we had to allocate for this iCode */
7552 freeAsmop(NULL,aop,ic,TRUE);
7554 /* we did not allocate which means left
7555 already in a pointer register, then
7556 if size > 0 && this could be used again
7557 we have to point it back to where it
7559 if (AOP_SIZE(right) > 1 &&
7560 !OP_SYMBOL(result)->remat &&
7561 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7563 int size = AOP_SIZE(right) - 1;
7565 emitcode("dec","%s",rname);
7570 freeAsmop(right,NULL,ic,TRUE);
7575 /*-----------------------------------------------------------------*/
7576 /* genPagedPointerSet - emitcode for Paged pointer put */
7577 /*-----------------------------------------------------------------*/
7578 static void genPagedPointerSet (operand *right,
7585 sym_link *retype, *letype;
7587 retype= getSpec(operandType(right));
7588 letype= getSpec(operandType(result));
7590 aopOp(result,ic,FALSE, FALSE);
7592 /* if the value is already in a pointer register
7593 then don't need anything more */
7594 if (!AOP_INPREG(AOP(result))) {
7595 /* otherwise get a free pointer register */
7597 preg = getFreePtr(ic,&aop,FALSE);
7598 emitcode("mov","%s,%s",
7600 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7601 rname = preg->name ;
7603 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7605 freeAsmop(result,NULL,ic,TRUE);
7606 aopOp (right,ic,FALSE, FALSE);
7608 /* if bitfield then unpack the bits */
7609 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7610 genPackBits ((IS_BITVAR(retype) ? retype : letype) ,right,rname,PPOINTER);
7612 /* we have can just get the values */
7613 int size = AOP_SIZE(right);
7617 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7620 emitcode("movx","@%s,a",rname);
7623 emitcode("inc","%s",rname);
7629 /* now some housekeeping stuff */
7631 /* we had to allocate for this iCode */
7632 freeAsmop(NULL,aop,ic,TRUE);
7634 /* we did not allocate which means left
7635 already in a pointer register, then
7636 if size > 0 && this could be used again
7637 we have to point it back to where it
7639 if (AOP_SIZE(right) > 1 &&
7640 !OP_SYMBOL(result)->remat &&
7641 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7643 int size = AOP_SIZE(right) - 1;
7645 emitcode("dec","%s",rname);
7650 freeAsmop(right,NULL,ic,TRUE);
7655 /*-----------------------------------------------------------------*/
7656 /* genFarPointerSet - set value from far space */
7657 /*-----------------------------------------------------------------*/
7658 static void genFarPointerSet (operand *right,
7659 operand *result, iCode *ic)
7662 sym_link *retype = getSpec(operandType(right));
7663 sym_link *letype = getSpec(operandType(result));
7665 aopOp(result,ic,FALSE, FALSE);
7667 /* if the operand is already in dptr
7668 then we do nothing else we move the value to dptr */
7669 if (AOP_TYPE(result) != AOP_STR) {
7670 /* if this is remateriazable */
7671 if (AOP_TYPE(result) == AOP_IMMD)
7672 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7675 /* we need to get it byte by byte */
7676 _startLazyDPSEvaluation();
7677 if (AOP_TYPE(result) != AOP_DPTR)
7679 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7680 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7681 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7685 /* We need to generate a load to DPTR indirect through DPTR. */
7686 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7687 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7688 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7689 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7690 emitcode("pop", "dph");
7691 emitcode("pop", "dpl");
7693 _endLazyDPSEvaluation();
7696 /* so dptr know contains the address */
7697 freeAsmop(result,NULL,ic,TRUE);
7698 aopOp(right,ic,FALSE, TRUE);
7700 /* if bit then unpack */
7701 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7702 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",FPOINTER);
7704 size = AOP_SIZE(right);
7707 _startLazyDPSEvaluation();
7709 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7715 emitcode("movx","@dptr,a");
7717 emitcode("inc","dptr");
7719 _endLazyDPSEvaluation();
7722 freeAsmop(right,NULL,ic,TRUE);
7725 /*-----------------------------------------------------------------*/
7726 /* genGenPointerSet - set value from generic pointer space */
7727 /*-----------------------------------------------------------------*/
7728 static void genGenPointerSet (operand *right,
7729 operand *result, iCode *ic)
7732 sym_link *retype = getSpec(operandType(right));
7733 sym_link *letype = getSpec(operandType(result));
7735 aopOp(result,ic,FALSE, TRUE);
7737 /* if the operand is already in dptr
7738 then we do nothing else we move the value to dptr */
7739 if (AOP_TYPE(result) != AOP_STR) {
7740 _startLazyDPSEvaluation();
7741 /* if this is remateriazable */
7742 if (AOP_TYPE(result) == AOP_IMMD) {
7743 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7744 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7746 else { /* we need to get it byte by byte */
7747 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7748 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7749 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7750 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7752 _endLazyDPSEvaluation();
7754 /* so dptr know contains the address */
7755 freeAsmop(result,NULL,ic,TRUE);
7756 aopOp(right,ic,FALSE, TRUE);
7758 /* if bit then unpack */
7759 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7760 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",GPOINTER);
7762 size = AOP_SIZE(right);
7765 _startLazyDPSEvaluation();
7767 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7773 emitcode("lcall","__gptrput");
7775 emitcode("inc","dptr");
7777 _endLazyDPSEvaluation();
7780 freeAsmop(right,NULL,ic,TRUE);
7783 /*-----------------------------------------------------------------*/
7784 /* genPointerSet - stores the value into a pointer location */
7785 /*-----------------------------------------------------------------*/
7786 static void genPointerSet (iCode *ic)
7788 operand *right, *result ;
7789 sym_link *type, *etype;
7792 D(emitcode(";", "genPointerSet "););
7794 right = IC_RIGHT(ic);
7795 result = IC_RESULT(ic) ;
7797 /* depending on the type of pointer we need to
7798 move it to the correct pointer register */
7799 type = operandType(result);
7800 etype = getSpec(type);
7801 /* if left is of type of pointer then it is simple */
7802 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7803 p_type = DCL_TYPE(type);
7806 /* we have to go by the storage class */
7807 p_type = PTR_TYPE(SPEC_OCLS(etype));
7810 /* now that we have the pointer type we assign
7811 the pointer values */
7816 genNearPointerSet (right,result,ic);
7820 genPagedPointerSet (right,result,ic);
7824 genFarPointerSet (right,result,ic);
7828 genGenPointerSet (right,result,ic);
7834 /*-----------------------------------------------------------------*/
7835 /* genIfx - generate code for Ifx statement */
7836 /*-----------------------------------------------------------------*/
7837 static void genIfx (iCode *ic, iCode *popIc)
7839 operand *cond = IC_COND(ic);
7842 D(emitcode(";", "genIfx "););
7844 aopOp(cond,ic,FALSE, FALSE);
7846 /* get the value into acc */
7847 if (AOP_TYPE(cond) != AOP_CRY)
7851 /* the result is now in the accumulator */
7852 freeAsmop(cond,NULL,ic,TRUE);
7854 /* if there was something to be popped then do it */
7858 /* if the condition is a bit variable */
7859 if (isbit && IS_ITEMP(cond) &&
7861 genIfxJump(ic,SPIL_LOC(cond)->rname);
7863 if (isbit && !IS_ITEMP(cond))
7864 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7871 /*-----------------------------------------------------------------*/
7872 /* genAddrOf - generates code for address of */
7873 /*-----------------------------------------------------------------*/
7874 static void genAddrOf (iCode *ic)
7876 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7879 D(emitcode(";", "genAddrOf "););
7881 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7883 /* if the operand is on the stack then we
7884 need to get the stack offset of this
7887 /* if it has an offset then we need to compute
7890 emitcode("mov","a,_bp");
7891 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7892 aopPut(AOP(IC_RESULT(ic)),"a",0);
7894 /* we can just move _bp */
7895 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7897 /* fill the result with zero */
7898 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7901 if (options.stack10bit && size < (FPTRSIZE - 1))
7904 "*** warning: pointer to stack var truncated.\n");
7911 if (options.stack10bit && offset == 2)
7913 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7917 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7924 /* object not on stack then we need the name */
7925 size = AOP_SIZE(IC_RESULT(ic));
7929 char s[SDCC_NAME_MAX];
7931 sprintf(s,"#(%s >> %d)",
7935 sprintf(s,"#%s",sym->rname);
7936 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7940 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7944 /*-----------------------------------------------------------------*/
7945 /* genFarFarAssign - assignment when both are in far space */
7946 /*-----------------------------------------------------------------*/
7947 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7949 int size = AOP_SIZE(right);
7956 /* This is a net loss for size == 1, but a big gain
7959 D(emitcode(";", "genFarFarAssign (improved)"););
7961 aopOp(result,ic,TRUE, TRUE);
7963 _startLazyDPSEvaluation();
7967 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7971 _endLazyDPSEvaluation();
7972 freeAsmop(result,NULL,ic,FALSE);
7973 freeAsmop(right,NULL,ic,FALSE);
7978 D(emitcode(";", "genFarFarAssign "););
7980 /* first push the right side on to the stack */
7981 _startLazyDPSEvaluation();
7983 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7985 emitcode ("push","acc");
7988 freeAsmop(right,NULL,ic,FALSE);
7989 /* now assign DPTR to result */
7990 aopOp(result,ic,FALSE, FALSE);
7991 size = AOP_SIZE(result);
7993 emitcode ("pop","acc");
7994 aopPut(AOP(result),"a",--offset);
7996 freeAsmop(result,NULL,ic,FALSE);
7997 _endLazyDPSEvaluation();
8001 /*-----------------------------------------------------------------*/
8002 /* genAssign - generate code for assignment */
8003 /*-----------------------------------------------------------------*/
8004 static void genAssign (iCode *ic)
8006 operand *result, *right;
8008 unsigned long lit = 0L;
8010 D(emitcode(";", "genAssign "););
8012 result = IC_RESULT(ic);
8013 right = IC_RIGHT(ic) ;
8015 /* if they are the same */
8016 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8019 aopOp(right,ic,FALSE, FALSE);
8021 emitcode(";", "genAssign: resultIsFar = %s",
8022 isOperandInFarSpace(result) ?
8025 /* special case both in far space */
8026 if ((AOP_TYPE(right) == AOP_DPTR ||
8027 AOP_TYPE(right) == AOP_DPTR2) &&
8028 /* IS_TRUE_SYMOP(result) && */
8029 isOperandInFarSpace(result)) {
8031 genFarFarAssign (result,right,ic);
8035 aopOp(result,ic,TRUE, FALSE);
8037 /* if they are the same registers */
8038 if (sameRegs(AOP(right),AOP(result)))
8041 /* if the result is a bit */
8042 if (AOP_TYPE(result) == AOP_CRY) {
8044 /* if the right size is a literal then
8045 we know what the value is */
8046 if (AOP_TYPE(right) == AOP_LIT) {
8047 if (((int) operandLitValue(right)))
8048 aopPut(AOP(result),one,0);
8050 aopPut(AOP(result),zero,0);
8054 /* the right is also a bit variable */
8055 if (AOP_TYPE(right) == AOP_CRY) {
8056 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8057 aopPut(AOP(result),"c",0);
8063 aopPut(AOP(result),"a",0);
8067 /* bit variables done */
8069 size = AOP_SIZE(result);
8071 if(AOP_TYPE(right) == AOP_LIT)
8072 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8075 (AOP_TYPE(result) != AOP_REG) &&
8076 (AOP_TYPE(right) == AOP_LIT) &&
8077 !IS_FLOAT(operandType(right))
8078 #ifndef LAZY_DPS_OPT
8084 D(emitcode(";", "Kevin's better literal load code"););
8085 _startLazyDPSEvaluation();
8086 while (size && ((unsigned int)(lit >> (offset*8)) != 0))
8089 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
8094 /* And now fill the rest with zeros. */
8097 emitcode("clr","a");
8101 aopPut(AOP(result), "a", offset++);
8103 _endLazyDPSEvaluation();
8105 emitcode("clr","a");
8107 _startLazyDPSEvaluation();
8110 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
8111 aopPut(AOP(result),"a",size);
8114 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
8117 _endLazyDPSEvaluation();
8122 _startLazyDPSEvaluation();
8126 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8130 _endLazyDPSEvaluation();
8134 freeAsmop (right,NULL,ic,FALSE);
8135 freeAsmop (result,NULL,ic,TRUE);
8138 /*-----------------------------------------------------------------*/
8139 /* genJumpTab - generates code for jump table */
8140 /*-----------------------------------------------------------------*/
8141 static void genJumpTab (iCode *ic)
8146 D(emitcode(";", "genJumpTab "););
8148 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
8149 /* get the condition into accumulator */
8150 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
8152 /* multiply by four! */
8153 emitcode("add","a,acc");
8154 emitcode("add","a,acc");
8155 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8157 jtab = newiTempLabel(NULL);
8158 emitcode("mov","dptr,#%05d$",jtab->key+100);
8159 emitcode("jmp","@a+dptr");
8160 emitcode("","%05d$:",jtab->key+100);
8161 /* now generate the jump labels */
8162 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8163 jtab = setNextItem(IC_JTLABELS(ic)))
8164 emitcode("ljmp","%05d$",jtab->key+100);
8168 /*-----------------------------------------------------------------*/
8169 /* genCast - gen code for casting */
8170 /*-----------------------------------------------------------------*/
8171 static void genCast (iCode *ic)
8173 operand *result = IC_RESULT(ic);
8174 sym_link *ctype = operandType(IC_LEFT(ic));
8175 sym_link *rtype = operandType(IC_RIGHT(ic));
8176 operand *right = IC_RIGHT(ic);
8179 D(emitcode(";", "genCast "););
8181 /* if they are equivalent then do nothing */
8182 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8185 aopOp(right,ic,FALSE, FALSE) ;
8186 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
8188 /* if the result is a bit */
8189 if (AOP_TYPE(result) == AOP_CRY) {
8190 /* if the right size is a literal then
8191 we know what the value is */
8192 if (AOP_TYPE(right) == AOP_LIT) {
8193 if (((int) operandLitValue(right)))
8194 aopPut(AOP(result),one,0);
8196 aopPut(AOP(result),zero,0);
8201 /* the right is also a bit variable */
8202 if (AOP_TYPE(right) == AOP_CRY) {
8203 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8204 aopPut(AOP(result),"c",0);
8210 aopPut(AOP(result),"a",0);
8214 /* if they are the same size : or less */
8215 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8217 /* if they are in the same place */
8218 if (sameRegs(AOP(right),AOP(result)))
8221 /* if they in different places then copy */
8222 size = AOP_SIZE(result);
8224 _startLazyDPSEvaluation();
8227 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8231 _endLazyDPSEvaluation();
8236 /* if the result is of type pointer */
8237 if (IS_PTR(ctype)) {
8240 sym_link *type = operandType(right);
8242 /* pointer to generic pointer */
8243 if (IS_GENPTR(ctype)) {
8248 p_type = DCL_TYPE(type);
8252 #if OLD_CAST_BEHAVIOR
8253 /* KV: we are converting a non-pointer type to
8254 * a generic pointer. This (ifdef'd out) code
8255 * says that the resulting generic pointer
8256 * should have the same class as the storage
8257 * location of the non-pointer variable.
8259 * For example, converting an int (which happens
8260 * to be stored in DATA space) to a pointer results
8261 * in a DATA generic pointer; if the original int
8262 * in XDATA space, so will be the resulting pointer.
8264 * I don't like that behavior, and thus this change:
8265 * all such conversions will be forced to XDATA and
8266 * throw a warning. If you want some non-XDATA
8267 * type, or you want to suppress the warning, you
8268 * must go through an intermediate cast, like so:
8270 * char _generic *gp = (char _xdata *)(intVar);
8272 sym_link *etype = getSpec(type);
8274 /* we have to go by the storage class */
8275 if (SPEC_OCLS(etype) != generic)
8277 p_type = PTR_TYPE(SPEC_OCLS(etype));
8282 /* Converting unknown class (i.e. register variable)
8283 * to generic pointer. This is not good, but
8284 * we'll make a guess (and throw a warning).
8287 werror(W_INT_TO_GEN_PTR_CAST);
8291 /* the first two bytes are known */
8292 size = GPTRSIZE - 1;
8294 _startLazyDPSEvaluation();
8297 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8301 _endLazyDPSEvaluation();
8303 /* the last byte depending on type */
8320 /* this should never happen */
8321 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8322 "got unknown pointer type");
8325 aopPut(AOP(result),l, GPTRSIZE - 1);
8329 /* just copy the pointers */
8330 size = AOP_SIZE(result);
8332 _startLazyDPSEvaluation();
8335 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8339 _endLazyDPSEvaluation();
8343 /* so we now know that the size of destination is greater
8344 than the size of the source */
8345 /* we move to result for the size of source */
8346 size = AOP_SIZE(right);
8348 _startLazyDPSEvaluation();
8351 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8355 _endLazyDPSEvaluation();
8357 /* now depending on the sign of the source && destination */
8358 size = AOP_SIZE(result) - AOP_SIZE(right);
8359 /* if unsigned or not an integral type */
8360 /* also, if the source is a bit, we don't need to sign extend, because
8361 * it can't possibly have set the sign bit.
8363 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype) || AOP_TYPE(right) == AOP_CRY)
8367 aopPut(AOP(result),zero,offset++);
8372 /* we need to extend the sign :{ */
8373 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8376 emitcode("rlc","a");
8377 emitcode("subb","a,acc");
8379 aopPut(AOP(result),"a",offset++);
8382 /* we are done hurray !!!! */
8385 freeAsmop(right,NULL,ic,TRUE);
8386 freeAsmop(result,NULL,ic,TRUE);
8390 /*-----------------------------------------------------------------*/
8391 /* genDjnz - generate decrement & jump if not zero instrucion */
8392 /*-----------------------------------------------------------------*/
8393 static int genDjnz (iCode *ic, iCode *ifx)
8399 /* if the if condition has a false label
8400 then we cannot save */
8404 /* if the minus is not of the form
8406 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8407 !IS_OP_LITERAL(IC_RIGHT(ic)))
8410 if (operandLitValue(IC_RIGHT(ic)) != 1)
8413 /* if the size of this greater than one then no
8415 if (getSize(operandType(IC_RESULT(ic))) > 1)
8418 /* otherwise we can save BIG */
8419 lbl = newiTempLabel(NULL);
8420 lbl1= newiTempLabel(NULL);
8422 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8424 if (IS_AOP_PREG(IC_RESULT(ic))) {
8425 emitcode("dec","%s",
8426 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8427 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8428 emitcode("jnz","%05d$",lbl->key+100);
8430 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8433 emitcode ("sjmp","%05d$",lbl1->key+100);
8434 emitcode ("","%05d$:",lbl->key+100);
8435 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8436 emitcode ("","%05d$:",lbl1->key+100);
8438 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8443 /*-----------------------------------------------------------------*/
8444 /* genReceive - generate code for a receive iCode */
8445 /*-----------------------------------------------------------------*/
8446 static void genReceive (iCode *ic)
8449 D(emitcode(";", "genReceive "););
8451 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8452 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8453 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8454 int size = getSize(operandType(IC_RESULT(ic)));
8455 int offset = fReturnSize_390 - size;
8457 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8458 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8461 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8462 size = AOP_SIZE(IC_RESULT(ic));
8465 emitcode ("pop","acc");
8466 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8471 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8473 assignResultValue(IC_RESULT(ic));
8476 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8479 /*-----------------------------------------------------------------*/
8480 /* gen390Code - generate code for Dallas 390 based controllers */
8481 /*-----------------------------------------------------------------*/
8482 void gen390Code (iCode *lic)
8487 lineHead = lineCurr = NULL;
8491 /* print the allocation information */
8493 printAllocInfo( currFunc, codeOutFile);
8495 /* if debug information required */
8496 if (options.debug && currFunc) {
8497 //jwk if (currFunc) {
8498 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8500 if (IS_STATIC(currFunc->etype))
8501 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8503 emitcode("","G$%s$0$0 ==.",currFunc->name);
8506 /* stack pointer name */
8507 if (options.useXstack)
8513 for (ic = lic ; ic ; ic = ic->next ) {
8515 if ( cln != ic->lineno ) {
8516 if ( options.debug ) {
8518 emitcode("","C$%s$%d$%d$%d ==.",
8519 ic->filename,ic->lineno,
8520 ic->level,ic->block);
8523 emitcode(";","%s %d",ic->filename,ic->lineno);
8526 /* if the result is marked as
8527 spilt and rematerializable or code for
8528 this has already been generated then
8530 if (resultRemat(ic) || ic->generated )
8533 /* depending on the operation */
8552 /* IPOP happens only when trying to restore a
8553 spilt live range, if there is an ifx statement
8554 following this pop then the if statement might
8555 be using some of the registers being popped which
8556 would destory the contents of the register so
8557 we need to check for this condition and handle it */
8559 ic->next->op == IFX &&
8560 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8561 genIfx (ic->next,ic);
8579 genEndFunction (ic);
8599 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8616 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8620 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8627 /* note these two are xlated by algebraic equivalence
8628 during parsing SDCC.y */
8629 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8630 "got '>=' or '<=' shouldn't have come here");
8634 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8646 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8650 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8654 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8681 case GET_VALUE_AT_ADDRESS:
8686 if (POINTER_SET(ic))
8713 addSet(&_G.sendSet,ic);
8718 /* piCode(ic,stdout); */
8724 /* now we are ready to call the
8725 peep hole optimizer */
8726 if (!options.nopeep)
8727 peepHole (&lineHead);
8729 /* now do the actual printing */
8730 printLine (lineHead,codeOutFile);