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 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
42 #ifdef HAVE_SYS_ISA_DEFS_H
43 #include <sys/isa_defs.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
55 char *aopLiteral (value *val, int offset);
61 /* this is the down and dirty file with all kinds of
62 kludgy & hacky stuff. This is what it is all about
63 CODE GENERATION for a specific MCU . some of the
64 routines may be reusable, will have to see */
66 static char *zero = "#0x00";
67 static char *one = "#0x01";
72 unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
73 static char *fReturn[] = {"dpl","dph","dpx", "b","a" };
74 static char *accUse[] = {"a","b"};
76 static short rbank = -1;
88 static void saverbank (int, iCode *,bool);
90 #define RESULTONSTACK(x) \
91 (IC_RESULT(x) && IC_RESULT(x)->aop && \
92 IC_RESULT(x)->aop->type == AOP_STK )
94 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
95 #define MOVA(x) { char *_mova_tmp = strdup(x); \
96 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
98 emitcode("mov","a,%s",_mova_tmp); \
102 #define CLRC emitcode("clr","c")
103 #define SETC emitcode("setb","c")
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
108 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
109 0xE0, 0xC0, 0x80, 0x00};
110 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
111 0x07, 0x03, 0x01, 0x00};
118 /*-----------------------------------------------------------------*/
119 /* emitcode - writes the code into a file : for now it is simple */
120 /*-----------------------------------------------------------------*/
121 static void emitcode (char *inst,char *fmt, ...)
124 char lb[MAX_INLINEASM];
131 sprintf(lb,"%s\t",inst);
133 sprintf(lb,"%s",inst);
134 vsprintf(lb+(strlen(lb)),fmt,ap);
138 while (isspace(*lbp)) lbp++;
141 lineCurr = (lineCurr ?
142 connectLine(lineCurr,newLineNode(lb)) :
143 (lineHead = newLineNode(lb)));
144 lineCurr->isInline = _G.inLine;
145 lineCurr->isDebug = _G.debugLine;
149 /*-----------------------------------------------------------------*/
150 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
151 /*-----------------------------------------------------------------*/
152 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
154 bool r0iu = FALSE , r1iu = FALSE;
155 bool r0ou = FALSE , r1ou = FALSE;
157 /* the logic: if r0 & r1 used in the instruction
158 then we are in trouble otherwise */
160 /* first check if r0 & r1 are used by this
161 instruction, in which case we are in trouble */
162 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
163 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
168 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
169 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
171 /* if no usage of r0 then return it */
172 if (!r0iu && !r0ou) {
173 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
174 (*aopp)->type = AOP_R0;
176 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
179 /* if no usage of r1 then return it */
180 if (!r1iu && !r1ou) {
181 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
182 (*aopp)->type = AOP_R1;
184 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R1_IDX);
187 /* now we know they both have usage */
188 /* if r0 not used in this instruction */
190 /* push it if not already pushed */
192 emitcode ("push","%s",
193 ds390_regWithIdx(R0_IDX)->dname);
197 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
198 (*aopp)->type = AOP_R0;
200 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
203 /* if r1 not used then */
206 /* push it if not already pushed */
208 emitcode ("push","%s",
209 ds390_regWithIdx(R1_IDX)->dname);
213 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
214 (*aopp)->type = AOP_R1;
215 return ds390_regWithIdx(R1_IDX);
219 /* I said end of world but not quite end of world yet */
220 /* if this is a result then we can push it on the stack*/
222 (*aopp)->type = AOP_STK;
227 /* other wise this is true end of the world */
228 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
229 "getFreePtr should never reach here");
233 /*-----------------------------------------------------------------*/
234 /* newAsmop - creates a new asmOp */
235 /*-----------------------------------------------------------------*/
236 static asmop *newAsmop (short type)
240 aop = Safe_calloc(1,sizeof(asmop));
245 /* Turn this off if the world goes to hell. */
248 static int _currentDPS; /* Current processor DPS. */
249 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
250 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
252 /*-----------------------------------------------------------------*/
253 /* genSetDPTR: generate code to select which DPTR is in use (zero */
254 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
255 /* alternate DPTR (DPL1/DPH1/DPX1). */
256 /*-----------------------------------------------------------------*/
257 static void genSetDPTR(int n)
261 /* If we are doing lazy evaluation, simply note the desired
262 * change, but don't emit any code yet.
273 emitcode("mov", "dps, #0x00");
277 emitcode("mov", "dps, #0x01");
281 /*-----------------------------------------------------------------*/
282 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation*/
284 /* Any code that operates on DPTR (NB: not on the individual */
285 /* components, like DPH) *must* call _flushLazyDPS() before using */
286 /* DPTR within a lazy DPS evaluation block. */
288 /* Note that aopPut and aopGet already contain the proper calls to */
289 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
290 /* DPS evaluation block. */
292 /* Also, _flushLazyDPS must be called before any flow control */
293 /* operations that could potentially branch out of the block. */
295 /* Lazy DPS evaluation is simply an optimization (though an */
296 /* important one), so if in doubt, leave it out. */
297 /*-----------------------------------------------------------------*/
298 static void _startLazyDPSEvaluation(void)
305 /*-----------------------------------------------------------------*/
306 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
307 /* desired one. Call before using DPTR within a lazy DPS evaluation*/
309 /*-----------------------------------------------------------------*/
310 static void _flushLazyDPS(void)
318 if (_desiredDPS != _currentDPS)
322 emitcode("inc", "dps");
326 emitcode("dec", "dps");
328 _currentDPS = _desiredDPS;
332 /*-----------------------------------------------------------------*/
333 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
335 /* Forces us back to the safe state (standard DPTR selected). */
336 /*-----------------------------------------------------------------*/
337 static void _endLazyDPSEvaluation(void)
351 /*-----------------------------------------------------------------*/
352 /* pointerCode - returns the code for a pointer type */
353 /*-----------------------------------------------------------------*/
354 static int pointerCode (sym_link *etype)
357 return PTR_TYPE(SPEC_OCLS(etype));
361 /*-----------------------------------------------------------------*/
362 /* aopForSym - for a true symbol */
363 /*-----------------------------------------------------------------*/
364 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
367 memmap *space= SPEC_OCLS(sym->etype);
369 /* if already has one */
373 /* assign depending on the storage class */
374 /* if it is on the stack or indirectly addressable */
375 /* space we need to assign either r0 or r1 to it */
376 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
377 sym->aop = aop = newAsmop(0);
378 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
379 aop->size = getSize(sym->type);
381 /* now assign the address of the variable to
382 the pointer register */
383 if (aop->type != AOP_STK) {
387 emitcode("push","acc");
389 emitcode("mov","a,_bp");
390 emitcode("add","a,#0x%02x",
392 ((char)(sym->stack - _G.nRegsSaved )) :
393 ((char)sym->stack)) & 0xff);
394 emitcode("mov","%s,a",
395 aop->aopu.aop_ptr->name);
398 emitcode("pop","acc");
400 emitcode("mov","%s,#%s",
401 aop->aopu.aop_ptr->name,
403 aop->paged = space->paged;
405 aop->aopu.aop_stk = sym->stack;
409 if (sym->onStack && options.stack10bit)
411 /* It's on the 10 bit stack, which is located in
416 emitcode("push","acc");
418 emitcode("mov","a,_bp");
419 emitcode("add","a,#0x%02x",
421 ((char)(sym->stack - _G.nRegsSaved )) :
422 ((char)sym->stack)) & 0xff);
427 emitcode ("mov","dpx1,#0x40");
428 emitcode ("mov","dph1,#0x00");
429 emitcode ("mov","dpl1, a");
434 emitcode ("mov","dpx,#0x40");
435 emitcode ("mov","dph,#0x00");
436 emitcode ("mov","dpl, a");
440 emitcode("pop","acc");
442 sym->aop = aop = newAsmop((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
443 aop->size = getSize(sym->type);
447 /* if in bit space */
448 if (IN_BITSPACE(space)) {
449 sym->aop = aop = newAsmop (AOP_CRY);
450 aop->aopu.aop_dir = sym->rname ;
451 aop->size = getSize(sym->type);
454 /* if it is in direct space */
455 if (IN_DIRSPACE(space)) {
456 sym->aop = aop = newAsmop (AOP_DIR);
457 aop->aopu.aop_dir = sym->rname ;
458 aop->size = getSize(sym->type);
462 /* special case for a function */
463 if (IS_FUNC(sym->type)) {
464 sym->aop = aop = newAsmop(AOP_IMMD);
465 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
466 strcpy(aop->aopu.aop_immd,sym->rname);
467 aop->size = FPTRSIZE;
471 /* only remaining is far space */
472 /* in which case DPTR gets the address */
473 sym->aop = aop = newAsmop((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
478 emitcode ("mov","dptr,#%s", sym->rname);
483 emitcode ("mov","dptr,#%s", sym->rname);
485 aop->size = getSize(sym->type);
487 /* if it is in code space */
488 if (IN_CODESPACE(space))
494 /*-----------------------------------------------------------------*/
495 /* aopForRemat - rematerialzes an object */
496 /*-----------------------------------------------------------------*/
497 static asmop *aopForRemat (symbol *sym)
499 iCode *ic = sym->rematiCode;
500 asmop *aop = newAsmop(AOP_IMMD);
506 val += (int) operandLitValue(IC_RIGHT(ic));
507 else if (ic->op == '-')
508 val -= (int) operandLitValue(IC_RIGHT(ic));
512 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
516 sprintf(buffer,"(%s %c 0x%04x)",
517 OP_SYMBOL(IC_LEFT(ic))->rname,
518 val >= 0 ? '+' : '-',
521 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
523 aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
524 strcpy(aop->aopu.aop_immd,buffer);
528 /*-----------------------------------------------------------------*/
529 /* regsInCommon - two operands have some registers in common */
530 /*-----------------------------------------------------------------*/
531 static bool regsInCommon (operand *op1, operand *op2)
536 /* if they have registers in common */
537 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
540 sym1 = OP_SYMBOL(op1);
541 sym2 = OP_SYMBOL(op2);
543 if (sym1->nRegs == 0 || sym2->nRegs == 0)
546 for (i = 0 ; i < sym1->nRegs ; i++) {
551 for (j = 0 ; j < sym2->nRegs ;j++ ) {
555 if (sym2->regs[j] == sym1->regs[i])
563 /*-----------------------------------------------------------------*/
564 /* operandsEqu - equivalent */
565 /*-----------------------------------------------------------------*/
566 static bool operandsEqu ( operand *op1, operand *op2)
570 /* if they not symbols */
571 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
574 sym1 = OP_SYMBOL(op1);
575 sym2 = OP_SYMBOL(op2);
577 /* if both are itemps & one is spilt
578 and the other is not then false */
579 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
580 sym1->isspilt != sym2->isspilt )
583 /* if they are the same */
587 if (strcmp(sym1->rname,sym2->rname) == 0)
591 /* if left is a tmp & right is not */
595 (sym1->usl.spillLoc == sym2))
602 (sym2->usl.spillLoc == sym1))
608 /*-----------------------------------------------------------------*/
609 /* sameRegs - two asmops have the same registers */
610 /*-----------------------------------------------------------------*/
611 static bool sameRegs (asmop *aop1, asmop *aop2 )
617 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
624 if (aop1->type != AOP_REG ||
625 aop2->type != AOP_REG )
628 if (aop1->size != aop2->size )
631 for (i = 0 ; i < aop1->size ; i++ )
632 if (aop1->aopu.aop_reg[i] !=
633 aop2->aopu.aop_reg[i] )
639 /*-----------------------------------------------------------------*/
640 /* aopOp - allocates an asmop for an operand : */
641 /*-----------------------------------------------------------------*/
642 static void aopOp (operand *op, iCode *ic, bool result, bool useDP2)
651 /* if this a literal */
652 if (IS_OP_LITERAL(op)) {
653 op->aop = aop = newAsmop(AOP_LIT);
654 aop->aopu.aop_lit = op->operand.valOperand;
655 aop->size = getSize(operandType(op));
659 /* if already has a asmop then continue */
663 /* if the underlying symbol has a aop */
664 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
665 op->aop = OP_SYMBOL(op)->aop;
669 /* if this is a true symbol */
670 if (IS_TRUE_SYMOP(op)) {
671 op->aop = aopForSym(ic,OP_SYMBOL(op),result, useDP2);
675 /* this is a temporary : this has
681 e) can be a return use only */
686 /* if the type is a conditional */
687 if (sym->regType == REG_CND) {
688 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
693 /* if it is spilt then two situations
695 b) has a spill location */
696 if (sym->isspilt || sym->nRegs == 0) {
698 /* rematerialize it NOW */
700 sym->aop = op->aop = aop =
702 aop->size = getSize(sym->type);
708 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
709 aop->size = getSize(sym->type);
710 for ( i = 0 ; i < 2 ; i++ )
711 aop->aopu.aop_str[i] = accUse[i];
720 /* a AOP_STR uses DPTR, but DPTR is already in use;
723 fprintf(stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
726 aop = op->aop = sym->aop = newAsmop(AOP_STR);
727 aop->size = getSize(sym->type);
728 for ( i = 0 ; i < (int) fReturnSize_390 ; i++ )
729 aop->aopu.aop_str[i] = fReturn[i];
733 /* else spill location */
734 sym->aop = op->aop = aop =
735 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
736 aop->size = getSize(sym->type);
740 /* must be in a register */
741 sym->aop = op->aop = aop = newAsmop(AOP_REG);
742 aop->size = sym->nRegs;
743 for ( i = 0 ; i < sym->nRegs ;i++)
744 aop->aopu.aop_reg[i] = sym->regs[i];
747 /*-----------------------------------------------------------------*/
748 /* freeAsmop - free up the asmop given to an operand */
749 /*----------------------------------------------------------------*/
750 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
767 /* depending on the asmop type only three cases need work AOP_RO
768 , AOP_R1 && AOP_STK */
773 emitcode ("pop","ar0");
777 bitVectUnSetBit(ic->rUsed,R0_IDX);
783 emitcode ("pop","ar1");
787 bitVectUnSetBit(ic->rUsed,R1_IDX);
793 int stk = aop->aopu.aop_stk + aop->size;
794 bitVectUnSetBit(ic->rUsed,R0_IDX);
795 bitVectUnSetBit(ic->rUsed,R1_IDX);
797 getFreePtr(ic,&aop,FALSE);
799 if (options.stack10bit)
801 /* I'm not sure what to do here yet... */
804 "*** Warning: probably generating bad code for "
805 "10 bit stack mode.\n");
809 emitcode ("mov","a,_bp");
810 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
811 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
813 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
817 emitcode("pop","acc");
818 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
820 emitcode("dec","%s",aop->aopu.aop_ptr->name);
823 freeAsmop(op,NULL,ic,TRUE);
825 emitcode("pop","ar0");
830 emitcode("pop","ar1");
837 /* all other cases just dealloc */
841 OP_SYMBOL(op)->aop = NULL;
842 /* if the symbol has a spill */
844 SPIL_LOC(op)->aop = NULL;
849 /*------------------------------------------------------------------*/
850 /* aopGet - for fetching value of the aop */
852 /* Set canClobberACC if you are aure it is OK to clobber the value */
853 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe,*/
854 /* just less efficient. */
855 /*------------------------------------------------------------------*/
857 static char *aopGet (asmop *aop,
866 /* offset is greater than
868 if (offset > (aop->size - 1) &&
869 aop->type != AOP_LIT)
872 /* depending on type */
877 /* if we need to increment it */
878 while (offset > aop->coff) {
879 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
883 while (offset < aop->coff) {
884 emitcode("dec","%s",aop->aopu.aop_ptr->name);
890 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
891 return (dname ? "acc" : "a");
893 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
894 rs = Safe_calloc(1,strlen(s)+1);
901 if (aop->type == AOP_DPTR2)
905 #ifndef KEVIN_BROKE_IT
909 emitcode("xch", "a, ap");
915 while (offset > aop->coff) {
916 emitcode ("inc","dptr");
920 while (offset < aop->coff) {
921 emitcode("lcall","__decdptr");
928 emitcode("movc","a,@a+dptr");
931 emitcode("movx","a,@dptr");
934 if (aop->type == AOP_DPTR2)
938 #ifndef KEVIN_BROKE_IT
942 emitcode("xch", "a, ap");
947 return (dname ? "acc" : "a");
951 sprintf (s,"#%s",aop->aopu.aop_immd);
954 sprintf(s,"#(%s >> %d)",
960 rs = Safe_calloc(1,strlen(s)+1);
966 sprintf(s,"(%s + %d)",
970 sprintf(s,"%s",aop->aopu.aop_dir);
971 rs = Safe_calloc(1,strlen(s)+1);
977 return aop->aopu.aop_reg[offset]->dname;
979 return aop->aopu.aop_reg[offset]->name;
983 emitcode("mov","c,%s",aop->aopu.aop_dir);
984 emitcode("rlc","a") ;
985 return (dname ? "acc" : "a");
988 if (!offset && dname)
990 return aop->aopu.aop_str[offset];
993 return aopLiteral (aop->aopu.aop_lit,offset);
997 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1001 return aop->aopu.aop_str[offset];
1005 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1006 "aopget got unsupported aop->type");
1009 /*-----------------------------------------------------------------*/
1010 /* aopPut - puts a string for a aop */
1011 /*-----------------------------------------------------------------*/
1012 static void aopPut (asmop *aop, char *s, int offset)
1017 if (aop->size && offset > ( aop->size - 1)) {
1018 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1019 "aopPut got offset > aop->size");
1023 /* will assign value to value */
1024 /* depending on where it is ofcourse */
1025 switch (aop->type) {
1028 sprintf(d,"(%s + %d)",
1029 aop->aopu.aop_dir,offset);
1031 sprintf(d,"%s",aop->aopu.aop_dir);
1034 emitcode("mov","%s,%s",d,s);
1039 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1040 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1042 strcmp(s,"r0") == 0 ||
1043 strcmp(s,"r1") == 0 ||
1044 strcmp(s,"r2") == 0 ||
1045 strcmp(s,"r3") == 0 ||
1046 strcmp(s,"r4") == 0 ||
1047 strcmp(s,"r5") == 0 ||
1048 strcmp(s,"r6") == 0 ||
1049 strcmp(s,"r7") == 0 )
1050 emitcode("mov","%s,%s",
1051 aop->aopu.aop_reg[offset]->dname,s);
1053 emitcode("mov","%s,%s",
1054 aop->aopu.aop_reg[offset]->name,s);
1061 if (aop->type == AOP_DPTR2)
1068 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1069 "aopPut writting to code space");
1073 while (offset > aop->coff) {
1075 emitcode ("inc","dptr");
1078 while (offset < aop->coff) {
1080 emitcode("lcall","__decdptr");
1085 /* if not in accumulater */
1088 emitcode ("movx","@dptr,a");
1090 if (aop->type == AOP_DPTR2)
1098 while (offset > aop->coff) {
1100 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1102 while (offset < aop->coff) {
1104 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1110 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1115 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1117 if (strcmp(s,"r0") == 0 ||
1118 strcmp(s,"r1") == 0 ||
1119 strcmp(s,"r2") == 0 ||
1120 strcmp(s,"r3") == 0 ||
1121 strcmp(s,"r4") == 0 ||
1122 strcmp(s,"r5") == 0 ||
1123 strcmp(s,"r6") == 0 ||
1124 strcmp(s,"r7") == 0 ) {
1126 sprintf(buffer,"a%s",s);
1127 emitcode("mov","@%s,%s",
1128 aop->aopu.aop_ptr->name,buffer);
1130 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1135 if (strcmp(s,"a") == 0)
1136 emitcode("push","acc");
1138 emitcode("push","%s",s);
1143 /* if bit variable */
1144 if (!aop->aopu.aop_dir) {
1145 emitcode("clr","a");
1146 emitcode("rlc","a");
1149 emitcode("clr","%s",aop->aopu.aop_dir);
1152 emitcode("setb","%s",aop->aopu.aop_dir);
1155 emitcode("mov","%s,c",aop->aopu.aop_dir);
1157 lbl = newiTempLabel(NULL);
1159 if (strcmp(s,"a")) {
1162 emitcode("clr","c");
1163 emitcode("jz","%05d$",lbl->key+100);
1164 emitcode("cpl","c");
1165 emitcode("","%05d$:",lbl->key+100);
1166 emitcode("mov","%s,c",aop->aopu.aop_dir);
1173 if (strcmp(aop->aopu.aop_str[offset],s))
1174 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1179 if (!offset && (strcmp(s,"acc") == 0))
1182 if (strcmp(aop->aopu.aop_str[offset],s))
1183 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1187 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1188 "aopPut got unsupported aop->type");
1195 /*-----------------------------------------------------------------*/
1196 /* reAdjustPreg - points a register back to where it should */
1197 /*-----------------------------------------------------------------*/
1198 static void reAdjustPreg (asmop *aop)
1203 if ((size = aop->size) <= 1)
1206 switch (aop->type) {
1210 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1214 if (aop->type == AOP_DPTR2)
1221 emitcode("lcall","__decdptr");
1224 if (aop->type == AOP_DPTR2)
1234 #define AOP(op) op->aop
1235 #define AOP_TYPE(op) AOP(op)->type
1236 #define AOP_SIZE(op) AOP(op)->size
1237 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1238 AOP_TYPE(x) == AOP_R0))
1240 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1241 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1244 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1245 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1246 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1248 /* Workaround for DS80C390 bug: div ab may return bogus results
1249 * if A is accessed in instruction immediately before the div.
1251 * Will be fixed in B4 rev of processor, Dallas claims.
1254 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1255 if (!AOP_NEEDSACC(RIGHT)) \
1257 /* We can load A first, then B, since \
1258 * B (the RIGHT operand) won't clobber A, \
1259 * thus avoiding touching A right before the div. \
1261 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1262 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1264 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1268 /* Just stuff in a nop after loading A. */ \
1269 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1270 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1272 emitcode("nop", "; workaround for DS80C390 div bug."); \
1275 /*-----------------------------------------------------------------*/
1276 /* genNotFloat - generates not for float operations */
1277 /*-----------------------------------------------------------------*/
1278 static void genNotFloat (operand *op, operand *res)
1284 D(emitcode(";", "genNotFloat "););
1286 /* we will put 127 in the first byte of
1288 aopPut(AOP(res),"#127",0);
1289 size = AOP_SIZE(op) - 1;
1292 _startLazyDPSEvaluation();
1293 l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
1297 emitcode("orl","a,%s",
1299 offset++,FALSE,FALSE,FALSE));
1301 _endLazyDPSEvaluation();
1302 tlbl = newiTempLabel(NULL);
1304 tlbl = newiTempLabel(NULL);
1305 aopPut(res->aop,one,1);
1306 emitcode("jz","%05d$",(tlbl->key+100));
1307 aopPut(res->aop,zero,1);
1308 emitcode("","%05d$:",(tlbl->key+100));
1310 size = res->aop->size - 2;
1312 /* put zeros in the rest */
1314 aopPut(res->aop,zero,offset++);
1317 /*-----------------------------------------------------------------*/
1318 /* opIsGptr: returns non-zero if the passed operand is */
1319 /* a generic pointer type. */
1320 /*-----------------------------------------------------------------*/
1321 static int opIsGptr(operand *op)
1323 sym_link *type = operandType(op);
1325 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1332 /*-----------------------------------------------------------------*/
1333 /* getDataSize - get the operand data size */
1334 /*-----------------------------------------------------------------*/
1335 static int getDataSize(operand *op)
1338 size = AOP_SIZE(op);
1339 if (size == GPTRSIZE)
1341 sym_link *type = operandType(op);
1342 if (IS_GENPTR(type))
1344 /* generic pointer; arithmetic operations
1345 * should ignore the high byte (pointer type).
1353 /*-----------------------------------------------------------------*/
1354 /* outAcc - output Acc */
1355 /*-----------------------------------------------------------------*/
1356 static void outAcc(operand *result)
1359 size = getDataSize(result);
1362 aopPut(AOP(result),"a",0);
1365 /* unsigned or positive */
1367 aopPut(AOP(result),zero,offset++);
1372 /*-----------------------------------------------------------------*/
1373 /* outBitC - output a bit C */
1374 /*-----------------------------------------------------------------*/
1375 static void outBitC(operand *result)
1377 /* if the result is bit */
1378 if (AOP_TYPE(result) == AOP_CRY)
1380 aopPut(AOP(result),"c",0);
1384 emitcode("clr","a");
1385 emitcode("rlc","a");
1390 /*-----------------------------------------------------------------*/
1391 /* toBoolean - emit code for orl a,operator(sizeop) */
1392 /*-----------------------------------------------------------------*/
1393 static void toBoolean(operand *oper)
1395 int size = AOP_SIZE(oper) - 1;
1398 /* The generic part of a generic pointer should
1399 * not participate in it's truth value.
1401 * i.e. 0x10000000 is zero.
1405 D(emitcode(";", "toBoolean: generic ptr special case."););
1409 _startLazyDPSEvaluation();
1410 if (AOP_NEEDSACC(oper))
1412 emitcode("push", "b");
1413 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1417 MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1421 if (AOP_NEEDSACC(oper))
1423 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1427 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1430 _endLazyDPSEvaluation();
1432 if (AOP_NEEDSACC(oper))
1434 emitcode("mov", "a,b");
1435 emitcode("pop", "b");
1440 /*-----------------------------------------------------------------*/
1441 /* genNot - generate code for ! operation */
1442 /*-----------------------------------------------------------------*/
1443 static void genNot (iCode *ic)
1446 sym_link *optype = operandType(IC_LEFT(ic));
1448 D(emitcode(";", "genNot "););
1450 /* assign asmOps to operand & result */
1451 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1452 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1454 /* if in bit space then a special case */
1455 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1456 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1457 emitcode("cpl","c");
1458 outBitC(IC_RESULT(ic));
1462 /* if type float then do float */
1463 if (IS_FLOAT(optype)) {
1464 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1468 toBoolean(IC_LEFT(ic));
1470 tlbl = newiTempLabel(NULL);
1471 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1472 emitcode("","%05d$:",tlbl->key+100);
1473 outBitC(IC_RESULT(ic));
1476 /* release the aops */
1477 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1478 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1482 /*-----------------------------------------------------------------*/
1483 /* genCpl - generate code for complement */
1484 /*-----------------------------------------------------------------*/
1485 static void genCpl (iCode *ic)
1490 D(emitcode(";", "genCpl "););
1493 /* assign asmOps to operand & result */
1494 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1495 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1497 /* if both are in bit space then
1499 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1500 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1502 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1503 emitcode("cpl","c");
1504 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1508 size = AOP_SIZE(IC_RESULT(ic));
1509 _startLazyDPSEvaluation();
1511 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1513 emitcode("cpl","a");
1514 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1516 _endLazyDPSEvaluation();
1520 /* release the aops */
1521 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1522 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1525 /*-----------------------------------------------------------------*/
1526 /* genUminusFloat - unary minus for floating points */
1527 /*-----------------------------------------------------------------*/
1528 static void genUminusFloat(operand *op,operand *result)
1530 int size ,offset =0 ;
1532 /* for this we just need to flip the
1533 first it then copy the rest in place */
1534 D(emitcode(";", "genUminusFloat"););
1536 _startLazyDPSEvaluation();
1537 size = AOP_SIZE(op) - 1;
1538 l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1541 emitcode("cpl","acc.7");
1542 aopPut(AOP(result),"a",3);
1546 aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1550 _endLazyDPSEvaluation();
1553 /*-----------------------------------------------------------------*/
1554 /* genUminus - unary minus code generation */
1555 /*-----------------------------------------------------------------*/
1556 static void genUminus (iCode *ic)
1559 sym_link *optype, *rtype;
1561 D(emitcode(";", "genUminus "););
1565 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1566 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1568 /* if both in bit space then special
1570 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1571 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1573 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1574 emitcode("cpl","c");
1575 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1579 optype = operandType(IC_LEFT(ic));
1580 rtype = operandType(IC_RESULT(ic));
1582 /* if float then do float stuff */
1583 if (IS_FLOAT(optype)) {
1584 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1588 /* otherwise subtract from zero */
1589 size = AOP_SIZE(IC_LEFT(ic));
1591 _startLazyDPSEvaluation();
1593 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1594 if (!strcmp(l,"a")) {
1597 emitcode("cpl","a");
1598 emitcode("addc", "a,#0");
1602 emitcode("clr","a");
1603 emitcode("subb","a,%s",l);
1605 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1607 _endLazyDPSEvaluation();
1609 /* if any remaining bytes in the result */
1610 /* we just need to propagate the sign */
1611 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1612 emitcode("rlc","a");
1613 emitcode("subb","a,acc");
1615 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1619 /* release the aops */
1620 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1621 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1624 /*-----------------------------------------------------------------*/
1625 /* saveRegisters - will look for a call and save the registers */
1626 /*-----------------------------------------------------------------*/
1627 static void saveRegisters(iCode *lic)
1635 for (ic = lic ; ic ; ic = ic->next)
1636 if (ic->op == CALL || ic->op == PCALL)
1640 fprintf(stderr,"found parameter push with no function call\n");
1644 /* if the registers have been saved already then
1646 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1649 /* find the registers in use at this time
1650 and push them away to safety */
1651 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1655 if (options.useXstack) {
1656 if (bitVectBitValue(rsave,R0_IDX))
1657 emitcode("mov","b,r0");
1658 emitcode("mov","r0,%s",spname);
1659 for (i = 0 ; i < ds390_nRegs ; i++) {
1660 if (bitVectBitValue(rsave,i)) {
1662 emitcode("mov","a,b");
1664 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1665 emitcode("movx","@r0,a");
1666 emitcode("inc","r0");
1669 emitcode("mov","%s,r0",spname);
1670 if (bitVectBitValue(rsave,R0_IDX))
1671 emitcode("mov","r0,b");
1673 for (i = 0 ; i < ds390_nRegs ; i++) {
1674 if (bitVectBitValue(rsave,i))
1675 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1678 detype = getSpec(operandType(IC_LEFT(ic)));
1680 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1681 IS_ISR(currFunc->etype) &&
1684 saverbank(SPEC_BANK(detype),ic,TRUE);
1687 /*-----------------------------------------------------------------*/
1688 /* unsaveRegisters - pop the pushed registers */
1689 /*-----------------------------------------------------------------*/
1690 static void unsaveRegisters (iCode *ic)
1694 /* find the registers in use at this time
1695 and push them away to safety */
1696 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1699 if (options.useXstack) {
1700 emitcode("mov","r0,%s",spname);
1701 for (i = ds390_nRegs ; i >= 0 ; i--) {
1702 if (bitVectBitValue(rsave,i)) {
1703 emitcode("dec","r0");
1704 emitcode("movx","a,@r0");
1706 emitcode("mov","b,a");
1708 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1712 emitcode("mov","%s,r0",spname);
1713 if (bitVectBitValue(rsave,R0_IDX))
1714 emitcode("mov","r0,b");
1716 for (i = ds390_nRegs ; i >= 0 ; i--) {
1717 if (bitVectBitValue(rsave,i))
1718 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1724 /*-----------------------------------------------------------------*/
1726 /*-----------------------------------------------------------------*/
1727 static void pushSide(operand * oper, int size)
1730 _startLazyDPSEvaluation();
1732 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1733 if (AOP_TYPE(oper) != AOP_REG &&
1734 AOP_TYPE(oper) != AOP_DIR &&
1736 emitcode("mov","a,%s",l);
1737 emitcode("push","acc");
1739 emitcode("push","%s",l);
1741 _endLazyDPSEvaluation();
1744 /*-----------------------------------------------------------------*/
1745 /* assignResultValue - */
1746 /*-----------------------------------------------------------------*/
1747 static void assignResultValue(operand * oper)
1750 int size = AOP_SIZE(oper);
1752 _startLazyDPSEvaluation();
1754 aopPut(AOP(oper),fReturn[offset],offset);
1757 _endLazyDPSEvaluation();
1761 /*-----------------------------------------------------------------*/
1762 /* genXpush - pushes onto the external stack */
1763 /*-----------------------------------------------------------------*/
1764 static void genXpush (iCode *ic)
1766 asmop *aop = newAsmop(0);
1768 int size,offset = 0;
1770 D(emitcode(";", "genXpush "););
1772 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1773 r = getFreePtr(ic,&aop,FALSE);
1776 emitcode("mov","%s,_spx",r->name);
1778 size = AOP_SIZE(IC_LEFT(ic));
1779 _startLazyDPSEvaluation();
1782 char *l = aopGet(AOP(IC_LEFT(ic)),
1783 offset++,FALSE,FALSE,TRUE);
1785 emitcode("movx","@%s,a",r->name);
1786 emitcode("inc","%s",r->name);
1789 _endLazyDPSEvaluation();
1792 emitcode("mov","_spx,%s",r->name);
1794 freeAsmop(NULL,aop,ic,TRUE);
1795 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1798 /*-----------------------------------------------------------------*/
1799 /* genIpush - genrate code for pushing this gets a little complex */
1800 /*-----------------------------------------------------------------*/
1801 static void genIpush (iCode *ic)
1803 int size, offset = 0 ;
1806 D(emitcode(";", "genIpush "););
1809 /* if this is not a parm push : ie. it is spill push
1810 and spill push is always done on the local stack */
1811 if (!ic->parmPush) {
1813 /* and the item is spilt then do nothing */
1814 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1817 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1818 size = AOP_SIZE(IC_LEFT(ic));
1819 /* push it on the stack */
1820 _startLazyDPSEvaluation();
1822 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1827 emitcode("push","%s",l);
1829 _endLazyDPSEvaluation();
1833 /* this is a paramter push: in this case we call
1834 the routine to find the call and save those
1835 registers that need to be saved */
1838 /* if use external stack then call the external
1839 stack pushing routine */
1840 if (options.useXstack) {
1845 /* then do the push */
1846 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1848 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1849 size = AOP_SIZE(IC_LEFT(ic));
1851 _startLazyDPSEvaluation();
1853 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1854 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1855 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1857 emitcode("mov","a,%s",l);
1858 emitcode("push","acc");
1860 emitcode("push","%s",l);
1862 _endLazyDPSEvaluation();
1864 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1867 /*-----------------------------------------------------------------*/
1868 /* genIpop - recover the registers: can happen only for spilling */
1869 /*-----------------------------------------------------------------*/
1870 static void genIpop (iCode *ic)
1874 D(emitcode(";", "genIpop "););
1877 /* if the temp was not pushed then */
1878 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1881 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1882 size = AOP_SIZE(IC_LEFT(ic));
1884 _startLazyDPSEvaluation();
1887 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1890 _endLazyDPSEvaluation();
1892 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1895 /*-----------------------------------------------------------------*/
1896 /* unsaverbank - restores the resgister bank from stack */
1897 /*-----------------------------------------------------------------*/
1898 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1905 if (options.useXstack) {
1907 r = getFreePtr(ic,&aop,FALSE);
1910 emitcode("mov","%s,_spx",r->name);
1911 emitcode("movx","a,@%s",r->name);
1912 emitcode("mov","psw,a");
1913 emitcode("dec","%s",r->name);
1916 emitcode ("pop","psw");
1919 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1920 if (options.useXstack) {
1921 emitcode("movx","a,@%s",r->name);
1922 emitcode("mov","(%s+%d),a",
1923 regs390[i].base,8*bank+regs390[i].offset);
1924 emitcode("dec","%s",r->name);
1927 emitcode("pop","(%s+%d)",
1928 regs390[i].base,8*bank+regs390[i].offset);
1931 if (options.useXstack) {
1933 emitcode("mov","_spx,%s",r->name);
1934 freeAsmop(NULL,aop,ic,TRUE);
1939 /*-----------------------------------------------------------------*/
1940 /* saverbank - saves an entire register bank on the stack */
1941 /*-----------------------------------------------------------------*/
1942 static void saverbank (int bank, iCode *ic, bool pushPsw)
1948 if (options.useXstack) {
1951 r = getFreePtr(ic,&aop,FALSE);
1952 emitcode("mov","%s,_spx",r->name);
1956 for (i = 0 ; i < ds390_nRegs ;i++) {
1957 if (options.useXstack) {
1958 emitcode("inc","%s",r->name);
1959 emitcode("mov","a,(%s+%d)",
1960 regs390[i].base,8*bank+regs390[i].offset);
1961 emitcode("movx","@%s,a",r->name);
1963 emitcode("push","(%s+%d)",
1964 regs390[i].base,8*bank+regs390[i].offset);
1968 if (options.useXstack) {
1969 emitcode("mov","a,psw");
1970 emitcode("movx","@%s,a",r->name);
1971 emitcode("inc","%s",r->name);
1972 emitcode("mov","_spx,%s",r->name);
1973 freeAsmop (NULL,aop,ic,TRUE);
1976 emitcode("push","psw");
1978 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1984 /*-----------------------------------------------------------------*/
1985 /* genCall - generates a call statement */
1986 /*-----------------------------------------------------------------*/
1987 static void genCall (iCode *ic)
1991 D(emitcode(";", "genCall "););
1993 /* if caller saves & we have not saved then */
1997 /* if we are calling a function that is not using
1998 the same register bank then we need to save the
1999 destination registers on the stack */
2000 detype = getSpec(operandType(IC_LEFT(ic)));
2002 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2003 IS_ISR(currFunc->etype) &&
2006 saverbank(SPEC_BANK(detype),ic,TRUE);
2008 /* if send set is not empty the assign */
2012 for (sic = setFirstItem(_G.sendSet) ; sic ;
2013 sic = setNextItem(_G.sendSet))
2015 int size, offset = 0;
2017 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
2018 size = AOP_SIZE(IC_LEFT(sic));
2020 _startLazyDPSEvaluation();
2022 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2023 FALSE, FALSE, TRUE);
2024 if (strcmp(l,fReturn[offset]))
2025 emitcode("mov","%s,%s",
2030 _endLazyDPSEvaluation();
2031 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2036 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2037 OP_SYMBOL(IC_LEFT(ic))->rname :
2038 OP_SYMBOL(IC_LEFT(ic))->name));
2040 /* if we need assign a result value */
2041 if ((IS_ITEMP(IC_RESULT(ic)) &&
2042 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2043 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2044 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2047 /* Not really related to LAZY_DPS_OPT, but don't want
2048 * another testing flag right now...
2050 #define FAR_RETURN_OPT
2051 #ifdef FAR_RETURN_OPT
2052 if (isOperandInFarSpace(IC_RESULT(ic))
2053 && getSize(operandType(IC_RESULT(ic))) <= 2)
2055 int size = getSize(operandType(IC_RESULT(ic)));
2057 /* Special case for 1 or 2 byte return in far space. */
2058 emitcode(";", "Kevin function call abuse #1");
2063 emitcode("mov", "b,%s", fReturn[1]);
2066 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2067 aopPut(AOP(IC_RESULT(ic)),"a",0);
2071 aopPut(AOP(IC_RESULT(ic)),"b",1);
2073 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2079 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2082 assignResultValue(IC_RESULT(ic));
2084 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2087 if (!isOperandInFarSpace(IC_RESULT(ic)))
2090 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2093 assignResultValue(IC_RESULT(ic));
2095 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2099 /* Result is in far space, and requires DPTR to access
2100 * it. Push the result onto the stack and restore from
2103 int size = getSize(operandType(IC_RESULT(ic)));
2104 int offset = size - 1;
2107 emitcode(";", "Kevin function call abuse #1");
2109 /* first push the right side on to the stack */
2110 /* NB: this relies on the fact that "a" is the last
2111 * register in fReturn. If it were not, the MOVA
2112 * would potentially clobber a returned byte in A.
2115 l = fReturn[offset--];
2117 emitcode ("push","acc");
2120 /* now assign DPTR to result */
2121 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2122 size = AOP_SIZE(IC_RESULT(ic));
2123 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
2125 emitcode ("pop","acc");
2126 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
2128 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2133 /* adjust the stack for parameters if
2135 if (IC_LEFT(ic)->parmBytes) {
2137 if (IC_LEFT(ic)->parmBytes > 3) {
2138 emitcode("mov","a,%s",spname);
2139 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2140 emitcode("mov","%s,a",spname);
2142 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2143 emitcode("dec","%s",spname);
2147 /* if register bank was saved then pop them */
2149 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2151 /* if we hade saved some registers then unsave them */
2152 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2153 unsaveRegisters (ic);
2158 /*-----------------------------------------------------------------*/
2159 /* genPcall - generates a call by pointer statement */
2160 /*-----------------------------------------------------------------*/
2161 static void genPcall (iCode *ic)
2164 symbol *rlbl = newiTempLabel(NULL);
2166 D(emitcode(";", "genPcall "););
2169 /* if caller saves & we have not saved then */
2173 /* if we are calling a function that is not using
2174 the same register bank then we need to save the
2175 destination registers on the stack */
2176 detype = getSpec(operandType(IC_LEFT(ic)));
2178 IS_ISR(currFunc->etype) &&
2179 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2180 saverbank(SPEC_BANK(detype),ic,TRUE);
2183 /* push the return address on to the stack */
2184 emitcode("mov","a,#%05d$",(rlbl->key+100));
2185 emitcode("push","acc");
2186 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2187 emitcode("push","acc");
2189 if (options.model == MODEL_FLAT24)
2191 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2192 emitcode("push","acc");
2195 /* now push the calling address */
2196 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2198 pushSide(IC_LEFT(ic), FPTRSIZE);
2200 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2202 /* if send set is not empty the assign */
2206 for (sic = setFirstItem(_G.sendSet) ; sic ;
2207 sic = setNextItem(_G.sendSet))
2209 int size, offset = 0;
2211 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2212 size = AOP_SIZE(IC_LEFT(sic));
2213 _startLazyDPSEvaluation();
2216 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2218 if (strcmp(l,fReturn[offset]))
2220 emitcode("mov","%s,%s",
2226 _endLazyDPSEvaluation();
2227 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2233 emitcode("","%05d$:",(rlbl->key+100));
2236 /* if we need assign a result value */
2237 if ((IS_ITEMP(IC_RESULT(ic)) &&
2238 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2239 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2240 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2243 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2246 assignResultValue(IC_RESULT(ic));
2248 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2251 /* adjust the stack for parameters if
2253 if (IC_LEFT(ic)->parmBytes) {
2255 if (IC_LEFT(ic)->parmBytes > 3) {
2256 emitcode("mov","a,%s",spname);
2257 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2258 emitcode("mov","%s,a",spname);
2260 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2261 emitcode("dec","%s",spname);
2265 /* if register bank was saved then unsave them */
2267 (SPEC_BANK(currFunc->etype) !=
2269 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2271 /* if we hade saved some registers then
2274 unsaveRegisters (ic);
2278 /*-----------------------------------------------------------------*/
2279 /* resultRemat - result is rematerializable */
2280 /*-----------------------------------------------------------------*/
2281 static int resultRemat (iCode *ic)
2283 if (SKIP_IC(ic) || ic->op == IFX)
2286 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2287 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2288 if (sym->remat && !POINTER_SET(ic))
2295 #if defined(__BORLANDC__) || defined(_MSC_VER)
2296 #define STRCASECMP stricmp
2298 #define STRCASECMP strcasecmp
2301 /*-----------------------------------------------------------------*/
2302 /* inExcludeList - return 1 if the string is in exclude Reg list */
2303 /*-----------------------------------------------------------------*/
2304 static bool inExcludeList(char *s)
2308 if (options.excludeRegs[i] &&
2309 STRCASECMP(options.excludeRegs[i],"none") == 0)
2312 for ( i = 0 ; options.excludeRegs[i]; i++) {
2313 if (options.excludeRegs[i] &&
2314 STRCASECMP(s,options.excludeRegs[i]) == 0)
2320 /*-----------------------------------------------------------------*/
2321 /* genFunction - generated code for function entry */
2322 /*-----------------------------------------------------------------*/
2323 static void genFunction (iCode *ic)
2328 D(emitcode(";", "genFunction "););
2331 /* create the function header */
2332 emitcode(";","-----------------------------------------");
2333 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2334 emitcode(";","-----------------------------------------");
2336 emitcode("","%s:",sym->rname);
2337 fetype = getSpec(operandType(IC_LEFT(ic)));
2339 /* if critical function then turn interrupts off */
2340 if (SPEC_CRTCL(fetype))
2341 emitcode("clr","ea");
2343 /* here we need to generate the equates for the
2344 register bank if required */
2345 if (SPEC_BANK(fetype) != rbank) {
2348 rbank = SPEC_BANK(fetype);
2349 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2350 if (strcmp(regs390[i].base,"0") == 0)
2351 emitcode("","%s = 0x%02x",
2353 8*rbank+regs390[i].offset);
2355 emitcode ("","%s = %s + 0x%02x",
2358 8*rbank+regs390[i].offset);
2362 /* if this is an interrupt service routine then
2363 save acc, b, dpl, dph */
2364 if (IS_ISR(sym->etype)) {
2366 if (!inExcludeList("acc"))
2367 emitcode ("push","acc");
2368 if (!inExcludeList("b"))
2369 emitcode ("push","b");
2370 if (!inExcludeList("dpl"))
2371 emitcode ("push","dpl");
2372 if (!inExcludeList("dph"))
2373 emitcode ("push","dph");
2374 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2376 emitcode ("push", "dpx");
2377 /* Make sure we're using standard DPTR */
2378 emitcode ("push", "dps");
2379 emitcode ("mov", "dps, #0x00");
2380 if (options.stack10bit)
2382 /* This ISR could conceivably use DPTR2. Better save it. */
2383 emitcode ("push", "dpl1");
2384 emitcode ("push", "dph1");
2385 emitcode ("push", "dpx1");
2386 emitcode ("push", "ap");
2389 /* if this isr has no bank i.e. is going to
2390 run with bank 0 , then we need to save more
2392 if (!SPEC_BANK(sym->etype)) {
2394 /* if this function does not call any other
2395 function then we can be economical and
2396 save only those registers that are used */
2397 if (! sym->hasFcall) {
2400 /* if any registers used */
2401 if (sym->regsUsed) {
2402 /* save the registers used */
2403 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2404 if (bitVectBitValue(sym->regsUsed,i) ||
2405 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2406 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2411 /* this function has a function call cannot
2412 determines register usage so we will have the
2414 saverbank(0,ic,FALSE);
2418 /* if callee-save to be used for this function
2419 then save the registers being used in this function */
2420 if (sym->calleeSave) {
2423 /* if any registers used */
2424 if (sym->regsUsed) {
2425 /* save the registers used */
2426 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2427 if (bitVectBitValue(sym->regsUsed,i) ||
2428 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2429 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2437 /* set the register bank to the desired value */
2438 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2439 emitcode("push","psw");
2440 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2443 if (IS_RENT(sym->etype) || options.stackAuto) {
2445 if (options.useXstack) {
2446 emitcode("mov","r0,%s",spname);
2447 emitcode("mov","a,_bp");
2448 emitcode("movx","@r0,a");
2449 emitcode("inc","%s",spname);
2453 /* set up the stack */
2454 emitcode ("push","_bp"); /* save the callers stack */
2456 emitcode ("mov","_bp,%s",spname);
2459 /* adjust the stack for the function */
2464 werror(W_STACK_OVERFLOW,sym->name);
2466 if (i > 3 && sym->recvSize < 4) {
2468 emitcode ("mov","a,sp");
2469 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2470 emitcode ("mov","sp,a");
2475 emitcode("inc","sp");
2480 emitcode ("mov","a,_spx");
2481 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2482 emitcode ("mov","_spx,a");
2487 /*-----------------------------------------------------------------*/
2488 /* genEndFunction - generates epilogue for functions */
2489 /*-----------------------------------------------------------------*/
2490 static void genEndFunction (iCode *ic)
2492 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2494 D(emitcode(";", "genEndFunction "););
2496 if (IS_RENT(sym->etype) || options.stackAuto)
2498 emitcode ("mov","%s,_bp",spname);
2501 /* if use external stack but some variables were
2502 added to the local stack then decrement the
2504 if (options.useXstack && sym->stack) {
2505 emitcode("mov","a,sp");
2506 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2507 emitcode("mov","sp,a");
2511 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2512 if (options.useXstack) {
2513 emitcode("mov","r0,%s",spname);
2514 emitcode("movx","a,@r0");
2515 emitcode("mov","_bp,a");
2516 emitcode("dec","%s",spname);
2520 emitcode ("pop","_bp");
2524 /* restore the register bank */
2525 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2526 emitcode ("pop","psw");
2528 if (IS_ISR(sym->etype)) {
2530 /* now we need to restore the registers */
2531 /* if this isr has no bank i.e. is going to
2532 run with bank 0 , then we need to save more
2534 if (!SPEC_BANK(sym->etype)) {
2536 /* if this function does not call any other
2537 function then we can be economical and
2538 save only those registers that are used */
2539 if (! sym->hasFcall) {
2542 /* if any registers used */
2543 if (sym->regsUsed) {
2544 /* save the registers used */
2545 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2546 if (bitVectBitValue(sym->regsUsed,i) ||
2547 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2548 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2553 /* this function has a function call cannot
2554 determines register usage so we will have the
2556 unsaverbank(0,ic,FALSE);
2560 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2562 if (options.stack10bit)
2564 emitcode ("pop", "ap");
2565 emitcode ("pop", "dpx1");
2566 emitcode ("pop", "dph1");
2567 emitcode ("pop", "dpl1");
2569 emitcode ("pop", "dps");
2570 emitcode ("pop", "dpx");
2572 if (!inExcludeList("dph"))
2573 emitcode ("pop","dph");
2574 if (!inExcludeList("dpl"))
2575 emitcode ("pop","dpl");
2576 if (!inExcludeList("b"))
2577 emitcode ("pop","b");
2578 if (!inExcludeList("acc"))
2579 emitcode ("pop","acc");
2581 if (SPEC_CRTCL(sym->etype))
2582 emitcode("setb","ea");
2584 /* if debug then send end of function */
2585 /* if (options.debug && currFunc) { */
2588 emitcode("","C$%s$%d$%d$%d ==.",
2589 ic->filename,currFunc->lastLine,
2590 ic->level,ic->block);
2591 if (IS_STATIC(currFunc->etype))
2592 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2594 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2598 emitcode ("reti","");
2601 if (SPEC_CRTCL(sym->etype))
2602 emitcode("setb","ea");
2604 if (sym->calleeSave) {
2607 /* if any registers used */
2608 if (sym->regsUsed) {
2609 /* save the registers used */
2610 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2611 if (bitVectBitValue(sym->regsUsed,i) ||
2612 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2613 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2619 /* if debug then send end of function */
2622 emitcode("","C$%s$%d$%d$%d ==.",
2623 ic->filename,currFunc->lastLine,
2624 ic->level,ic->block);
2625 if (IS_STATIC(currFunc->etype))
2626 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2628 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2632 emitcode ("ret","");
2637 /*-----------------------------------------------------------------*/
2638 /* genRet - generate code for return statement */
2639 /*-----------------------------------------------------------------*/
2640 static void genRet (iCode *ic)
2642 int size,offset = 0 , pushed = 0;
2644 D(emitcode(";", "genRet "););
2646 /* if we have no return value then
2647 just generate the "ret" */
2651 /* we have something to return then
2652 move the return value into place */
2653 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2654 size = AOP_SIZE(IC_LEFT(ic));
2656 _startLazyDPSEvaluation();
2659 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2660 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2662 emitcode("push","%s",l);
2665 l = aopGet(AOP(IC_LEFT(ic)),offset,
2667 if (strcmp(fReturn[offset],l))
2668 emitcode("mov","%s,%s",fReturn[offset++],l);
2671 _endLazyDPSEvaluation();
2676 if (strcmp(fReturn[pushed],"a"))
2677 emitcode("pop",fReturn[pushed]);
2679 emitcode("pop","acc");
2682 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2685 /* generate a jump to the return label
2686 if the next is not the return statement */
2687 if (!(ic->next && ic->next->op == LABEL &&
2688 IC_LABEL(ic->next) == returnLabel))
2690 emitcode("ljmp","%05d$",(returnLabel->key+100));
2694 /*-----------------------------------------------------------------*/
2695 /* genLabel - generates a label */
2696 /*-----------------------------------------------------------------*/
2697 static void genLabel (iCode *ic)
2699 /* special case never generate */
2700 if (IC_LABEL(ic) == entryLabel)
2703 D(emitcode(";", "genLabel "););
2705 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2708 /*-----------------------------------------------------------------*/
2709 /* genGoto - generates a ljmp */
2710 /*-----------------------------------------------------------------*/
2711 static void genGoto (iCode *ic)
2713 D(emitcode(";", "genGoto "););
2714 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2717 /*-----------------------------------------------------------------*/
2718 /* findLabelBackwards: walks back through the iCode chain looking */
2719 /* for the given label. Returns number of iCode instructions */
2720 /* between that label and given ic. */
2721 /* Returns zero if label not found. */
2722 /*-----------------------------------------------------------------*/
2723 static int findLabelBackwards(iCode *ic, int key)
2732 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2734 /* printf("findLabelBackwards = %d\n", count); */
2742 /*-----------------------------------------------------------------*/
2743 /* genPlusIncr :- does addition with increment if possible */
2744 /*-----------------------------------------------------------------*/
2745 static bool genPlusIncr (iCode *ic)
2747 unsigned int icount ;
2748 unsigned int size = getDataSize(IC_RESULT(ic));
2750 /* will try to generate an increment */
2751 /* if the right side is not a literal
2753 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2756 /* if the literal value of the right hand side
2757 is greater than 4 then it is not worth it */
2758 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2761 /* if increment 16 bits in register */
2763 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2764 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2765 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2772 /* If the next instruction is a goto and the goto target
2773 * is <= 5 instructions previous to this, we can generate
2774 * jumps straight to that target.
2776 if (ic->next && ic->next->op == GOTO
2777 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2778 && labelRange <= 5 )
2780 emitcode(";", "tail increment optimized (range %d)", labelRange);
2781 tlbl = IC_LABEL(ic->next);
2786 tlbl = newiTempLabel(NULL);
2789 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2790 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2791 IS_AOP_PREG(IC_RESULT(ic)))
2792 emitcode("cjne","%s,#0x00,%05d$"
2793 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2796 emitcode("clr","a");
2797 emitcode("cjne","a,%s,%05d$"
2798 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2802 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2805 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2806 IS_AOP_PREG(IC_RESULT(ic)))
2807 emitcode("cjne","%s,#0x00,%05d$"
2808 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2811 emitcode("cjne","a,%s,%05d$"
2812 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2815 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2819 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2820 IS_AOP_PREG(IC_RESULT(ic)))
2821 emitcode("cjne","%s,#0x00,%05d$"
2822 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2825 emitcode("cjne","a,%s,%05d$"
2826 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2829 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2834 emitcode("","%05d$:",tlbl->key+100);
2839 /* if the sizes are greater than 1 then we cannot */
2840 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2841 AOP_SIZE(IC_LEFT(ic)) > 1 )
2844 /* we can if the aops of the left & result match or
2845 if they are in registers and the registers are the
2848 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2849 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2850 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2853 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2854 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2855 aopPut(AOP(IC_RESULT(ic)),"a",0);
2858 _startLazyDPSEvaluation();
2861 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2863 _endLazyDPSEvaluation();
2872 /*-----------------------------------------------------------------*/
2873 /* outBitAcc - output a bit in acc */
2874 /*-----------------------------------------------------------------*/
2875 static void outBitAcc(operand *result)
2877 symbol *tlbl = newiTempLabel(NULL);
2878 /* if the result is a bit */
2879 if (AOP_TYPE(result) == AOP_CRY){
2880 aopPut(AOP(result),"a",0);
2883 emitcode("jz","%05d$",tlbl->key+100);
2884 emitcode("mov","a,%s",one);
2885 emitcode("","%05d$:",tlbl->key+100);
2890 /*-----------------------------------------------------------------*/
2891 /* genPlusBits - generates code for addition of two bits */
2892 /*-----------------------------------------------------------------*/
2893 static void genPlusBits (iCode *ic)
2895 D(emitcode(";", "genPlusBits "););
2896 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2897 symbol *lbl = newiTempLabel(NULL);
2898 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2899 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2900 emitcode("cpl","c");
2901 emitcode("","%05d$:",(lbl->key+100));
2902 outBitC(IC_RESULT(ic));
2905 emitcode("clr","a");
2906 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2907 emitcode("rlc","a");
2908 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2909 emitcode("addc","a,#0x00");
2910 outAcc(IC_RESULT(ic));
2914 static void adjustArithmeticResult(iCode *ic)
2916 if (opIsGptr(IC_RESULT(ic)) &&
2917 opIsGptr(IC_LEFT(ic)) &&
2918 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2920 aopPut(AOP(IC_RESULT(ic)),
2921 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2925 if (opIsGptr(IC_RESULT(ic)) &&
2926 opIsGptr(IC_RIGHT(ic)) &&
2927 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2929 aopPut(AOP(IC_RESULT(ic)),
2930 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2934 if (opIsGptr(IC_RESULT(ic)) &&
2935 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2936 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2937 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2938 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2940 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2941 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2946 #define AOP_OP_3(ic) \
2947 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2948 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2949 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2950 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2951 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2953 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2955 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2958 #define AOP_OP_3(ic) \
2959 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2960 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2961 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
2962 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2963 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2964 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2966 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2968 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2971 #define AOP_OP_3_NOFATAL(ic, rc) \
2972 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2973 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2974 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2975 isOperandInFarSpace(IC_RESULT(ic))) \
2977 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
2982 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
2983 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2985 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2986 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2988 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2990 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2994 #define AOP_OP_2(ic) \
2995 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2996 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3001 #define AOP_SET_LOCALS(ic) \
3002 left = IC_LEFT(ic); \
3003 right = IC_RIGHT(ic); \
3004 result = IC_RESULT(ic);
3006 /*-----------------------------------------------------------------*/
3007 /* genPlus - generates code for addition */
3008 /*-----------------------------------------------------------------*/
3009 static void genPlus (iCode *ic)
3011 int size, offset = 0;
3012 bool pushResult = FALSE;
3015 D(emitcode(";", "genPlus "););
3017 /* special cases :- */
3020 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
3021 aopOp (IC_LEFT(ic),ic,FALSE,
3022 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3023 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
3024 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
3030 aopOp (IC_RESULT(ic),ic,TRUE,
3031 ((AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)
3032 || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR)));
3035 AOP_OP_3_NOFATAL(ic, pushResult);
3038 D(emitcode(";", "genPlus: must push result: 3 ops in far space"););
3044 /* if literal, literal on the right or
3045 if left requires ACC or right is already
3047 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)
3048 || ((AOP_NEEDSACC(IC_LEFT(ic))) && !(AOP_NEEDSACC(IC_RIGHT(ic))))
3049 || AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC )
3051 operand *t = IC_RIGHT(ic);
3052 IC_RIGHT(ic) = IC_LEFT(ic);
3054 emitcode(";", "Swapped plus args.");
3057 /* if both left & right are in bit
3059 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3060 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3065 /* if left in bit space & right literal */
3066 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3067 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3068 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3069 /* if result in bit space */
3070 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3071 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
3072 emitcode("cpl","c");
3073 outBitC(IC_RESULT(ic));
3075 size = getDataSize(IC_RESULT(ic));
3076 _startLazyDPSEvaluation();
3078 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3079 emitcode("addc","a,#00");
3080 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3082 _endLazyDPSEvaluation();
3087 /* if I can do an increment instead
3088 of add then GOOD for ME */
3089 if (genPlusIncr (ic) == TRUE)
3091 emitcode(";", "did genPlusIncr");
3096 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3098 _startLazyDPSEvaluation();
3101 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3103 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3105 emitcode("add","a,%s",
3106 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3108 emitcode("addc","a,%s",
3109 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3111 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3113 emitcode("add","a,%s",
3114 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3116 emitcode("addc","a,%s",
3117 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3121 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3125 emitcode("push", "acc");
3129 _endLazyDPSEvaluation();
3133 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3135 size = getDataSize(IC_LEFT(ic));
3136 rSize = getDataSize(IC_RESULT(ic));
3138 /* If the pushed data is bigger than the result,
3139 * simply discard unused bytes. Icky, but works.
3141 * Should we throw a warning here? We're losing data...
3143 while (size > rSize)
3145 D(emitcode(";", "discarding unused result byte."););
3146 emitcode("pop", "acc");
3152 emitcode("clr", "a");
3153 /* Conversly, we haven't pushed enough here.
3154 * just zero-pad, and all is well.
3156 while (size < rSize)
3158 emitcode("push", "acc");
3164 _startLazyDPSEvaluation();
3167 emitcode("pop", "acc");
3168 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3170 _endLazyDPSEvaluation();
3173 adjustArithmeticResult(ic);
3176 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3177 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3178 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3181 /*-----------------------------------------------------------------*/
3182 /* genMinusDec :- does subtraction with deccrement if possible */
3183 /*-----------------------------------------------------------------*/
3184 static bool genMinusDec (iCode *ic)
3186 unsigned int icount ;
3187 unsigned int size = getDataSize(IC_RESULT(ic));
3189 /* will try to generate an increment */
3190 /* if the right side is not a literal
3192 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3195 /* if the literal value of the right hand side
3196 is greater than 4 then it is not worth it */
3197 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3200 /* if decrement 16 bits in register */
3201 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3202 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3203 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3210 /* If the next instruction is a goto and the goto target
3211 * is <= 5 instructions previous to this, we can generate
3212 * jumps straight to that target.
3214 if (ic->next && ic->next->op == GOTO
3215 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3216 && labelRange <= 5 )
3218 emitcode(";", "tail decrement optimized (range %d)", labelRange);
3219 tlbl = IC_LABEL(ic->next);
3224 tlbl = newiTempLabel(NULL);
3228 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3229 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3230 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3231 IS_AOP_PREG(IC_RESULT(ic)))
3232 emitcode("cjne","%s,#0xff,%05d$"
3233 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3236 emitcode("mov","a,#0xff");
3237 emitcode("cjne","a,%s,%05d$"
3238 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3241 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3244 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3245 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3246 IS_AOP_PREG(IC_RESULT(ic)))
3247 emitcode("cjne","%s,#0xff,%05d$"
3248 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3251 emitcode("cjne","a,%s,%05d$"
3252 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3255 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3259 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3260 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3261 IS_AOP_PREG(IC_RESULT(ic)))
3262 emitcode("cjne","%s,#0xff,%05d$"
3263 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3266 emitcode("cjne","a,%s,%05d$"
3267 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3270 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3274 emitcode("","%05d$:",tlbl->key+100);
3279 /* if the sizes are greater than 1 then we cannot */
3280 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3281 AOP_SIZE(IC_LEFT(ic)) > 1 )
3284 /* we can if the aops of the left & result match or
3285 if they are in registers and the registers are the
3288 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3289 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3290 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3292 _startLazyDPSEvaluation();
3295 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3297 _endLazyDPSEvaluation();
3305 /*-----------------------------------------------------------------*/
3306 /* addSign - complete with sign */
3307 /*-----------------------------------------------------------------*/
3308 static void addSign(operand *result, int offset, int sign)
3310 int size = (getDataSize(result) - offset);
3313 emitcode("rlc","a");
3314 emitcode("subb","a,acc");
3316 aopPut(AOP(result),"a",offset++);
3319 aopPut(AOP(result),zero,offset++);
3323 /*-----------------------------------------------------------------*/
3324 /* genMinusBits - generates code for subtraction of two bits */
3325 /*-----------------------------------------------------------------*/
3326 static void genMinusBits (iCode *ic)
3328 symbol *lbl = newiTempLabel(NULL);
3330 D(emitcode(";", "genMinusBits "););
3332 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3333 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3334 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3335 emitcode("cpl","c");
3336 emitcode("","%05d$:",(lbl->key+100));
3337 outBitC(IC_RESULT(ic));
3340 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3341 emitcode("subb","a,acc");
3342 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3343 emitcode("inc","a");
3344 emitcode("","%05d$:",(lbl->key+100));
3345 aopPut(AOP(IC_RESULT(ic)),"a",0);
3346 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3350 /*-----------------------------------------------------------------*/
3351 /* genMinus - generates code for subtraction */
3352 /*-----------------------------------------------------------------*/
3353 static void genMinus (iCode *ic)
3355 int size, offset = 0;
3357 unsigned long lit = 0L;
3358 bool pushResult = FALSE;
3360 D(emitcode(";", "genMinus "););
3362 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3363 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3364 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3365 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3371 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3373 /* special cases :- */
3374 /* if both left & right are in bit space */
3375 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3376 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3381 /* if I can do an decrement instead
3382 of subtract then GOOD for ME */
3383 if (genMinusDec (ic) == TRUE)
3388 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3390 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3394 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3399 /* if literal, add a,#-lit, else normal subb */
3400 _startLazyDPSEvaluation();
3402 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3403 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3404 emitcode("subb","a,%s",
3405 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3407 /* first add without previous c */
3409 emitcode("add","a,#0x%02x",
3410 (unsigned int)(lit & 0x0FFL));
3412 emitcode("addc","a,#0x%02x",
3413 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3418 emitcode("push", "acc");
3422 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3426 _endLazyDPSEvaluation();
3430 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3432 size = getDataSize(IC_LEFT(ic));
3433 rSize = getDataSize(IC_RESULT(ic));
3435 /* If the pushed data is bigger than the result,
3436 * simply discard unused bytes. Icky, but works.
3438 * Should we throw a warning here? We're losing data...
3440 while (size > getDataSize(IC_RESULT(ic)))
3442 emitcode(";", "discarding unused result byte.");
3443 emitcode("pop", "acc");
3449 emitcode("clr", "a");
3450 /* Conversly, we haven't pushed enough here.
3451 * just zero-pad, and all is well.
3453 while (size < rSize)
3455 emitcode("push", "acc");
3463 emitcode("pop", "acc");
3464 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3468 adjustArithmeticResult(ic);
3471 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3472 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3473 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3477 /*-----------------------------------------------------------------*/
3478 /* genMultbits :- multiplication of bits */
3479 /*-----------------------------------------------------------------*/
3480 static void genMultbits (operand *left,
3484 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3485 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3490 /*-----------------------------------------------------------------*/
3491 /* genMultOneByte : 8 bit multiplication & division */
3492 /*-----------------------------------------------------------------*/
3493 static void genMultOneByte (operand *left,
3497 sym_link *opetype = operandType(result);
3502 /* (if two literals, the value is computed before) */
3503 /* if one literal, literal on the right */
3504 if (AOP_TYPE(left) == AOP_LIT){
3510 size = AOP_SIZE(result);
3511 /* signed or unsigned */
3512 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3513 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3515 emitcode("mul","ab");
3516 /* if result size = 1, mul signed = mul unsigned */
3517 aopPut(AOP(result),"a",0);
3519 if (SPEC_USIGN(opetype)){
3520 aopPut(AOP(result),"b",1);
3522 /* for filling the MSBs */
3523 emitcode("clr","a");
3526 emitcode("mov","a,b");
3528 /* adjust the MSB if left or right neg */
3530 /* if one literal */
3531 if (AOP_TYPE(right) == AOP_LIT){
3532 /* AND literal negative */
3533 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3534 /* adjust MSB (c==0 after mul) */
3535 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3539 lbl = newiTempLabel(NULL);
3540 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3541 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3542 emitcode("","%05d$:",(lbl->key+100));
3543 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3544 lbl = newiTempLabel(NULL);
3545 emitcode("jc","%05d$",(lbl->key+100));
3546 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3547 emitcode("","%05d$:",(lbl->key+100));
3550 lbl = newiTempLabel(NULL);
3551 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3552 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3553 emitcode("","%05d$:",(lbl->key+100));
3554 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3555 lbl = newiTempLabel(NULL);
3556 emitcode("jc","%05d$",(lbl->key+100));
3557 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3558 emitcode("","%05d$:",(lbl->key+100));
3560 aopPut(AOP(result),"a",1);
3563 emitcode("rlc","a");
3564 emitcode("subb","a,acc");
3571 aopPut(AOP(result),"a",offset++);
3575 /*-----------------------------------------------------------------*/
3576 /* genMult - generates code for multiplication */
3577 /*-----------------------------------------------------------------*/
3578 static void genMult (iCode *ic)
3580 operand *left = IC_LEFT(ic);
3581 operand *right = IC_RIGHT(ic);
3582 operand *result= IC_RESULT(ic);
3584 D(emitcode(";", "genMult "););
3586 /* assign the amsops */
3589 aopOp (left,ic,FALSE, FALSE);
3590 aopOp (right,ic,FALSE, TRUE);
3591 aopOp (result,ic,TRUE, FALSE);
3594 /* special cases first */
3596 if (AOP_TYPE(left) == AOP_CRY &&
3597 AOP_TYPE(right)== AOP_CRY) {
3598 genMultbits(left,right,result);
3602 /* if both are of size == 1 */
3603 if (AOP_SIZE(left) == 1 &&
3604 AOP_SIZE(right) == 1 ) {
3605 genMultOneByte(left,right,result);
3609 /* should have been converted to function call */
3613 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3614 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3615 freeAsmop(result,NULL,ic,TRUE);
3618 /*-----------------------------------------------------------------*/
3619 /* genDivbits :- division of bits */
3620 /*-----------------------------------------------------------------*/
3621 static void genDivbits (operand *left,
3628 /* the result must be bit */
3629 LOAD_AB_FOR_DIV(left, right, l);
3630 emitcode("div","ab");
3631 emitcode("rrc","a");
3632 aopPut(AOP(result),"c",0);
3635 /*-----------------------------------------------------------------*/
3636 /* genDivOneByte : 8 bit division */
3637 /*-----------------------------------------------------------------*/
3638 static void genDivOneByte (operand *left,
3642 sym_link *opetype = operandType(result);
3647 size = AOP_SIZE(result) - 1;
3649 /* signed or unsigned */
3650 if (SPEC_USIGN(opetype)) {
3651 /* unsigned is easy */
3652 LOAD_AB_FOR_DIV(left, right, l);
3653 emitcode("div","ab");
3654 aopPut(AOP(result),"a",0);
3656 aopPut(AOP(result),zero,offset++);
3660 /* signed is a little bit more difficult */
3662 /* save the signs of the operands */
3663 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3665 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3666 emitcode("push","acc"); /* save it on the stack */
3668 /* now sign adjust for both left & right */
3669 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3671 lbl = newiTempLabel(NULL);
3672 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3673 emitcode("cpl","a");
3674 emitcode("inc","a");
3675 emitcode("","%05d$:",(lbl->key+100));
3676 emitcode("mov","b,a");
3678 /* sign adjust left side */
3679 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3682 lbl = newiTempLabel(NULL);
3683 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3684 emitcode("cpl","a");
3685 emitcode("inc","a");
3686 emitcode("","%05d$:",(lbl->key+100));
3688 /* now the division */
3689 emitcode("nop", "; workaround for DS80C390 div bug.");
3690 emitcode("div","ab");
3691 /* we are interested in the lower order
3693 emitcode("mov","b,a");
3694 lbl = newiTempLabel(NULL);
3695 emitcode("pop","acc");
3696 /* if there was an over flow we don't
3697 adjust the sign of the result */
3698 emitcode("jb","ov,%05d$",(lbl->key+100));
3699 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3701 emitcode("clr","a");
3702 emitcode("subb","a,b");
3703 emitcode("mov","b,a");
3704 emitcode("","%05d$:",(lbl->key+100));
3706 /* now we are done */
3707 aopPut(AOP(result),"b",0);
3709 emitcode("mov","c,b.7");
3710 emitcode("subb","a,acc");
3713 aopPut(AOP(result),"a",offset++);
3717 /*-----------------------------------------------------------------*/
3718 /* genDiv - generates code for division */
3719 /*-----------------------------------------------------------------*/
3720 static void genDiv (iCode *ic)
3722 operand *left = IC_LEFT(ic);
3723 operand *right = IC_RIGHT(ic);
3724 operand *result= IC_RESULT(ic);
3726 D(emitcode(";", "genDiv "););
3728 /* assign the amsops */
3731 aopOp (left,ic,FALSE, FALSE);
3732 aopOp (right,ic,FALSE, TRUE);
3733 aopOp (result,ic,TRUE, FALSE);
3736 /* special cases first */
3738 if (AOP_TYPE(left) == AOP_CRY &&
3739 AOP_TYPE(right)== AOP_CRY) {
3740 genDivbits(left,right,result);
3744 /* if both are of size == 1 */
3745 if (AOP_SIZE(left) == 1 &&
3746 AOP_SIZE(right) == 1 ) {
3747 genDivOneByte(left,right,result);
3751 /* should have been converted to function call */
3754 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3755 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3756 freeAsmop(result,NULL,ic,TRUE);
3759 /*-----------------------------------------------------------------*/
3760 /* genModbits :- modulus of bits */
3761 /*-----------------------------------------------------------------*/
3762 static void genModbits (operand *left,
3769 /* the result must be bit */
3770 LOAD_AB_FOR_DIV(left, right, l);
3771 emitcode("div","ab");
3772 emitcode("mov","a,b");
3773 emitcode("rrc","a");
3774 aopPut(AOP(result),"c",0);
3777 /*-----------------------------------------------------------------*/
3778 /* genModOneByte : 8 bit modulus */
3779 /*-----------------------------------------------------------------*/
3780 static void genModOneByte (operand *left,
3784 sym_link *opetype = operandType(result);
3788 /* signed or unsigned */
3789 if (SPEC_USIGN(opetype)) {
3790 /* unsigned is easy */
3791 LOAD_AB_FOR_DIV(left, right, l);
3792 emitcode("div","ab");
3793 aopPut(AOP(result),"b",0);
3797 /* signed is a little bit more difficult */
3799 /* save the signs of the operands */
3800 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3803 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3804 emitcode("push","acc"); /* save it on the stack */
3806 /* now sign adjust for both left & right */
3807 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3810 lbl = newiTempLabel(NULL);
3811 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3812 emitcode("cpl","a");
3813 emitcode("inc","a");
3814 emitcode("","%05d$:",(lbl->key+100));
3815 emitcode("mov","b,a");
3817 /* sign adjust left side */
3818 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3821 lbl = newiTempLabel(NULL);
3822 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3823 emitcode("cpl","a");
3824 emitcode("inc","a");
3825 emitcode("","%05d$:",(lbl->key+100));
3827 /* now the multiplication */
3828 emitcode("nop", "; workaround for DS80C390 div bug.");
3829 emitcode("div","ab");
3830 /* we are interested in the lower order
3832 lbl = newiTempLabel(NULL);
3833 emitcode("pop","acc");
3834 /* if there was an over flow we don't
3835 adjust the sign of the result */
3836 emitcode("jb","ov,%05d$",(lbl->key+100));
3837 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3839 emitcode("clr","a");
3840 emitcode("subb","a,b");
3841 emitcode("mov","b,a");
3842 emitcode("","%05d$:",(lbl->key+100));
3844 /* now we are done */
3845 aopPut(AOP(result),"b",0);
3849 /*-----------------------------------------------------------------*/
3850 /* genMod - generates code for division */
3851 /*-----------------------------------------------------------------*/
3852 static void genMod (iCode *ic)
3854 operand *left = IC_LEFT(ic);
3855 operand *right = IC_RIGHT(ic);
3856 operand *result= IC_RESULT(ic);
3858 D(emitcode(";", "genMod "););
3860 /* assign the amsops */
3863 aopOp (left,ic,FALSE, FALSE);
3864 aopOp (right,ic,FALSE, TRUE);
3865 aopOp (result,ic,TRUE, FALSE);
3868 /* special cases first */
3870 if (AOP_TYPE(left) == AOP_CRY &&
3871 AOP_TYPE(right)== AOP_CRY) {
3872 genModbits(left,right,result);
3876 /* if both are of size == 1 */
3877 if (AOP_SIZE(left) == 1 &&
3878 AOP_SIZE(right) == 1 ) {
3879 genModOneByte(left,right,result);
3883 /* should have been converted to function call */
3887 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3888 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3889 freeAsmop(result,NULL,ic,TRUE);
3892 /*-----------------------------------------------------------------*/
3893 /* genIfxJump :- will create a jump depending on the ifx */
3894 /*-----------------------------------------------------------------*/
3895 static void genIfxJump (iCode *ic, char *jval)
3898 symbol *tlbl = newiTempLabel(NULL);
3901 D(emitcode(";", "genIfxJump "););
3903 /* if true label then we jump if condition
3905 if ( IC_TRUE(ic) ) {
3907 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3908 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3911 /* false label is present */
3912 jlbl = IC_FALSE(ic) ;
3913 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3914 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3916 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3917 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3919 emitcode(inst,"%05d$",tlbl->key+100);
3920 emitcode("ljmp","%05d$",jlbl->key+100);
3921 emitcode("","%05d$:",tlbl->key+100);
3923 /* mark the icode as generated */
3927 /*-----------------------------------------------------------------*/
3928 /* genCmp :- greater or less than comparison */
3929 /*-----------------------------------------------------------------*/
3930 static void genCmp (operand *left,operand *right,
3931 iCode *ic, iCode *ifx, int sign)
3933 int size, offset = 0 ;
3934 unsigned long lit = 0L;
3937 D(emitcode(";", "genCmp"););
3939 result = IC_RESULT(ic);
3941 /* if left & right are bit variables */
3942 if (AOP_TYPE(left) == AOP_CRY &&
3943 AOP_TYPE(right) == AOP_CRY ) {
3944 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3945 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3947 /* subtract right from left if at the
3948 end the carry flag is set then we know that
3949 left is greater than right */
3950 size = max(AOP_SIZE(left),AOP_SIZE(right));
3952 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3953 if((size == 1) && !sign &&
3954 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3955 symbol *lbl = newiTempLabel(NULL);
3956 emitcode("cjne","%s,%s,%05d$",
3957 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3958 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3960 emitcode("","%05d$:",lbl->key+100);
3962 if (AOP_TYPE(right) == AOP_LIT)
3964 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3965 /* optimize if(x < 0) or if(x >= 0) */
3974 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3976 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3977 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3979 aopOp(result,ic,FALSE, FALSE);
3981 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx)
3983 freeAsmop(result,NULL,ic,TRUE);
3984 genIfxJump (ifx,"acc.7");
3989 emitcode("rlc","a");
3991 goto release_freedLR;
3999 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
4000 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4001 emitcode(";", "genCmp #2");
4002 if (sign && (size == 0))
4004 emitcode(";", "genCmp #3");
4005 emitcode("xrl","a,#0x80");
4006 if (AOP_TYPE(right) == AOP_LIT)
4008 unsigned long lit = (unsigned long)
4009 floatFromVal(AOP(right)->aopu.aop_lit);
4010 emitcode(";", "genCmp #3.1");
4011 emitcode("subb","a,#0x%02x",
4012 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
4016 emitcode(";", "genCmp #3.2");
4017 if (AOP_NEEDSACC(right))
4019 emitcode("push", "acc");
4021 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
4022 FALSE,FALSE,FALSE));
4023 emitcode("xrl","b,#0x80");
4024 if (AOP_NEEDSACC(right))
4026 emitcode("pop", "acc");
4028 emitcode("subb","a,b");
4035 emitcode(";", "genCmp #4");
4036 if (AOP_NEEDSACC(right))
4039 emitcode(";", "genCmp #4.1");
4040 emitcode("xch", "a, b");
4041 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
4042 emitcode("xch", "a, b");
4047 emitcode(";", "genCmp #4.2");
4048 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
4051 emitcode("subb","a,%s",s);
4058 /* Don't need the left & right operands any more; do need the result. */
4059 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4060 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4062 aopOp(result,ic,FALSE, FALSE);
4066 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result))
4072 /* if the result is used in the next
4073 ifx conditional branch then generate
4074 code a little differently */
4077 genIfxJump (ifx,"c");
4083 /* leave the result in acc */
4085 freeAsmop(result,NULL,ic,TRUE);
4088 /*-----------------------------------------------------------------*/
4089 /* genCmpGt :- greater than comparison */
4090 /*-----------------------------------------------------------------*/
4091 static void genCmpGt (iCode *ic, iCode *ifx)
4093 operand *left, *right;
4094 sym_link *letype , *retype;
4097 D(emitcode(";", "genCmpGt "););
4100 right= IC_RIGHT(ic);
4102 letype = getSpec(operandType(left));
4103 retype =getSpec(operandType(right));
4104 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4106 /* assign the left & right amsops */
4109 genCmp(right, left, ic, ifx, sign);
4112 /*-----------------------------------------------------------------*/
4113 /* genCmpLt - less than comparisons */
4114 /*-----------------------------------------------------------------*/
4115 static void genCmpLt (iCode *ic, iCode *ifx)
4117 operand *left, *right;
4118 sym_link *letype , *retype;
4121 D(emitcode(";", "genCmpLt "););
4124 right= IC_RIGHT(ic);
4126 letype = getSpec(operandType(left));
4127 retype =getSpec(operandType(right));
4128 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4130 /* assign the left & right amsops */
4133 genCmp(left, right, ic, ifx, sign);
4136 /*-----------------------------------------------------------------*/
4137 /* gencjneshort - compare and jump if not equal */
4138 /*-----------------------------------------------------------------*/
4139 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4141 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4143 unsigned long lit = 0L;
4145 D(emitcode(";", "gencjneshort"););
4147 /* if the left side is a literal or
4148 if the right is in a pointer register and left
4150 if ((AOP_TYPE(left) == AOP_LIT) ||
4151 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4157 if(AOP_TYPE(right) == AOP_LIT)
4158 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4160 if (opIsGptr(left) || opIsGptr(right))
4162 /* We are comparing a generic pointer to something.
4163 * Exclude the generic type byte from the comparison.
4166 D(emitcode(";", "cjneshort: generic ptr special case.");)
4170 /* if the right side is a literal then anything goes */
4171 if (AOP_TYPE(right) == AOP_LIT &&
4172 AOP_TYPE(left) != AOP_DIR ) {
4174 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4176 emitcode("cjne","a,%s,%05d$",
4177 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4183 /* if the right side is in a register or in direct space or
4184 if the left is a pointer register & right is not */
4185 else if (AOP_TYPE(right) == AOP_REG ||
4186 AOP_TYPE(right) == AOP_DIR ||
4187 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4188 (IS_AOP_PREG(left) && !IS_AOP_PREG(right)))
4192 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4193 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4194 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4195 emitcode("jnz","%05d$",lbl->key+100);
4197 emitcode("cjne","a,%s,%05d$",
4198 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4203 /* right is a pointer reg need both a & b */
4205 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4207 emitcode("mov","b,%s",l);
4208 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4209 emitcode("cjne","a,b,%05d$",lbl->key+100);
4215 /*-----------------------------------------------------------------*/
4216 /* gencjne - compare and jump if not equal */
4217 /*-----------------------------------------------------------------*/
4218 static void gencjne(operand *left, operand *right, symbol *lbl)
4220 symbol *tlbl = newiTempLabel(NULL);
4222 D(emitcode(";", "gencjne"););
4224 gencjneshort(left, right, lbl);
4226 emitcode("mov","a,%s",one);
4227 emitcode("sjmp","%05d$",tlbl->key+100);
4228 emitcode("","%05d$:",lbl->key+100);
4229 emitcode("clr","a");
4230 emitcode("","%05d$:",tlbl->key+100);
4233 /*-----------------------------------------------------------------*/
4234 /* genCmpEq - generates code for equal to */
4235 /*-----------------------------------------------------------------*/
4236 static void genCmpEq (iCode *ic, iCode *ifx)
4238 operand *left, *right, *result;
4240 D(emitcode(";", "genCmpEq "););
4245 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4246 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4247 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4250 /* if literal, literal on the right or
4251 if the right is in a pointer register and left
4253 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4254 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4255 operand *t = IC_RIGHT(ic);
4256 IC_RIGHT(ic) = IC_LEFT(ic);
4260 if (ifx && /* !AOP_SIZE(result) */
4261 OP_SYMBOL(result) &&
4262 OP_SYMBOL(result)->regType == REG_CND)
4265 /* if they are both bit variables */
4266 if (AOP_TYPE(left) == AOP_CRY &&
4267 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4268 if(AOP_TYPE(right) == AOP_LIT){
4269 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4271 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4272 emitcode("cpl","c");
4273 } else if(lit == 1L) {
4274 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4276 emitcode("clr","c");
4278 /* AOP_TYPE(right) == AOP_CRY */
4280 symbol *lbl = newiTempLabel(NULL);
4281 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4282 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4283 emitcode("cpl","c");
4284 emitcode("","%05d$:",(lbl->key+100));
4286 /* if true label then we jump if condition
4288 tlbl = newiTempLabel(NULL);
4289 if ( IC_TRUE(ifx) ) {
4290 emitcode("jnc","%05d$",tlbl->key+100);
4291 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4293 emitcode("jc","%05d$",tlbl->key+100);
4294 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4296 emitcode("","%05d$:",tlbl->key+100);
4298 tlbl = newiTempLabel(NULL);
4299 gencjneshort(left, right, tlbl);
4300 if ( IC_TRUE(ifx) ) {
4301 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4302 emitcode("","%05d$:",tlbl->key+100);
4304 symbol *lbl = newiTempLabel(NULL);
4305 emitcode("sjmp","%05d$",lbl->key+100);
4306 emitcode("","%05d$:",tlbl->key+100);
4307 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4308 emitcode("","%05d$:",lbl->key+100);
4311 /* mark the icode as generated */
4314 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4315 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4319 /* if they are both bit variables */
4320 if (AOP_TYPE(left) == AOP_CRY &&
4321 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4322 if(AOP_TYPE(right) == AOP_LIT){
4323 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4325 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4326 emitcode("cpl","c");
4327 } else if(lit == 1L) {
4328 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4330 emitcode("clr","c");
4332 /* AOP_TYPE(right) == AOP_CRY */
4334 symbol *lbl = newiTempLabel(NULL);
4335 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4336 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4337 emitcode("cpl","c");
4338 emitcode("","%05d$:",(lbl->key+100));
4341 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4342 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4344 aopOp(result,ic,TRUE, FALSE);
4347 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4352 genIfxJump (ifx,"c");
4355 /* if the result is used in an arithmetic operation
4356 then put the result in place */
4359 gencjne(left,right,newiTempLabel(NULL));
4361 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4362 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4364 aopOp(result,ic,TRUE, FALSE);
4366 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4367 aopPut(AOP(result),"a",0);
4371 genIfxJump (ifx,"a");
4374 /* if the result is used in an arithmetic operation
4375 then put the result in place */
4376 if (AOP_TYPE(result) != AOP_CRY)
4378 /* leave the result in acc */
4382 freeAsmop(result,NULL,ic,TRUE);
4385 /*-----------------------------------------------------------------*/
4386 /* ifxForOp - returns the icode containing the ifx for operand */
4387 /*-----------------------------------------------------------------*/
4388 static iCode *ifxForOp ( operand *op, iCode *ic )
4390 /* if true symbol then needs to be assigned */
4391 if (IS_TRUE_SYMOP(op))
4394 /* if this has register type condition and
4395 the next instruction is ifx with the same operand
4396 and live to of the operand is upto the ifx only then */
4398 ic->next->op == IFX &&
4399 IC_COND(ic->next)->key == op->key &&
4400 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4405 /*-----------------------------------------------------------------*/
4406 /* genAndOp - for && operation */
4407 /*-----------------------------------------------------------------*/
4408 static void genAndOp (iCode *ic)
4410 operand *left,*right, *result;
4413 D(emitcode(";", "genAndOp "););
4415 /* note here that && operations that are in an
4416 if statement are taken away by backPatchLabels
4417 only those used in arthmetic operations remain */
4421 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4422 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4423 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4426 /* if both are bit variables */
4427 if (AOP_TYPE(left) == AOP_CRY &&
4428 AOP_TYPE(right) == AOP_CRY ) {
4429 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4430 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4433 tlbl = newiTempLabel(NULL);
4435 emitcode("jz","%05d$",tlbl->key+100);
4437 emitcode("","%05d$:",tlbl->key+100);
4441 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4442 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4443 freeAsmop(result,NULL,ic,TRUE);
4447 /*-----------------------------------------------------------------*/
4448 /* genOrOp - for || operation */
4449 /*-----------------------------------------------------------------*/
4450 static void genOrOp (iCode *ic)
4452 operand *left,*right, *result;
4455 D(emitcode(";", "genOrOp "););
4457 /* note here that || operations that are in an
4458 if statement are taken away by backPatchLabels
4459 only those used in arthmetic operations remain */
4463 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4464 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4465 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4468 /* if both are bit variables */
4469 if (AOP_TYPE(left) == AOP_CRY &&
4470 AOP_TYPE(right) == AOP_CRY ) {
4471 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4472 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4475 tlbl = newiTempLabel(NULL);
4477 emitcode("jnz","%05d$",tlbl->key+100);
4479 emitcode("","%05d$:",tlbl->key+100);
4483 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4484 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4485 freeAsmop(result,NULL,ic,TRUE);
4488 /*-----------------------------------------------------------------*/
4489 /* isLiteralBit - test if lit == 2^n */
4490 /*-----------------------------------------------------------------*/
4491 static int isLiteralBit(unsigned long lit)
4493 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4494 0x100L,0x200L,0x400L,0x800L,
4495 0x1000L,0x2000L,0x4000L,0x8000L,
4496 0x10000L,0x20000L,0x40000L,0x80000L,
4497 0x100000L,0x200000L,0x400000L,0x800000L,
4498 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4499 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4502 for(idx = 0; idx < 32; idx++)
4508 /*-----------------------------------------------------------------*/
4509 /* continueIfTrue - */
4510 /*-----------------------------------------------------------------*/
4511 static void continueIfTrue (iCode *ic)
4514 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4518 /*-----------------------------------------------------------------*/
4520 /*-----------------------------------------------------------------*/
4521 static void jumpIfTrue (iCode *ic)
4524 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4528 /*-----------------------------------------------------------------*/
4529 /* jmpTrueOrFalse - */
4530 /*-----------------------------------------------------------------*/
4531 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4533 // ugly but optimized by peephole
4535 symbol *nlbl = newiTempLabel(NULL);
4536 emitcode("sjmp","%05d$",nlbl->key+100);
4537 emitcode("","%05d$:",tlbl->key+100);
4538 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4539 emitcode("","%05d$:",nlbl->key+100);
4542 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4543 emitcode("","%05d$:",tlbl->key+100);
4548 /*-----------------------------------------------------------------*/
4549 /* genAnd - code for and */
4550 /*-----------------------------------------------------------------*/
4551 static void genAnd (iCode *ic, iCode *ifx)
4553 operand *left, *right, *result;
4555 unsigned long lit = 0L;
4559 D(emitcode(";", "genAnd "););
4564 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4565 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4566 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4570 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4572 AOP_TYPE(left), AOP_TYPE(right));
4573 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4575 AOP_SIZE(left), AOP_SIZE(right));
4578 /* if left is a literal & right is not then exchange them */
4579 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4580 AOP_NEEDSACC(left)) {
4581 operand *tmp = right ;
4586 /* if result = right then exchange them */
4587 if(sameRegs(AOP(result),AOP(right))){
4588 operand *tmp = right ;
4593 /* if right is bit then exchange them */
4594 if (AOP_TYPE(right) == AOP_CRY &&
4595 AOP_TYPE(left) != AOP_CRY){
4596 operand *tmp = right ;
4600 if(AOP_TYPE(right) == AOP_LIT)
4601 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4603 size = AOP_SIZE(result);
4606 // result = bit & yy;
4607 if (AOP_TYPE(left) == AOP_CRY){
4608 // c = bit & literal;
4609 if(AOP_TYPE(right) == AOP_LIT){
4611 if(size && sameRegs(AOP(result),AOP(left)))
4614 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4617 if(size && (AOP_TYPE(result) == AOP_CRY)){
4618 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4621 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4625 emitcode("clr","c");
4628 if (AOP_TYPE(right) == AOP_CRY){
4630 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4631 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4634 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4636 emitcode("rrc","a");
4637 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4645 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4646 genIfxJump(ifx, "c");
4650 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4651 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4652 if((AOP_TYPE(right) == AOP_LIT) &&
4653 (AOP_TYPE(result) == AOP_CRY) &&
4654 (AOP_TYPE(left) != AOP_CRY)){
4655 int posbit = isLiteralBit(lit);
4659 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4662 emitcode("mov","c,acc.%d",posbit&0x07);
4666 sprintf(buffer,"acc.%d",posbit&0x07);
4667 genIfxJump(ifx, buffer);
4672 symbol *tlbl = newiTempLabel(NULL);
4673 int sizel = AOP_SIZE(left);
4675 emitcode("setb","c");
4677 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4678 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4680 if((posbit = isLiteralBit(bytelit)) != 0)
4681 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4683 if(bytelit != 0x0FFL)
4684 emitcode("anl","a,%s",
4685 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4686 emitcode("jnz","%05d$",tlbl->key+100);
4691 // bit = left & literal
4693 emitcode("clr","c");
4694 emitcode("","%05d$:",tlbl->key+100);
4696 // if(left & literal)
4699 jmpTrueOrFalse(ifx, tlbl);
4707 /* if left is same as result */
4708 if(sameRegs(AOP(result),AOP(left))){
4709 for(;size--; offset++) {
4710 if(AOP_TYPE(right) == AOP_LIT){
4711 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4715 aopPut(AOP(result),zero,offset);
4717 if (IS_AOP_PREG(result)) {
4718 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4719 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4720 aopPut(AOP(result),"a",offset);
4722 emitcode("anl","%s,%s",
4723 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4724 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4726 if (AOP_TYPE(left) == AOP_ACC)
4727 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4729 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4730 if (IS_AOP_PREG(result)) {
4731 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4732 aopPut(AOP(result),"a",offset);
4735 emitcode("anl","%s,a",
4736 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4741 // left & result in different registers
4742 if(AOP_TYPE(result) == AOP_CRY){
4744 // if(size), result in bit
4745 // if(!size && ifx), conditional oper: if(left & right)
4746 symbol *tlbl = newiTempLabel(NULL);
4747 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4749 emitcode("setb","c");
4751 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4752 emitcode("anl","a,%s",
4753 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4754 emitcode("jnz","%05d$",tlbl->key+100);
4759 emitcode("","%05d$:",tlbl->key+100);
4762 jmpTrueOrFalse(ifx, tlbl);
4765 for(;(size--);offset++)
4768 // result = left & right
4769 if(AOP_TYPE(right) == AOP_LIT)
4771 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4774 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4778 else if (bytelit == 0)
4780 aopPut(AOP(result),zero,offset);
4783 D(emitcode(";", "better literal AND."););
4784 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4785 emitcode("anl", "a, %s", aopGet(AOP(right),offset,
4786 FALSE,FALSE,FALSE));
4791 // faster than result <- left, anl result,right
4792 // and better if result is SFR
4793 if (AOP_TYPE(left) == AOP_ACC)
4795 emitcode("anl","a,%s",aopGet(AOP(right),offset,
4796 FALSE,FALSE,FALSE));
4800 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4801 emitcode("anl","a,%s",
4802 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4805 aopPut(AOP(result),"a",offset);
4811 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4812 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4813 freeAsmop(result,NULL,ic,TRUE);
4816 /*-----------------------------------------------------------------*/
4817 /* genOr - code for or */
4818 /*-----------------------------------------------------------------*/
4819 static void genOr (iCode *ic, iCode *ifx)
4821 operand *left, *right, *result;
4823 unsigned long lit = 0L;
4825 D(emitcode(";", "genOr "););
4830 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4831 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4832 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4836 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4838 AOP_TYPE(left), AOP_TYPE(right));
4839 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4841 AOP_SIZE(left), AOP_SIZE(right));
4844 /* if left is a literal & right is not then exchange them */
4845 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4846 AOP_NEEDSACC(left)) {
4847 operand *tmp = right ;
4852 /* if result = right then exchange them */
4853 if(sameRegs(AOP(result),AOP(right))){
4854 operand *tmp = right ;
4859 /* if right is bit then exchange them */
4860 if (AOP_TYPE(right) == AOP_CRY &&
4861 AOP_TYPE(left) != AOP_CRY){
4862 operand *tmp = right ;
4866 if(AOP_TYPE(right) == AOP_LIT)
4867 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4869 size = AOP_SIZE(result);
4873 if (AOP_TYPE(left) == AOP_CRY){
4874 if(AOP_TYPE(right) == AOP_LIT){
4875 // c = bit & literal;
4877 // lit != 0 => result = 1
4878 if(AOP_TYPE(result) == AOP_CRY){
4880 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4882 continueIfTrue(ifx);
4885 emitcode("setb","c");
4887 // lit == 0 => result = left
4888 if(size && sameRegs(AOP(result),AOP(left)))
4890 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4893 if (AOP_TYPE(right) == AOP_CRY){
4895 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4896 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4900 symbol *tlbl = newiTempLabel(NULL);
4901 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4902 emitcode("setb","c");
4903 emitcode("jb","%s,%05d$",
4904 AOP(left)->aopu.aop_dir,tlbl->key+100);
4906 emitcode("jnz","%05d$",tlbl->key+100);
4907 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4908 jmpTrueOrFalse(ifx, tlbl);
4912 emitcode("","%05d$:",tlbl->key+100);
4921 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4922 genIfxJump(ifx, "c");
4926 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4927 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4928 if((AOP_TYPE(right) == AOP_LIT) &&
4929 (AOP_TYPE(result) == AOP_CRY) &&
4930 (AOP_TYPE(left) != AOP_CRY)){
4934 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4936 continueIfTrue(ifx);
4939 // lit = 0, result = boolean(left)
4941 emitcode("setb","c");
4944 symbol *tlbl = newiTempLabel(NULL);
4945 emitcode("jnz","%05d$",tlbl->key+100);
4947 emitcode("","%05d$:",tlbl->key+100);
4949 genIfxJump (ifx,"a");
4957 /* if left is same as result */
4958 if(sameRegs(AOP(result),AOP(left)))
4960 for(;size--; offset++)
4962 if(AOP_TYPE(right) == AOP_LIT){
4963 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4969 if (IS_AOP_PREG(left))
4971 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4972 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4973 aopPut(AOP(result),"a",offset);
4977 emitcode("orl","%s,%s",
4978 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4979 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4985 if (AOP_TYPE(left) == AOP_ACC)
4987 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4991 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4992 if (IS_AOP_PREG(left))
4994 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4995 aopPut(AOP(result),"a",offset);
4999 emitcode("orl","%s,a",
5000 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5008 // left & result in different registers
5009 if(AOP_TYPE(result) == AOP_CRY)
5012 // if(size), result in bit
5013 // if(!size && ifx), conditional oper: if(left | right)
5014 symbol *tlbl = newiTempLabel(NULL);
5015 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5017 emitcode("setb","c");
5019 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5020 emitcode("orl","a,%s",
5021 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5022 emitcode("jnz","%05d$",tlbl->key+100);
5027 emitcode("","%05d$:",tlbl->key+100);
5030 jmpTrueOrFalse(ifx, tlbl);
5034 for(;(size--);offset++)
5037 // result = left & right
5038 if(AOP_TYPE(right) == AOP_LIT)
5040 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5043 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5047 D(emitcode(";", "better literal OR."););
5048 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5049 emitcode("orl", "a, %s", aopGet(AOP(right),offset,
5050 FALSE,FALSE,FALSE));
5055 // faster than result <- left, anl result,right
5056 // and better if result is SFR
5057 if (AOP_TYPE(left) == AOP_ACC)
5059 emitcode("orl","a,%s",aopGet(AOP(right),offset,
5060 FALSE,FALSE,FALSE));
5064 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5065 emitcode("orl","a,%s",
5066 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5069 aopPut(AOP(result),"a",offset);
5075 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5076 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5077 freeAsmop(result,NULL,ic,TRUE);
5080 /*-----------------------------------------------------------------*/
5081 /* genXor - code for xclusive or */
5082 /*-----------------------------------------------------------------*/
5083 static void genXor (iCode *ic, iCode *ifx)
5085 operand *left, *right, *result;
5087 unsigned long lit = 0L;
5089 D(emitcode(";", "genXor "););
5094 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
5095 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
5096 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
5100 emitcode("","; Type res[%d] = l[%d]&r[%d]",
5102 AOP_TYPE(left), AOP_TYPE(right));
5103 emitcode("","; Size res[%d] = l[%d]&r[%d]",
5105 AOP_SIZE(left), AOP_SIZE(right));
5108 /* if left is a literal & right is not ||
5109 if left needs acc & right does not */
5110 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5111 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5112 operand *tmp = right ;
5117 /* if result = right then exchange them */
5118 if(sameRegs(AOP(result),AOP(right))){
5119 operand *tmp = right ;
5124 /* if right is bit then exchange them */
5125 if (AOP_TYPE(right) == AOP_CRY &&
5126 AOP_TYPE(left) != AOP_CRY){
5127 operand *tmp = right ;
5131 if(AOP_TYPE(right) == AOP_LIT)
5132 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5134 size = AOP_SIZE(result);
5138 if (AOP_TYPE(left) == AOP_CRY){
5139 if(AOP_TYPE(right) == AOP_LIT){
5140 // c = bit & literal;
5142 // lit>>1 != 0 => result = 1
5143 if(AOP_TYPE(result) == AOP_CRY){
5145 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5147 continueIfTrue(ifx);
5150 emitcode("setb","c");
5154 // lit == 0, result = left
5155 if(size && sameRegs(AOP(result),AOP(left)))
5157 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5159 // lit == 1, result = not(left)
5160 if(size && sameRegs(AOP(result),AOP(left))){
5161 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5164 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5165 emitcode("cpl","c");
5172 symbol *tlbl = newiTempLabel(NULL);
5173 if (AOP_TYPE(right) == AOP_CRY){
5175 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5178 int sizer = AOP_SIZE(right);
5180 // if val>>1 != 0, result = 1
5181 emitcode("setb","c");
5183 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5185 // test the msb of the lsb
5186 emitcode("anl","a,#0xfe");
5187 emitcode("jnz","%05d$",tlbl->key+100);
5191 emitcode("rrc","a");
5193 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5194 emitcode("cpl","c");
5195 emitcode("","%05d$:",(tlbl->key+100));
5202 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5203 genIfxJump(ifx, "c");
5207 if(sameRegs(AOP(result),AOP(left))){
5208 /* if left is same as result */
5209 for(;size--; offset++) {
5210 if(AOP_TYPE(right) == AOP_LIT){
5211 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5214 if (IS_AOP_PREG(left)) {
5215 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5216 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5217 aopPut(AOP(result),"a",offset);
5219 emitcode("xrl","%s,%s",
5220 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5221 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5223 if (AOP_TYPE(left) == AOP_ACC)
5224 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5226 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5227 if (IS_AOP_PREG(left)) {
5228 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5229 aopPut(AOP(result),"a",offset);
5231 emitcode("xrl","%s,a",
5232 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5237 // left & result in different registers
5238 if(AOP_TYPE(result) == AOP_CRY){
5240 // if(size), result in bit
5241 // if(!size && ifx), conditional oper: if(left ^ right)
5242 symbol *tlbl = newiTempLabel(NULL);
5243 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5245 emitcode("setb","c");
5247 if((AOP_TYPE(right) == AOP_LIT) &&
5248 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5249 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5251 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5252 emitcode("xrl","a,%s",
5253 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5255 emitcode("jnz","%05d$",tlbl->key+100);
5260 emitcode("","%05d$:",tlbl->key+100);
5263 jmpTrueOrFalse(ifx, tlbl);
5264 } else for(;(size--);offset++)
5267 // result = left & right
5268 if(AOP_TYPE(right) == AOP_LIT)
5270 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5273 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5277 D(emitcode(";", "better literal XOR."););
5278 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5279 emitcode("xrl", "a, %s", aopGet(AOP(right),offset,
5280 FALSE,FALSE,FALSE));
5284 // faster than result <- left, anl result,right
5285 // and better if result is SFR
5286 if (AOP_TYPE(left) == AOP_ACC)
5288 emitcode("xrl","a,%s",aopGet(AOP(right),offset,
5289 FALSE,FALSE,FALSE));
5293 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5294 emitcode("xrl","a,%s",
5295 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5298 aopPut(AOP(result),"a",offset);
5303 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5304 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5305 freeAsmop(result,NULL,ic,TRUE);
5308 /*-----------------------------------------------------------------*/
5309 /* genInline - write the inline code out */
5310 /*-----------------------------------------------------------------*/
5311 static void genInline (iCode *ic)
5313 char buffer[MAX_INLINEASM];
5317 D(emitcode(";", "genInline "););
5319 _G.inLine += (!options.asmpeep);
5320 strcpy(buffer,IC_INLINE(ic));
5322 /* emit each line as a code */
5341 /* emitcode("",buffer); */
5342 _G.inLine -= (!options.asmpeep);
5345 /*-----------------------------------------------------------------*/
5346 /* genRRC - rotate right with carry */
5347 /*-----------------------------------------------------------------*/
5348 static void genRRC (iCode *ic)
5350 operand *left , *result ;
5351 int size, offset = 0;
5354 D(emitcode(";", "genRRC "););
5356 /* rotate right with carry */
5358 result=IC_RESULT(ic);
5359 aopOp (left,ic,FALSE, FALSE);
5360 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5362 /* move it to the result */
5363 size = AOP_SIZE(result);
5367 _startLazyDPSEvaluation();
5369 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5371 emitcode("rrc","a");
5372 if (AOP_SIZE(result) > 1)
5373 aopPut(AOP(result),"a",offset--);
5375 _endLazyDPSEvaluation();
5377 /* now we need to put the carry into the
5378 highest order byte of the result */
5379 if (AOP_SIZE(result) > 1) {
5380 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5383 emitcode("mov","acc.7,c");
5384 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5385 freeAsmop(left,NULL,ic,TRUE);
5386 freeAsmop(result,NULL,ic,TRUE);
5389 /*-----------------------------------------------------------------*/
5390 /* genRLC - generate code for rotate left with carry */
5391 /*-----------------------------------------------------------------*/
5392 static void genRLC (iCode *ic)
5394 operand *left , *result ;
5395 int size, offset = 0;
5398 D(emitcode(";", "genRLC "););
5400 /* rotate right with carry */
5402 result=IC_RESULT(ic);
5403 aopOp (left,ic,FALSE, FALSE);
5404 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5406 /* move it to the result */
5407 size = AOP_SIZE(result);
5410 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5412 emitcode("add","a,acc");
5413 if (AOP_SIZE(result) > 1)
5415 aopPut(AOP(result),"a",offset++);
5418 _startLazyDPSEvaluation();
5420 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5422 emitcode("rlc","a");
5423 if (AOP_SIZE(result) > 1)
5424 aopPut(AOP(result),"a",offset++);
5426 _endLazyDPSEvaluation();
5428 /* now we need to put the carry into the
5429 highest order byte of the result */
5430 if (AOP_SIZE(result) > 1) {
5431 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5434 emitcode("mov","acc.0,c");
5435 aopPut(AOP(result),"a",0);
5436 freeAsmop(left,NULL,ic,TRUE);
5437 freeAsmop(result,NULL,ic,TRUE);
5440 /*-----------------------------------------------------------------*/
5441 /* genGetHbit - generates code get highest order bit */
5442 /*-----------------------------------------------------------------*/
5443 static void genGetHbit (iCode *ic)
5445 operand *left, *result;
5447 result=IC_RESULT(ic);
5448 aopOp (left,ic,FALSE, FALSE);
5449 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5451 D(emitcode(";", "genGetHbit "););
5453 /* get the highest order byte into a */
5454 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5455 if(AOP_TYPE(result) == AOP_CRY){
5456 emitcode("rlc","a");
5461 emitcode("anl","a,#0x01");
5466 freeAsmop(left,NULL,ic,TRUE);
5467 freeAsmop(result,NULL,ic,TRUE);
5470 /*-----------------------------------------------------------------*/
5471 /* AccRol - rotate left accumulator by known count */
5472 /*-----------------------------------------------------------------*/
5473 static void AccRol (int shCount)
5475 shCount &= 0x0007; // shCount : 0..7
5487 emitcode("swap","a");
5491 emitcode("swap","a");
5494 emitcode("swap","a");
5507 /*-----------------------------------------------------------------*/
5508 /* AccLsh - left shift accumulator by known count */
5509 /*-----------------------------------------------------------------*/
5510 static void AccLsh (int shCount)
5514 emitcode("add","a,acc");
5517 emitcode("add","a,acc");
5518 emitcode("add","a,acc");
5520 /* rotate left accumulator */
5522 /* and kill the lower order bits */
5523 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5528 /*-----------------------------------------------------------------*/
5529 /* AccRsh - right shift accumulator by known count */
5530 /*-----------------------------------------------------------------*/
5531 static void AccRsh (int shCount)
5536 emitcode("rrc","a");
5538 /* rotate right accumulator */
5539 AccRol(8 - shCount);
5540 /* and kill the higher order bits */
5541 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5548 /*-----------------------------------------------------------------*/
5549 /* AccSRsh - signed right shift accumulator by known count */
5550 /*-----------------------------------------------------------------*/
5551 static void AccSRsh (int shCount)
5556 emitcode("mov","c,acc.7");
5557 emitcode("rrc","a");
5558 } else if(shCount == 2){
5559 emitcode("mov","c,acc.7");
5560 emitcode("rrc","a");
5561 emitcode("mov","c,acc.7");
5562 emitcode("rrc","a");
5564 tlbl = newiTempLabel(NULL);
5565 /* rotate right accumulator */
5566 AccRol(8 - shCount);
5567 /* and kill the higher order bits */
5568 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5569 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5570 emitcode("orl","a,#0x%02x",
5571 (unsigned char)~SRMask[shCount]);
5572 emitcode("","%05d$:",tlbl->key+100);
5580 /*-----------------------------------------------------------------*/
5581 /* shiftR1Left2Result - shift right one byte from left to result */
5582 /*-----------------------------------------------------------------*/
5583 static void shiftR1Left2Result (operand *left, int offl,
5584 operand *result, int offr,
5585 int shCount, int sign)
5587 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5588 /* shift right accumulator */
5593 aopPut(AOP(result),"a",offr);
5599 /*-----------------------------------------------------------------*/
5600 /* shiftL1Left2Result - shift left one byte from left to result */
5601 /*-----------------------------------------------------------------*/
5602 static void shiftL1Left2Result (operand *left, int offl,
5603 operand *result, int offr, int shCount)
5606 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5608 /* shift left accumulator */
5610 aopPut(AOP(result),"a",offr);
5616 /*-----------------------------------------------------------------*/
5617 /* movLeft2Result - move byte from left to result */
5618 /*-----------------------------------------------------------------*/
5619 static void movLeft2Result (operand *left, int offl,
5620 operand *result, int offr, int sign)
5623 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5624 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5626 if (*l == '@' && (IS_AOP_PREG(result))) {
5627 emitcode("mov","a,%s",l);
5628 aopPut(AOP(result),"a",offr);
5631 aopPut(AOP(result),l,offr);
5633 /* MSB sign in acc.7 ! */
5634 if(getDataSize(left) == offl+1){
5635 emitcode("mov","a,%s",l);
5636 aopPut(AOP(result),"a",offr);
5646 /*-----------------------------------------------------------------*/
5647 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5648 /*-----------------------------------------------------------------*/
5649 static void AccAXRrl1 (char *x)
5651 emitcode("rrc","a");
5652 emitcode("xch","a,%s", x);
5653 emitcode("rrc","a");
5654 emitcode("xch","a,%s", x);
5660 /*-----------------------------------------------------------------*/
5661 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5662 /*-----------------------------------------------------------------*/
5663 static void AccAXLrl1 (char *x)
5665 emitcode("xch","a,%s",x);
5666 emitcode("rlc","a");
5667 emitcode("xch","a,%s",x);
5668 emitcode("rlc","a");
5674 /*-----------------------------------------------------------------*/
5675 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5676 /*-----------------------------------------------------------------*/
5677 static void AccAXLsh1 (char *x)
5679 emitcode("xch","a,%s",x);
5680 emitcode("add","a,acc");
5681 emitcode("xch","a,%s",x);
5682 emitcode("rlc","a");
5688 /*-----------------------------------------------------------------*/
5689 /* AccAXLsh - left shift a:x by known count (0..7) */
5690 /*-----------------------------------------------------------------*/
5691 static void AccAXLsh (char *x, int shCount)
5705 case 5 : // AAAAABBB:CCCCCDDD
5706 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5707 emitcode("anl","a,#0x%02x",
5708 SLMask[shCount]); // BBB00000:CCCCCDDD
5709 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5710 AccRol(shCount); // DDDCCCCC:BBB00000
5711 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5712 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5713 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5714 emitcode("anl","a,#0x%02x",
5715 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5716 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5717 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5719 case 6 : // AAAAAABB:CCCCCCDD
5720 emitcode("anl","a,#0x%02x",
5721 SRMask[shCount]); // 000000BB:CCCCCCDD
5722 emitcode("mov","c,acc.0"); // c = B
5723 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5724 AccAXRrl1(x); // BCCCCCCD:D000000B
5725 AccAXRrl1(x); // BBCCCCCC:DD000000
5727 case 7 : // a:x <<= 7
5728 emitcode("anl","a,#0x%02x",
5729 SRMask[shCount]); // 0000000B:CCCCCCCD
5730 emitcode("mov","c,acc.0"); // c = B
5731 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5732 AccAXRrl1(x); // BCCCCCCC:D0000000
5742 /*-----------------------------------------------------------------*/
5743 /* AccAXRsh - right shift a:x known count (0..7) */
5744 /*-----------------------------------------------------------------*/
5745 static void AccAXRsh (char *x, int shCount)
5752 AccAXRrl1(x); // 0->a:x
5756 AccAXRrl1(x); // 0->a:x
5758 AccAXRrl1(x); // 0->a:x
5762 case 5 : // AAAAABBB:CCCCCDDD = a:x
5763 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5764 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5765 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5766 emitcode("anl","a,#0x%02x",
5767 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5768 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5769 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5770 emitcode("anl","a,#0x%02x",
5771 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5772 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5773 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5774 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5776 case 6 : // AABBBBBB:CCDDDDDD
5777 emitcode("mov","c,acc.7");
5778 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5779 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5780 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5781 emitcode("anl","a,#0x%02x",
5782 SRMask[shCount]); // 000000AA:BBBBBBCC
5784 case 7 : // ABBBBBBB:CDDDDDDD
5785 emitcode("mov","c,acc.7"); // c = A
5786 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5787 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5788 emitcode("anl","a,#0x%02x",
5789 SRMask[shCount]); // 0000000A:BBBBBBBC
5799 /*-----------------------------------------------------------------*/
5800 /* AccAXRshS - right shift signed a:x known count (0..7) */
5801 /*-----------------------------------------------------------------*/
5802 static void AccAXRshS (char *x, int shCount)
5809 emitcode("mov","c,acc.7");
5810 AccAXRrl1(x); // s->a:x
5813 emitcode("mov","c,acc.7");
5814 AccAXRrl1(x); // s->a:x
5815 emitcode("mov","c,acc.7");
5816 AccAXRrl1(x); // s->a:x
5820 case 5 : // AAAAABBB:CCCCCDDD = a:x
5821 tlbl = newiTempLabel(NULL);
5822 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5823 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5824 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5825 emitcode("anl","a,#0x%02x",
5826 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5827 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5828 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5829 emitcode("anl","a,#0x%02x",
5830 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5831 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5832 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5833 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5834 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5835 emitcode("orl","a,#0x%02x",
5836 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5837 emitcode("","%05d$:",tlbl->key+100);
5838 break; // SSSSAAAA:BBBCCCCC
5839 case 6 : // AABBBBBB:CCDDDDDD
5840 tlbl = newiTempLabel(NULL);
5841 emitcode("mov","c,acc.7");
5842 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5843 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5844 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5845 emitcode("anl","a,#0x%02x",
5846 SRMask[shCount]); // 000000AA:BBBBBBCC
5847 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5848 emitcode("orl","a,#0x%02x",
5849 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5850 emitcode("","%05d$:",tlbl->key+100);
5852 case 7 : // ABBBBBBB:CDDDDDDD
5853 tlbl = newiTempLabel(NULL);
5854 emitcode("mov","c,acc.7"); // c = A
5855 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5856 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5857 emitcode("anl","a,#0x%02x",
5858 SRMask[shCount]); // 0000000A:BBBBBBBC
5859 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5860 emitcode("orl","a,#0x%02x",
5861 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5862 emitcode("","%05d$:",tlbl->key+100);
5872 /*-----------------------------------------------------------------*/
5873 /* shiftL2Left2Result - shift left two bytes from left to result */
5874 /*-----------------------------------------------------------------*/
5875 static void shiftL2Left2Result (operand *left, int offl,
5876 operand *result, int offr, int shCount)
5878 if(sameRegs(AOP(result), AOP(left)) &&
5879 ((offl + MSB16) == offr)){
5880 /* don't crash result[offr] */
5881 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5882 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5884 movLeft2Result(left,offl, result, offr, 0);
5885 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5887 /* ax << shCount (x = lsb(result))*/
5888 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5889 aopPut(AOP(result),"a",offr+MSB16);
5895 /*-----------------------------------------------------------------*/
5896 /* shiftR2Left2Result - shift right two bytes from left to result */
5897 /*-----------------------------------------------------------------*/
5898 static void shiftR2Left2Result (operand *left, int offl,
5899 operand *result, int offr,
5900 int shCount, int sign)
5902 if(sameRegs(AOP(result), AOP(left)) &&
5903 ((offl + MSB16) == offr)){
5904 /* don't crash result[offr] */
5905 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5906 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5908 movLeft2Result(left,offl, result, offr, 0);
5909 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5911 /* a:x >> shCount (x = lsb(result))*/
5913 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5915 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5916 if(getDataSize(result) > 1)
5917 aopPut(AOP(result),"a",offr+MSB16);
5923 /*-----------------------------------------------------------------*/
5924 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5925 /*-----------------------------------------------------------------*/
5926 static void shiftLLeftOrResult (operand *left, int offl,
5927 operand *result, int offr, int shCount)
5929 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5930 /* shift left accumulator */
5932 /* or with result */
5933 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5934 /* back to result */
5935 aopPut(AOP(result),"a",offr);
5941 /*-----------------------------------------------------------------*/
5942 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5943 /*-----------------------------------------------------------------*/
5944 static void shiftRLeftOrResult (operand *left, int offl,
5945 operand *result, int offr, int shCount)
5947 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5948 /* shift right accumulator */
5950 /* or with result */
5951 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5952 /* back to result */
5953 aopPut(AOP(result),"a",offr);
5959 /*-----------------------------------------------------------------*/
5960 /* genlshOne - left shift a one byte quantity by known count */
5961 /*-----------------------------------------------------------------*/
5962 static void genlshOne (operand *result, operand *left, int shCount)
5964 D(emitcode(";", "genlshOne "););
5965 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5971 /*-----------------------------------------------------------------*/
5972 /* genlshTwo - left shift two bytes by known amount != 0 */
5973 /*-----------------------------------------------------------------*/
5974 static void genlshTwo (operand *result,operand *left, int shCount)
5978 D(emitcode(";", "genlshTwo "););
5980 size = getDataSize(result);
5982 /* if shCount >= 8 */
5988 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5990 movLeft2Result(left, LSB, result, MSB16, 0);
5992 aopPut(AOP(result),zero,LSB);
5995 /* 1 <= shCount <= 7 */
5998 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6000 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6007 /*-----------------------------------------------------------------*/
6008 /* shiftLLong - shift left one long from left to result */
6009 /* offl = LSB or MSB16 */
6010 /*-----------------------------------------------------------------*/
6011 static void shiftLLong (operand *left, operand *result, int offr )
6014 int size = AOP_SIZE(result);
6016 if(size >= LSB+offr){
6017 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
6019 emitcode("add","a,acc");
6020 if (sameRegs(AOP(left),AOP(result)) &&
6021 size >= MSB16+offr && offr != LSB )
6022 emitcode("xch","a,%s",
6023 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
6025 aopPut(AOP(result),"a",LSB+offr);
6028 if(size >= MSB16+offr){
6029 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6030 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
6033 emitcode("rlc","a");
6034 if (sameRegs(AOP(left),AOP(result)) &&
6035 size >= MSB24+offr && offr != LSB)
6036 emitcode("xch","a,%s",
6037 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
6039 aopPut(AOP(result),"a",MSB16+offr);
6042 if(size >= MSB24+offr){
6043 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6044 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
6047 emitcode("rlc","a");
6048 if (sameRegs(AOP(left),AOP(result)) &&
6049 size >= MSB32+offr && offr != LSB )
6050 emitcode("xch","a,%s",
6051 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
6053 aopPut(AOP(result),"a",MSB24+offr);
6056 if(size > MSB32+offr){
6057 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6058 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
6061 emitcode("rlc","a");
6062 aopPut(AOP(result),"a",MSB32+offr);
6065 aopPut(AOP(result),zero,LSB);
6071 /*-----------------------------------------------------------------*/
6072 /* genlshFour - shift four byte by a known amount != 0 */
6073 /*-----------------------------------------------------------------*/
6074 static void genlshFour (operand *result, operand *left, int shCount)
6078 D(emitcode(";", "genlshFour "););
6080 size = AOP_SIZE(result);
6082 /* if shifting more that 3 bytes */
6083 if (shCount >= 24 ) {
6086 /* lowest order of left goes to the highest
6087 order of the destination */
6088 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6090 movLeft2Result(left, LSB, result, MSB32, 0);
6091 aopPut(AOP(result),zero,LSB);
6092 aopPut(AOP(result),zero,MSB16);
6093 aopPut(AOP(result),zero,MSB32);
6097 /* more than two bytes */
6098 else if ( shCount >= 16 ) {
6099 /* lower order two bytes goes to higher order two bytes */
6101 /* if some more remaining */
6103 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6105 movLeft2Result(left, MSB16, result, MSB32, 0);
6106 movLeft2Result(left, LSB, result, MSB24, 0);
6108 aopPut(AOP(result),zero,MSB16);
6109 aopPut(AOP(result),zero,LSB);
6113 /* if more than 1 byte */
6114 else if ( shCount >= 8 ) {
6115 /* lower order three bytes goes to higher order three bytes */
6119 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6121 movLeft2Result(left, LSB, result, MSB16, 0);
6123 else{ /* size = 4 */
6125 movLeft2Result(left, MSB24, result, MSB32, 0);
6126 movLeft2Result(left, MSB16, result, MSB24, 0);
6127 movLeft2Result(left, LSB, result, MSB16, 0);
6128 aopPut(AOP(result),zero,LSB);
6130 else if(shCount == 1)
6131 shiftLLong(left, result, MSB16);
6133 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6134 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6135 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6136 aopPut(AOP(result),zero,LSB);
6141 /* 1 <= shCount <= 7 */
6142 else if(shCount <= 2){
6143 shiftLLong(left, result, LSB);
6145 shiftLLong(result, result, LSB);
6147 /* 3 <= shCount <= 7, optimize */
6149 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6150 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6151 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6158 /*-----------------------------------------------------------------*/
6159 /* genLeftShiftLiteral - left shifting by known count */
6160 /*-----------------------------------------------------------------*/
6161 static void genLeftShiftLiteral (operand *left,
6166 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6169 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
6171 freeAsmop(right,NULL,ic,TRUE);
6173 aopOp(left,ic,FALSE, FALSE);
6174 aopOp(result,ic,FALSE, TRUE);
6176 size = getSize(operandType(result));
6179 emitcode("; shift left ","result %d, left %d",size,
6183 /* I suppose that the left size >= result size */
6186 movLeft2Result(left, size, result, size, 0);
6190 else if(shCount >= (size * 8))
6192 aopPut(AOP(result),zero,size);
6196 genlshOne (result,left,shCount);
6200 case 3: /* bug: this is for generic pointers, I bet. */
6201 genlshTwo (result,left,shCount);
6205 genlshFour (result,left,shCount);
6209 freeAsmop(left,NULL,ic,TRUE);
6210 freeAsmop(result,NULL,ic,TRUE);
6214 /*-----------------------------------------------------------------*/
6215 /* genLeftShift - generates code for left shifting */
6216 /*-----------------------------------------------------------------*/
6217 static void genLeftShift (iCode *ic)
6219 operand *left,*right, *result;
6222 symbol *tlbl , *tlbl1;
6224 D(emitcode(";", "genLeftShift "););
6226 right = IC_RIGHT(ic);
6228 result = IC_RESULT(ic);
6230 aopOp(right,ic,FALSE, FALSE);
6233 /* if the shift count is known then do it
6234 as efficiently as possible */
6235 if (AOP_TYPE(right) == AOP_LIT) {
6236 genLeftShiftLiteral (left,right,result,ic);
6241 /* shift count is unknown then we have to form
6242 a loop get the loop count in B : Note: we take
6243 only the lower order byte since shifting
6244 more that 32 bits make no sense anyway, ( the
6245 largest size of an object can be only 32 bits ) */
6247 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6248 emitcode("inc","b");
6249 freeAsmop (right,NULL,ic,TRUE);
6250 aopOp(left,ic,FALSE, FALSE);
6251 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6253 /* now move the left to the result if they are not the
6255 if (!sameRegs(AOP(left),AOP(result)) &&
6256 AOP_SIZE(result) > 1) {
6258 size = AOP_SIZE(result);
6260 _startLazyDPSEvaluation();
6262 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6263 if (*l == '@' && (IS_AOP_PREG(result))) {
6265 emitcode("mov","a,%s",l);
6266 aopPut(AOP(result),"a",offset);
6268 aopPut(AOP(result),l,offset);
6271 _endLazyDPSEvaluation();
6274 tlbl = newiTempLabel(NULL);
6275 size = AOP_SIZE(result);
6277 tlbl1 = newiTempLabel(NULL);
6279 /* if it is only one byte then */
6281 symbol *tlbl1 = newiTempLabel(NULL);
6283 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6285 emitcode("sjmp","%05d$",tlbl1->key+100);
6286 emitcode("","%05d$:",tlbl->key+100);
6287 emitcode("add","a,acc");
6288 emitcode("","%05d$:",tlbl1->key+100);
6289 emitcode("djnz","b,%05d$",tlbl->key+100);
6290 aopPut(AOP(result),"a",0);
6294 reAdjustPreg(AOP(result));
6296 emitcode("sjmp","%05d$",tlbl1->key+100);
6297 emitcode("","%05d$:",tlbl->key+100);
6298 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6300 emitcode("add","a,acc");
6301 aopPut(AOP(result),"a",offset++);
6302 _startLazyDPSEvaluation();
6304 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6306 emitcode("rlc","a");
6307 aopPut(AOP(result),"a",offset++);
6309 _endLazyDPSEvaluation();
6310 reAdjustPreg(AOP(result));
6312 emitcode("","%05d$:",tlbl1->key+100);
6313 emitcode("djnz","b,%05d$",tlbl->key+100);
6315 freeAsmop(left,NULL,ic,TRUE);
6316 freeAsmop(result,NULL,ic,TRUE);
6321 /*-----------------------------------------------------------------*/
6322 /* genrshOne - right shift a one byte quantity by known count */
6323 /*-----------------------------------------------------------------*/
6324 static void genrshOne (operand *result, operand *left,
6325 int shCount, int sign)
6327 D(emitcode(";", "genrshOne"););
6328 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6334 /*-----------------------------------------------------------------*/
6335 /* genrshTwo - right shift two bytes by known amount != 0 */
6336 /*-----------------------------------------------------------------*/
6337 static void genrshTwo (operand *result,operand *left,
6338 int shCount, int sign)
6340 D(emitcode(";", "genrshTwo"););
6342 /* if shCount >= 8 */
6346 shiftR1Left2Result(left, MSB16, result, LSB,
6349 movLeft2Result(left, MSB16, result, LSB, sign);
6350 addSign(result, MSB16, sign);
6353 /* 1 <= shCount <= 7 */
6355 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6361 /*-----------------------------------------------------------------*/
6362 /* shiftRLong - shift right one long from left to result */
6363 /* offl = LSB or MSB16 */
6364 /*-----------------------------------------------------------------*/
6365 static void shiftRLong (operand *left, int offl,
6366 operand *result, int sign)
6369 emitcode("clr","c");
6370 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6372 emitcode("mov","c,acc.7");
6373 emitcode("rrc","a");
6374 aopPut(AOP(result),"a",MSB32-offl);
6376 /* add sign of "a" */
6377 addSign(result, MSB32, sign);
6379 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6380 emitcode("rrc","a");
6381 aopPut(AOP(result),"a",MSB24-offl);
6383 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6384 emitcode("rrc","a");
6385 aopPut(AOP(result),"a",MSB16-offl);
6388 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6389 emitcode("rrc","a");
6390 aopPut(AOP(result),"a",LSB);
6397 /*-----------------------------------------------------------------*/
6398 /* genrshFour - shift four byte by a known amount != 0 */
6399 /*-----------------------------------------------------------------*/
6400 static void genrshFour (operand *result, operand *left,
6401 int shCount, int sign)
6403 D(emitcode(";", "genrshFour"););
6405 /* if shifting more that 3 bytes */
6406 if(shCount >= 24 ) {
6409 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6411 movLeft2Result(left, MSB32, result, LSB, sign);
6412 addSign(result, MSB16, sign);
6414 else if(shCount >= 16){
6417 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6419 movLeft2Result(left, MSB24, result, LSB, 0);
6420 movLeft2Result(left, MSB32, result, MSB16, sign);
6422 addSign(result, MSB24, sign);
6424 else if(shCount >= 8){
6427 shiftRLong(left, MSB16, result, sign);
6428 else if(shCount == 0){
6429 movLeft2Result(left, MSB16, result, LSB, 0);
6430 movLeft2Result(left, MSB24, result, MSB16, 0);
6431 movLeft2Result(left, MSB32, result, MSB24, sign);
6432 addSign(result, MSB32, sign);
6435 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6436 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6437 /* the last shift is signed */
6438 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6439 addSign(result, MSB32, sign);
6442 else{ /* 1 <= shCount <= 7 */
6444 shiftRLong(left, LSB, result, sign);
6446 shiftRLong(result, LSB, result, sign);
6449 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6450 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6451 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6459 /*-----------------------------------------------------------------*/
6460 /* genRightShiftLiteral - right shifting by known count */
6461 /*-----------------------------------------------------------------*/
6462 static void genRightShiftLiteral (operand *left,
6468 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6471 D(emitcode(";", "genRightShiftLiteral"););
6473 freeAsmop(right,NULL,ic,TRUE);
6475 aopOp(left,ic,FALSE, FALSE);
6476 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6479 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6483 size = getDataSize(left);
6484 /* test the LEFT size !!! */
6486 /* I suppose that the left size >= result size */
6488 size = getDataSize(result);
6490 movLeft2Result(left, size, result, size, 0);
6493 else if(shCount >= (size * 8)){
6495 /* get sign in acc.7 */
6496 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6497 addSign(result, LSB, sign);
6501 genrshOne (result,left,shCount,sign);
6505 genrshTwo (result,left,shCount,sign);
6509 genrshFour (result,left,shCount,sign);
6515 freeAsmop(left,NULL,ic,TRUE);
6516 freeAsmop(result,NULL,ic,TRUE);
6521 /*-----------------------------------------------------------------*/
6522 /* genSignedRightShift - right shift of signed number */
6523 /*-----------------------------------------------------------------*/
6524 static void genSignedRightShift (iCode *ic)
6526 operand *right, *left, *result;
6529 symbol *tlbl, *tlbl1 ;
6531 D(emitcode(";", "genSignedRightShift "););
6533 /* we do it the hard way put the shift count in b
6534 and loop thru preserving the sign */
6536 right = IC_RIGHT(ic);
6538 result = IC_RESULT(ic);
6540 aopOp(right,ic,FALSE, FALSE);
6543 if ( AOP_TYPE(right) == AOP_LIT) {
6544 genRightShiftLiteral (left,right,result,ic,1);
6548 /* shift count is unknown then we have to form
6549 a loop get the loop count in B : Note: we take
6550 only the lower order byte since shifting
6551 more that 32 bits make no sense anyway, ( the
6552 largest size of an object can be only 32 bits ) */
6554 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6555 emitcode("inc","b");
6556 freeAsmop (right,NULL,ic,TRUE);
6557 aopOp(left,ic,FALSE, FALSE);
6558 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6560 /* now move the left to the result if they are not the
6562 if (!sameRegs(AOP(left),AOP(result)) &&
6563 AOP_SIZE(result) > 1) {
6565 size = AOP_SIZE(result);
6567 _startLazyDPSEvaluation();
6569 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6570 if (*l == '@' && IS_AOP_PREG(result)) {
6572 emitcode("mov","a,%s",l);
6573 aopPut(AOP(result),"a",offset);
6575 aopPut(AOP(result),l,offset);
6578 _endLazyDPSEvaluation();
6581 /* mov the highest order bit to OVR */
6582 tlbl = newiTempLabel(NULL);
6583 tlbl1= newiTempLabel(NULL);
6585 size = AOP_SIZE(result);
6587 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6588 emitcode("rlc","a");
6589 emitcode("mov","ov,c");
6590 /* if it is only one byte then */
6592 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6594 emitcode("sjmp","%05d$",tlbl1->key+100);
6595 emitcode("","%05d$:",tlbl->key+100);
6596 emitcode("mov","c,ov");
6597 emitcode("rrc","a");
6598 emitcode("","%05d$:",tlbl1->key+100);
6599 emitcode("djnz","b,%05d$",tlbl->key+100);
6600 aopPut(AOP(result),"a",0);
6604 reAdjustPreg(AOP(result));
6605 emitcode("sjmp","%05d$",tlbl1->key+100);
6606 emitcode("","%05d$:",tlbl->key+100);
6607 emitcode("mov","c,ov");
6608 _startLazyDPSEvaluation();
6610 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6612 emitcode("rrc","a");
6613 aopPut(AOP(result),"a",offset--);
6615 _endLazyDPSEvaluation();
6616 reAdjustPreg(AOP(result));
6617 emitcode("","%05d$:",tlbl1->key+100);
6618 emitcode("djnz","b,%05d$",tlbl->key+100);
6621 freeAsmop(left,NULL,ic,TRUE);
6622 freeAsmop(result,NULL,ic,TRUE);
6625 /*-----------------------------------------------------------------*/
6626 /* genRightShift - generate code for right shifting */
6627 /*-----------------------------------------------------------------*/
6628 static void genRightShift (iCode *ic)
6630 operand *right, *left, *result;
6634 symbol *tlbl, *tlbl1 ;
6636 D(emitcode(";", "genRightShift "););
6638 /* if signed then we do it the hard way preserve the
6639 sign bit moving it inwards */
6640 retype = getSpec(operandType(IC_RESULT(ic)));
6642 if (!SPEC_USIGN(retype)) {
6643 genSignedRightShift (ic);
6647 /* signed & unsigned types are treated the same : i.e. the
6648 signed is NOT propagated inwards : quoting from the
6649 ANSI - standard : "for E1 >> E2, is equivalent to division
6650 by 2**E2 if unsigned or if it has a non-negative value,
6651 otherwise the result is implementation defined ", MY definition
6652 is that the sign does not get propagated */
6654 right = IC_RIGHT(ic);
6656 result = IC_RESULT(ic);
6658 aopOp(right,ic,FALSE, FALSE);
6661 /* if the shift count is known then do it
6662 as efficiently as possible */
6663 if (AOP_TYPE(right) == AOP_LIT) {
6664 genRightShiftLiteral (left,right,result,ic, 0);
6669 /* shift count is unknown then we have to form
6670 a loop get the loop count in B : Note: we take
6671 only the lower order byte since shifting
6672 more that 32 bits make no sense anyway, ( the
6673 largest size of an object can be only 32 bits ) */
6675 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6676 emitcode("inc","b");
6677 freeAsmop (right,NULL,ic,TRUE);
6678 aopOp(left,ic,FALSE, FALSE);
6679 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6681 /* now move the left to the result if they are not the
6683 if (!sameRegs(AOP(left),AOP(result)) &&
6684 AOP_SIZE(result) > 1) {
6686 size = AOP_SIZE(result);
6688 _startLazyDPSEvaluation();
6690 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6691 if (*l == '@' && IS_AOP_PREG(result)) {
6693 emitcode("mov","a,%s",l);
6694 aopPut(AOP(result),"a",offset);
6696 aopPut(AOP(result),l,offset);
6699 _endLazyDPSEvaluation();
6702 tlbl = newiTempLabel(NULL);
6703 tlbl1= newiTempLabel(NULL);
6704 size = AOP_SIZE(result);
6707 /* if it is only one byte then */
6709 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6711 emitcode("sjmp","%05d$",tlbl1->key+100);
6712 emitcode("","%05d$:",tlbl->key+100);
6714 emitcode("rrc","a");
6715 emitcode("","%05d$:",tlbl1->key+100);
6716 emitcode("djnz","b,%05d$",tlbl->key+100);
6717 aopPut(AOP(result),"a",0);
6721 reAdjustPreg(AOP(result));
6722 emitcode("sjmp","%05d$",tlbl1->key+100);
6723 emitcode("","%05d$:",tlbl->key+100);
6725 _startLazyDPSEvaluation();
6727 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6729 emitcode("rrc","a");
6730 aopPut(AOP(result),"a",offset--);
6732 _endLazyDPSEvaluation();
6733 reAdjustPreg(AOP(result));
6735 emitcode("","%05d$:",tlbl1->key+100);
6736 emitcode("djnz","b,%05d$",tlbl->key+100);
6739 freeAsmop(left,NULL,ic,TRUE);
6740 freeAsmop(result,NULL,ic,TRUE);
6743 /*-----------------------------------------------------------------*/
6744 /* genUnpackBits - generates code for unpacking bits */
6745 /*-----------------------------------------------------------------*/
6746 static void genUnpackBits (operand *result, char *rname, int ptype)
6753 D(emitcode(";", "genUnpackBits "););
6755 etype = getSpec(operandType(result));
6757 /* read the first byte */
6762 emitcode("mov","a,@%s",rname);
6766 emitcode("movx","a,@%s",rname);
6770 emitcode("movx","a,@dptr");
6774 emitcode("clr","a");
6775 emitcode("movc","a","@a+dptr");
6779 emitcode("lcall","__gptrget");
6783 /* if we have bitdisplacement then it fits */
6784 /* into this byte completely or if length is */
6785 /* less than a byte */
6786 if ((shCnt = SPEC_BSTR(etype)) ||
6787 (SPEC_BLEN(etype) <= 8)) {
6789 /* shift right acc */
6792 emitcode("anl","a,#0x%02x",
6793 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6794 aopPut(AOP(result),"a",offset);
6798 /* bit field did not fit in a byte */
6799 rlen = SPEC_BLEN(etype) - 8;
6800 aopPut(AOP(result),"a",offset++);
6807 emitcode("inc","%s",rname);
6808 emitcode("mov","a,@%s",rname);
6812 emitcode("inc","%s",rname);
6813 emitcode("movx","a,@%s",rname);
6817 emitcode("inc","dptr");
6818 emitcode("movx","a,@dptr");
6822 emitcode("clr","a");
6823 emitcode("inc","dptr");
6824 emitcode("movc","a","@a+dptr");
6828 emitcode("inc","dptr");
6829 emitcode("lcall","__gptrget");
6834 /* if we are done */
6838 aopPut(AOP(result),"a",offset++);
6843 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6844 aopPut(AOP(result),"a",offset);
6851 /*-----------------------------------------------------------------*/
6852 /* genDataPointerGet - generates code when ptr offset is known */
6853 /*-----------------------------------------------------------------*/
6854 static void genDataPointerGet (operand *left,
6860 int size , offset = 0;
6861 aopOp(result,ic,TRUE, FALSE);
6863 /* get the string representation of the name */
6864 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6865 size = AOP_SIZE(result);
6866 _startLazyDPSEvaluation();
6869 sprintf(buffer,"(%s + %d)",l+1,offset);
6871 sprintf(buffer,"%s",l+1);
6872 aopPut(AOP(result),buffer,offset++);
6874 _endLazyDPSEvaluation();
6876 freeAsmop(left,NULL,ic,TRUE);
6877 freeAsmop(result,NULL,ic,TRUE);
6880 /*-----------------------------------------------------------------*/
6881 /* genNearPointerGet - emitcode for near pointer fetch */
6882 /*-----------------------------------------------------------------*/
6883 static void genNearPointerGet (operand *left,
6890 sym_link *rtype, *retype, *letype;
6891 sym_link *ltype = operandType(left);
6894 rtype = operandType(result);
6895 retype= getSpec(rtype);
6896 letype= getSpec(ltype);
6898 aopOp(left,ic,FALSE, FALSE);
6900 /* if left is rematerialisable and
6901 result is not bit variable type and
6902 the left is pointer to data space i.e
6903 lower 128 bytes of space */
6904 if (AOP_TYPE(left) == AOP_IMMD &&
6905 !IS_BITVAR(retype) &&
6906 !IS_BITVAR(letype) &&
6907 DCL_TYPE(ltype) == POINTER) {
6908 genDataPointerGet (left,result,ic);
6912 /* if the value is already in a pointer register
6913 then don't need anything more */
6914 if (!AOP_INPREG(AOP(left))) {
6915 /* otherwise get a free pointer register */
6917 preg = getFreePtr(ic,&aop,FALSE);
6918 emitcode("mov","%s,%s",
6920 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6921 rname = preg->name ;
6923 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6925 freeAsmop(left,NULL,ic,TRUE);
6926 aopOp (result,ic,FALSE, FALSE);
6928 /* if bitfield then unpack the bits */
6929 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6930 genUnpackBits (result,rname,POINTER);
6932 /* we have can just get the values */
6933 int size = AOP_SIZE(result);
6937 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6939 emitcode("mov","a,@%s",rname);
6940 aopPut(AOP(result),"a",offset);
6942 sprintf(buffer,"@%s",rname);
6943 aopPut(AOP(result),buffer,offset);
6947 emitcode("inc","%s",rname);
6951 /* now some housekeeping stuff */
6953 /* we had to allocate for this iCode */
6954 freeAsmop(NULL,aop,ic,TRUE);
6956 /* we did not allocate which means left
6957 already in a pointer register, then
6958 if size > 0 && this could be used again
6959 we have to point it back to where it
6961 if (AOP_SIZE(result) > 1 &&
6962 !OP_SYMBOL(left)->remat &&
6963 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6965 int size = AOP_SIZE(result) - 1;
6967 emitcode("dec","%s",rname);
6972 freeAsmop(result,NULL,ic,TRUE);
6976 /*-----------------------------------------------------------------*/
6977 /* genPagedPointerGet - emitcode for paged pointer fetch */
6978 /*-----------------------------------------------------------------*/
6979 static void genPagedPointerGet (operand *left,
6986 sym_link *rtype, *retype, *letype;
6988 rtype = operandType(result);
6989 retype= getSpec(rtype);
6990 letype= getSpec(operandType(left));
6991 aopOp(left,ic,FALSE, FALSE);
6993 /* if the value is already in a pointer register
6994 then don't need anything more */
6995 if (!AOP_INPREG(AOP(left))) {
6996 /* otherwise get a free pointer register */
6998 preg = getFreePtr(ic,&aop,FALSE);
6999 emitcode("mov","%s,%s",
7001 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
7002 rname = preg->name ;
7004 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
7006 freeAsmop(left,NULL,ic,TRUE);
7007 aopOp (result,ic,FALSE, FALSE);
7009 /* if bitfield then unpack the bits */
7010 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7011 genUnpackBits (result,rname,PPOINTER);
7013 /* we have can just get the values */
7014 int size = AOP_SIZE(result);
7019 emitcode("movx","a,@%s",rname);
7020 aopPut(AOP(result),"a",offset);
7025 emitcode("inc","%s",rname);
7029 /* now some housekeeping stuff */
7031 /* we had to allocate for this iCode */
7032 freeAsmop(NULL,aop,ic,TRUE);
7034 /* we did not allocate which means left
7035 already in a pointer register, then
7036 if size > 0 && this could be used again
7037 we have to point it back to where it
7039 if (AOP_SIZE(result) > 1 &&
7040 !OP_SYMBOL(left)->remat &&
7041 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7043 int size = AOP_SIZE(result) - 1;
7045 emitcode("dec","%s",rname);
7050 freeAsmop(result,NULL,ic,TRUE);
7055 /*-----------------------------------------------------------------*/
7056 /* genFarPointerGet - gget value from far space */
7057 /*-----------------------------------------------------------------*/
7058 static void genFarPointerGet (operand *left,
7059 operand *result, iCode *ic)
7062 sym_link *retype = getSpec(operandType(result));
7063 sym_link *letype = getSpec(operandType(left));
7064 D(emitcode(";", "genFarPointerGet"););
7066 aopOp(left,ic,FALSE, FALSE);
7068 /* if the operand is already in dptr
7069 then we do nothing else we move the value to dptr */
7070 if (AOP_TYPE(left) != AOP_STR) {
7071 /* if this is remateriazable */
7072 if (AOP_TYPE(left) == AOP_IMMD)
7074 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7078 /* we need to get it byte by byte */
7079 _startLazyDPSEvaluation();
7080 if (AOP_TYPE(left) != AOP_DPTR)
7082 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7083 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7084 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7088 /* We need to generate a load to DPTR indirect through DPTR. */
7089 D(emitcode(";", "genFarPointerGet -- indirection special case."););
7090 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7091 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7092 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7093 emitcode("pop", "dph");
7094 emitcode("pop", "dpl");
7096 _endLazyDPSEvaluation();
7099 /* so dptr know contains the address */
7100 freeAsmop(left,NULL,ic,TRUE);
7101 aopOp(result,ic,FALSE, TRUE);
7103 /* if bit then unpack */
7104 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7105 genUnpackBits(result,"dptr",FPOINTER);
7107 size = AOP_SIZE(result);
7110 _startLazyDPSEvaluation();
7116 emitcode("movx","a,@dptr");
7118 emitcode("inc","dptr");
7120 aopPut(AOP(result),"a",offset++);
7122 _endLazyDPSEvaluation();
7125 freeAsmop(result,NULL,ic,TRUE);
7128 /*-----------------------------------------------------------------*/
7129 /* emitcodePointerGet - gget value from code space */
7130 /*-----------------------------------------------------------------*/
7131 static void emitcodePointerGet (operand *left,
7132 operand *result, iCode *ic)
7135 sym_link *retype = getSpec(operandType(result));
7137 aopOp(left,ic,FALSE, FALSE);
7139 /* if the operand is already in dptr
7140 then we do nothing else we move the value to dptr */
7141 if (AOP_TYPE(left) != AOP_STR) {
7142 /* if this is remateriazable */
7143 if (AOP_TYPE(left) == AOP_IMMD)
7145 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7148 { /* we need to get it byte by byte */
7149 _startLazyDPSEvaluation();
7150 if (AOP_TYPE(left) != AOP_DPTR)
7152 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7153 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7154 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7158 /* We need to generate a load to DPTR indirect through DPTR. */
7159 D(emitcode(";", "gencodePointerGet -- indirection special case."););
7160 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7161 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7162 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7163 emitcode("pop", "dph");
7164 emitcode("pop", "dpl");
7166 _endLazyDPSEvaluation();
7169 /* so dptr know contains the address */
7170 freeAsmop(left,NULL,ic,TRUE);
7171 aopOp(result,ic,FALSE, TRUE);
7173 /* if bit then unpack */
7174 if (IS_BITVAR(retype))
7175 genUnpackBits(result,"dptr",CPOINTER);
7177 size = AOP_SIZE(result);
7180 _startLazyDPSEvaluation();
7186 emitcode("clr","a");
7187 emitcode("movc","a,@a+dptr");
7189 emitcode("inc","dptr");
7190 aopPut(AOP(result),"a",offset++);
7192 _endLazyDPSEvaluation();
7195 freeAsmop(result,NULL,ic,TRUE);
7198 /*-----------------------------------------------------------------*/
7199 /* genGenPointerGet - gget value from generic pointer space */
7200 /*-----------------------------------------------------------------*/
7201 static void genGenPointerGet (operand *left,
7202 operand *result, iCode *ic)
7205 sym_link *retype = getSpec(operandType(result));
7206 sym_link *letype = getSpec(operandType(left));
7208 aopOp(left,ic,FALSE, TRUE);
7210 /* if the operand is already in dptr
7211 then we do nothing else we move the value to dptr */
7212 if (AOP_TYPE(left) != AOP_STR) {
7213 /* if this is remateriazable */
7214 if (AOP_TYPE(left) == AOP_IMMD) {
7215 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7216 emitcode("mov","b,#%d",pointerCode(retype));
7218 else { /* we need to get it byte by byte */
7219 _startLazyDPSEvaluation();
7220 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7221 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7222 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7223 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7224 _endLazyDPSEvaluation();
7227 /* so dptr know contains the address */
7228 freeAsmop(left,NULL,ic,TRUE);
7229 aopOp(result,ic,FALSE, TRUE);
7231 /* if bit then unpack */
7232 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7233 genUnpackBits(result,"dptr",GPOINTER);
7235 size = AOP_SIZE(result);
7239 emitcode("lcall","__gptrget");
7240 aopPut(AOP(result),"a",offset++);
7242 emitcode("inc","dptr");
7246 freeAsmop(result,NULL,ic,TRUE);
7249 /*-----------------------------------------------------------------*/
7250 /* genPointerGet - generate code for pointer get */
7251 /*-----------------------------------------------------------------*/
7252 static void genPointerGet (iCode *ic)
7254 operand *left, *result ;
7255 sym_link *type, *etype;
7258 D(emitcode(";", "genPointerGet "););
7261 result = IC_RESULT(ic) ;
7263 /* depending on the type of pointer we need to
7264 move it to the correct pointer register */
7265 type = operandType(left);
7266 etype = getSpec(type);
7267 /* if left is of type of pointer then it is simple */
7268 if (IS_PTR(type) && !IS_FUNC(type->next))
7269 p_type = DCL_TYPE(type);
7271 /* we have to go by the storage class */
7272 p_type = PTR_TYPE(SPEC_OCLS(etype));
7275 /* now that we have the pointer type we assign
7276 the pointer values */
7281 genNearPointerGet (left,result,ic);
7285 genPagedPointerGet(left,result,ic);
7289 genFarPointerGet (left,result,ic);
7293 emitcodePointerGet (left,result,ic);
7297 genGenPointerGet (left,result,ic);
7303 /*-----------------------------------------------------------------*/
7304 /* genPackBits - generates code for packed bit storage */
7305 /*-----------------------------------------------------------------*/
7306 static void genPackBits (sym_link *etype ,
7308 char *rname, int p_type)
7316 blen = SPEC_BLEN(etype);
7317 bstr = SPEC_BSTR(etype);
7319 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7322 /* if the bit lenth is less than or */
7323 /* it exactly fits a byte then */
7324 if (SPEC_BLEN(etype) <= 8 ) {
7325 shCount = SPEC_BSTR(etype) ;
7327 /* shift left acc */
7330 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7335 emitcode ("mov","b,a");
7336 emitcode("mov","a,@%s",rname);
7340 emitcode ("mov","b,a");
7341 emitcode("movx","a,@dptr");
7345 emitcode ("push","b");
7346 emitcode ("push","acc");
7347 emitcode ("lcall","__gptrget");
7348 emitcode ("pop","b");
7352 emitcode ("anl","a,#0x%02x",(unsigned char)
7353 ((unsigned char)(0xFF << (blen+bstr)) |
7354 (unsigned char)(0xFF >> (8-bstr)) ) );
7355 emitcode ("orl","a,b");
7356 if (p_type == GPOINTER)
7357 emitcode("pop","b");
7363 emitcode("mov","@%s,a",rname);
7367 emitcode("movx","@dptr,a");
7371 emitcode("lcall","__gptrput");
7376 if ( SPEC_BLEN(etype) <= 8 )
7379 emitcode("inc","%s",rname);
7380 rLen = SPEC_BLEN(etype) ;
7382 /* now generate for lengths greater than one byte */
7385 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7395 emitcode("mov","@%s,a",rname);
7397 emitcode("mov","@%s,%s",rname,l);
7402 emitcode("movx","@dptr,a");
7407 emitcode("lcall","__gptrput");
7410 emitcode ("inc","%s",rname);
7415 /* last last was not complete */
7417 /* save the byte & read byte */
7420 emitcode ("mov","b,a");
7421 emitcode("mov","a,@%s",rname);
7425 emitcode ("mov","b,a");
7426 emitcode("movx","a,@dptr");
7430 emitcode ("push","b");
7431 emitcode ("push","acc");
7432 emitcode ("lcall","__gptrget");
7433 emitcode ("pop","b");
7437 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << rLen) );
7438 emitcode ("orl","a,b");
7441 if (p_type == GPOINTER)
7442 emitcode("pop","b");
7447 emitcode("mov","@%s,a",rname);
7451 emitcode("movx","@dptr,a");
7455 emitcode("lcall","__gptrput");
7459 /*-----------------------------------------------------------------*/
7460 /* genDataPointerSet - remat pointer to data space */
7461 /*-----------------------------------------------------------------*/
7462 static void genDataPointerSet(operand *right,
7466 int size, offset = 0 ;
7467 char *l, buffer[256];
7469 aopOp(right,ic,FALSE, FALSE);
7471 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7472 size = AOP_SIZE(right);
7475 sprintf(buffer,"(%s + %d)",l+1,offset);
7477 sprintf(buffer,"%s",l+1);
7478 emitcode("mov","%s,%s",buffer,
7479 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7482 freeAsmop(right,NULL,ic,TRUE);
7483 freeAsmop(result,NULL,ic,TRUE);
7486 /*-----------------------------------------------------------------*/
7487 /* genNearPointerSet - emitcode for near pointer put */
7488 /*-----------------------------------------------------------------*/
7489 static void genNearPointerSet (operand *right,
7496 sym_link *retype, *letype;
7497 sym_link *ptype = operandType(result);
7499 retype= getSpec(operandType(right));
7500 letype= getSpec(ptype);
7502 aopOp(result,ic,FALSE, FALSE);
7504 /* if the result is rematerializable &
7505 in data space & not a bit variable */
7506 if (AOP_TYPE(result) == AOP_IMMD &&
7507 DCL_TYPE(ptype) == POINTER &&
7508 !IS_BITVAR(retype) &&
7509 !IS_BITVAR(letype)) {
7510 genDataPointerSet (right,result,ic);
7514 /* if the value is already in a pointer register
7515 then don't need anything more */
7516 if (!AOP_INPREG(AOP(result))) {
7517 /* otherwise get a free pointer register */
7519 preg = getFreePtr(ic,&aop,FALSE);
7520 emitcode("mov","%s,%s",
7522 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7523 rname = preg->name ;
7525 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7527 freeAsmop(result,NULL,ic,TRUE);
7528 aopOp (right,ic,FALSE, FALSE);
7530 /* if bitfield then unpack the bits */
7531 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7532 genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
7534 /* we have can just get the values */
7535 int size = AOP_SIZE(right);
7539 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7542 emitcode("mov","@%s,a",rname);
7544 emitcode("mov","@%s,%s",rname,l);
7546 emitcode("inc","%s",rname);
7551 /* now some housekeeping stuff */
7553 /* we had to allocate for this iCode */
7554 freeAsmop(NULL,aop,ic,TRUE);
7556 /* we did not allocate which means left
7557 already in a pointer register, then
7558 if size > 0 && this could be used again
7559 we have to point it back to where it
7561 if (AOP_SIZE(right) > 1 &&
7562 !OP_SYMBOL(result)->remat &&
7563 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7565 int size = AOP_SIZE(right) - 1;
7567 emitcode("dec","%s",rname);
7572 freeAsmop(right,NULL,ic,TRUE);
7577 /*-----------------------------------------------------------------*/
7578 /* genPagedPointerSet - emitcode for Paged pointer put */
7579 /*-----------------------------------------------------------------*/
7580 static void genPagedPointerSet (operand *right,
7587 sym_link *retype, *letype;
7589 retype= getSpec(operandType(right));
7590 letype= getSpec(operandType(result));
7592 aopOp(result,ic,FALSE, FALSE);
7594 /* if the value is already in a pointer register
7595 then don't need anything more */
7596 if (!AOP_INPREG(AOP(result))) {
7597 /* otherwise get a free pointer register */
7599 preg = getFreePtr(ic,&aop,FALSE);
7600 emitcode("mov","%s,%s",
7602 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7603 rname = preg->name ;
7605 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7607 freeAsmop(result,NULL,ic,TRUE);
7608 aopOp (right,ic,FALSE, FALSE);
7610 /* if bitfield then unpack the bits */
7611 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7612 genPackBits ((IS_BITVAR(retype) ? retype : letype) ,right,rname,PPOINTER);
7614 /* we have can just get the values */
7615 int size = AOP_SIZE(right);
7619 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7622 emitcode("movx","@%s,a",rname);
7625 emitcode("inc","%s",rname);
7631 /* now some housekeeping stuff */
7633 /* we had to allocate for this iCode */
7634 freeAsmop(NULL,aop,ic,TRUE);
7636 /* we did not allocate which means left
7637 already in a pointer register, then
7638 if size > 0 && this could be used again
7639 we have to point it back to where it
7641 if (AOP_SIZE(right) > 1 &&
7642 !OP_SYMBOL(result)->remat &&
7643 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7645 int size = AOP_SIZE(right) - 1;
7647 emitcode("dec","%s",rname);
7652 freeAsmop(right,NULL,ic,TRUE);
7657 /*-----------------------------------------------------------------*/
7658 /* genFarPointerSet - set value from far space */
7659 /*-----------------------------------------------------------------*/
7660 static void genFarPointerSet (operand *right,
7661 operand *result, iCode *ic)
7664 sym_link *retype = getSpec(operandType(right));
7665 sym_link *letype = getSpec(operandType(result));
7667 aopOp(result,ic,FALSE, FALSE);
7669 /* if the operand is already in dptr
7670 then we do nothing else we move the value to dptr */
7671 if (AOP_TYPE(result) != AOP_STR) {
7672 /* if this is remateriazable */
7673 if (AOP_TYPE(result) == AOP_IMMD)
7674 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7677 /* we need to get it byte by byte */
7678 _startLazyDPSEvaluation();
7679 if (AOP_TYPE(result) != AOP_DPTR)
7681 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7682 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7683 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7687 /* We need to generate a load to DPTR indirect through DPTR. */
7688 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7689 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7690 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7691 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7692 emitcode("pop", "dph");
7693 emitcode("pop", "dpl");
7695 _endLazyDPSEvaluation();
7698 /* so dptr know contains the address */
7699 freeAsmop(result,NULL,ic,TRUE);
7700 aopOp(right,ic,FALSE, TRUE);
7702 /* if bit then unpack */
7703 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7704 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",FPOINTER);
7706 size = AOP_SIZE(right);
7709 _startLazyDPSEvaluation();
7711 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7717 emitcode("movx","@dptr,a");
7719 emitcode("inc","dptr");
7721 _endLazyDPSEvaluation();
7724 freeAsmop(right,NULL,ic,TRUE);
7727 /*-----------------------------------------------------------------*/
7728 /* genGenPointerSet - set value from generic pointer space */
7729 /*-----------------------------------------------------------------*/
7730 static void genGenPointerSet (operand *right,
7731 operand *result, iCode *ic)
7734 sym_link *retype = getSpec(operandType(right));
7735 sym_link *letype = getSpec(operandType(result));
7737 aopOp(result,ic,FALSE, TRUE);
7739 /* if the operand is already in dptr
7740 then we do nothing else we move the value to dptr */
7741 if (AOP_TYPE(result) != AOP_STR) {
7742 _startLazyDPSEvaluation();
7743 /* if this is remateriazable */
7744 if (AOP_TYPE(result) == AOP_IMMD) {
7745 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7746 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7748 else { /* we need to get it byte by byte */
7749 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7750 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7751 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7752 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7754 _endLazyDPSEvaluation();
7756 /* so dptr know contains the address */
7757 freeAsmop(result,NULL,ic,TRUE);
7758 aopOp(right,ic,FALSE, TRUE);
7760 /* if bit then unpack */
7761 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7762 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",GPOINTER);
7764 size = AOP_SIZE(right);
7767 _startLazyDPSEvaluation();
7769 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7775 emitcode("lcall","__gptrput");
7777 emitcode("inc","dptr");
7779 _endLazyDPSEvaluation();
7782 freeAsmop(right,NULL,ic,TRUE);
7785 /*-----------------------------------------------------------------*/
7786 /* genPointerSet - stores the value into a pointer location */
7787 /*-----------------------------------------------------------------*/
7788 static void genPointerSet (iCode *ic)
7790 operand *right, *result ;
7791 sym_link *type, *etype;
7794 D(emitcode(";", "genPointerSet "););
7796 right = IC_RIGHT(ic);
7797 result = IC_RESULT(ic) ;
7799 /* depending on the type of pointer we need to
7800 move it to the correct pointer register */
7801 type = operandType(result);
7802 etype = getSpec(type);
7803 /* if left is of type of pointer then it is simple */
7804 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7805 p_type = DCL_TYPE(type);
7808 /* we have to go by the storage class */
7809 p_type = PTR_TYPE(SPEC_OCLS(etype));
7812 /* now that we have the pointer type we assign
7813 the pointer values */
7818 genNearPointerSet (right,result,ic);
7822 genPagedPointerSet (right,result,ic);
7826 genFarPointerSet (right,result,ic);
7830 genGenPointerSet (right,result,ic);
7836 /*-----------------------------------------------------------------*/
7837 /* genIfx - generate code for Ifx statement */
7838 /*-----------------------------------------------------------------*/
7839 static void genIfx (iCode *ic, iCode *popIc)
7841 operand *cond = IC_COND(ic);
7844 D(emitcode(";", "genIfx "););
7846 aopOp(cond,ic,FALSE, FALSE);
7848 /* get the value into acc */
7849 if (AOP_TYPE(cond) != AOP_CRY)
7853 /* the result is now in the accumulator */
7854 freeAsmop(cond,NULL,ic,TRUE);
7856 /* if there was something to be popped then do it */
7860 /* if the condition is a bit variable */
7861 if (isbit && IS_ITEMP(cond) &&
7863 genIfxJump(ic,SPIL_LOC(cond)->rname);
7865 if (isbit && !IS_ITEMP(cond))
7866 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7873 /*-----------------------------------------------------------------*/
7874 /* genAddrOf - generates code for address of */
7875 /*-----------------------------------------------------------------*/
7876 static void genAddrOf (iCode *ic)
7878 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7881 D(emitcode(";", "genAddrOf "););
7883 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7885 /* if the operand is on the stack then we
7886 need to get the stack offset of this
7889 /* if it has an offset then we need to compute
7892 emitcode("mov","a,_bp");
7893 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7894 aopPut(AOP(IC_RESULT(ic)),"a",0);
7896 /* we can just move _bp */
7897 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7899 /* fill the result with zero */
7900 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7903 if (options.stack10bit && size < (FPTRSIZE - 1))
7906 "*** warning: pointer to stack var truncated.\n");
7913 if (options.stack10bit && offset == 2)
7915 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7919 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7926 /* object not on stack then we need the name */
7927 size = AOP_SIZE(IC_RESULT(ic));
7931 char s[SDCC_NAME_MAX];
7933 sprintf(s,"#(%s >> %d)",
7937 sprintf(s,"#%s",sym->rname);
7938 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7942 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7946 /*-----------------------------------------------------------------*/
7947 /* genFarFarAssign - assignment when both are in far space */
7948 /*-----------------------------------------------------------------*/
7949 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7951 int size = AOP_SIZE(right);
7958 /* This is a net loss for size == 1, but a big gain
7961 D(emitcode(";", "genFarFarAssign (improved)"););
7963 aopOp(result,ic,TRUE, TRUE);
7965 _startLazyDPSEvaluation();
7969 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7973 _endLazyDPSEvaluation();
7974 freeAsmop(result,NULL,ic,FALSE);
7975 freeAsmop(right,NULL,ic,FALSE);
7980 D(emitcode(";", "genFarFarAssign "););
7982 /* first push the right side on to the stack */
7983 _startLazyDPSEvaluation();
7985 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7987 emitcode ("push","acc");
7990 freeAsmop(right,NULL,ic,FALSE);
7991 /* now assign DPTR to result */
7992 aopOp(result,ic,FALSE, FALSE);
7993 size = AOP_SIZE(result);
7995 emitcode ("pop","acc");
7996 aopPut(AOP(result),"a",--offset);
7998 freeAsmop(result,NULL,ic,FALSE);
7999 _endLazyDPSEvaluation();
8003 /*-----------------------------------------------------------------*/
8004 /* genAssign - generate code for assignment */
8005 /*-----------------------------------------------------------------*/
8006 static void genAssign (iCode *ic)
8008 operand *result, *right;
8010 unsigned long lit = 0L;
8012 D(emitcode(";", "genAssign "););
8014 result = IC_RESULT(ic);
8015 right = IC_RIGHT(ic) ;
8017 /* if they are the same */
8018 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8021 aopOp(right,ic,FALSE, FALSE);
8023 emitcode(";", "genAssign: resultIsFar = %s",
8024 isOperandInFarSpace(result) ?
8027 /* special case both in far space */
8028 if ((AOP_TYPE(right) == AOP_DPTR ||
8029 AOP_TYPE(right) == AOP_DPTR2) &&
8030 /* IS_TRUE_SYMOP(result) && */
8031 isOperandInFarSpace(result)) {
8033 genFarFarAssign (result,right,ic);
8037 aopOp(result,ic,TRUE, FALSE);
8039 /* if they are the same registers */
8040 if (sameRegs(AOP(right),AOP(result)))
8043 /* if the result is a bit */
8044 if (AOP_TYPE(result) == AOP_CRY) {
8046 /* if the right size is a literal then
8047 we know what the value is */
8048 if (AOP_TYPE(right) == AOP_LIT) {
8049 if (((int) operandLitValue(right)))
8050 aopPut(AOP(result),one,0);
8052 aopPut(AOP(result),zero,0);
8056 /* the right is also a bit variable */
8057 if (AOP_TYPE(right) == AOP_CRY) {
8058 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8059 aopPut(AOP(result),"c",0);
8065 aopPut(AOP(result),"a",0);
8069 /* bit variables done */
8071 size = AOP_SIZE(result);
8073 if(AOP_TYPE(right) == AOP_LIT)
8074 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8077 (AOP_TYPE(result) != AOP_REG) &&
8078 (AOP_TYPE(right) == AOP_LIT) &&
8079 !IS_FLOAT(operandType(right))
8080 #ifndef LAZY_DPS_OPT
8086 D(emitcode(";", "Kevin's better literal load code"););
8087 _startLazyDPSEvaluation();
8088 while (size && ((unsigned int)(lit >> (offset*8)) != 0))
8091 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
8096 /* And now fill the rest with zeros. */
8099 emitcode("clr","a");
8103 aopPut(AOP(result), "a", offset++);
8105 _endLazyDPSEvaluation();
8107 emitcode("clr","a");
8109 _startLazyDPSEvaluation();
8112 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
8113 aopPut(AOP(result),"a",size);
8116 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
8119 _endLazyDPSEvaluation();
8124 _startLazyDPSEvaluation();
8128 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8132 _endLazyDPSEvaluation();
8136 freeAsmop (right,NULL,ic,FALSE);
8137 freeAsmop (result,NULL,ic,TRUE);
8140 /*-----------------------------------------------------------------*/
8141 /* genJumpTab - generates code for jump table */
8142 /*-----------------------------------------------------------------*/
8143 static void genJumpTab (iCode *ic)
8148 D(emitcode(";", "genJumpTab "););
8150 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
8151 /* get the condition into accumulator */
8152 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
8154 /* multiply by four! */
8155 emitcode("add","a,acc");
8156 emitcode("add","a,acc");
8157 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8159 jtab = newiTempLabel(NULL);
8160 emitcode("mov","dptr,#%05d$",jtab->key+100);
8161 emitcode("jmp","@a+dptr");
8162 emitcode("","%05d$:",jtab->key+100);
8163 /* now generate the jump labels */
8164 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8165 jtab = setNextItem(IC_JTLABELS(ic)))
8166 emitcode("ljmp","%05d$",jtab->key+100);
8170 /*-----------------------------------------------------------------*/
8171 /* genCast - gen code for casting */
8172 /*-----------------------------------------------------------------*/
8173 static void genCast (iCode *ic)
8175 operand *result = IC_RESULT(ic);
8176 sym_link *ctype = operandType(IC_LEFT(ic));
8177 sym_link *rtype = operandType(IC_RIGHT(ic));
8178 operand *right = IC_RIGHT(ic);
8181 D(emitcode(";", "genCast "););
8183 /* if they are equivalent then do nothing */
8184 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8187 aopOp(right,ic,FALSE, FALSE) ;
8188 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
8190 /* if the result is a bit */
8191 if (AOP_TYPE(result) == AOP_CRY) {
8192 /* if the right size is a literal then
8193 we know what the value is */
8194 if (AOP_TYPE(right) == AOP_LIT) {
8195 if (((int) operandLitValue(right)))
8196 aopPut(AOP(result),one,0);
8198 aopPut(AOP(result),zero,0);
8203 /* the right is also a bit variable */
8204 if (AOP_TYPE(right) == AOP_CRY) {
8205 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8206 aopPut(AOP(result),"c",0);
8212 aopPut(AOP(result),"a",0);
8216 /* if they are the same size : or less */
8217 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8219 /* if they are in the same place */
8220 if (sameRegs(AOP(right),AOP(result)))
8223 /* if they in different places then copy */
8224 size = AOP_SIZE(result);
8226 _startLazyDPSEvaluation();
8229 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8233 _endLazyDPSEvaluation();
8238 /* if the result is of type pointer */
8239 if (IS_PTR(ctype)) {
8242 sym_link *type = operandType(right);
8244 /* pointer to generic pointer */
8245 if (IS_GENPTR(ctype)) {
8250 p_type = DCL_TYPE(type);
8254 #if OLD_CAST_BEHAVIOR
8255 /* KV: we are converting a non-pointer type to
8256 * a generic pointer. This (ifdef'd out) code
8257 * says that the resulting generic pointer
8258 * should have the same class as the storage
8259 * location of the non-pointer variable.
8261 * For example, converting an int (which happens
8262 * to be stored in DATA space) to a pointer results
8263 * in a DATA generic pointer; if the original int
8264 * in XDATA space, so will be the resulting pointer.
8266 * I don't like that behavior, and thus this change:
8267 * all such conversions will be forced to XDATA and
8268 * throw a warning. If you want some non-XDATA
8269 * type, or you want to suppress the warning, you
8270 * must go through an intermediate cast, like so:
8272 * char _generic *gp = (char _xdata *)(intVar);
8274 sym_link *etype = getSpec(type);
8276 /* we have to go by the storage class */
8277 if (SPEC_OCLS(etype) != generic)
8279 p_type = PTR_TYPE(SPEC_OCLS(etype));
8284 /* Converting unknown class (i.e. register variable)
8285 * to generic pointer. This is not good, but
8286 * we'll make a guess (and throw a warning).
8289 werror(W_INT_TO_GEN_PTR_CAST);
8293 /* the first two bytes are known */
8294 size = GPTRSIZE - 1;
8296 _startLazyDPSEvaluation();
8299 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8303 _endLazyDPSEvaluation();
8305 /* the last byte depending on type */
8322 /* this should never happen */
8323 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8324 "got unknown pointer type");
8327 aopPut(AOP(result),l, GPTRSIZE - 1);
8331 /* just copy the pointers */
8332 size = AOP_SIZE(result);
8334 _startLazyDPSEvaluation();
8337 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8341 _endLazyDPSEvaluation();
8345 /* so we now know that the size of destination is greater
8346 than the size of the source */
8347 /* we move to result for the size of source */
8348 size = AOP_SIZE(right);
8350 _startLazyDPSEvaluation();
8353 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8357 _endLazyDPSEvaluation();
8359 /* now depending on the sign of the source && destination */
8360 size = AOP_SIZE(result) - AOP_SIZE(right);
8361 /* if unsigned or not an integral type */
8362 /* also, if the source is a bit, we don't need to sign extend, because
8363 * it can't possibly have set the sign bit.
8365 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype) || AOP_TYPE(right) == AOP_CRY)
8369 aopPut(AOP(result),zero,offset++);
8374 /* we need to extend the sign :{ */
8375 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8378 emitcode("rlc","a");
8379 emitcode("subb","a,acc");
8381 aopPut(AOP(result),"a",offset++);
8384 /* we are done hurray !!!! */
8387 freeAsmop(right,NULL,ic,TRUE);
8388 freeAsmop(result,NULL,ic,TRUE);
8392 /*-----------------------------------------------------------------*/
8393 /* genDjnz - generate decrement & jump if not zero instrucion */
8394 /*-----------------------------------------------------------------*/
8395 static int genDjnz (iCode *ic, iCode *ifx)
8401 /* if the if condition has a false label
8402 then we cannot save */
8406 /* if the minus is not of the form
8408 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8409 !IS_OP_LITERAL(IC_RIGHT(ic)))
8412 if (operandLitValue(IC_RIGHT(ic)) != 1)
8415 /* if the size of this greater than one then no
8417 if (getSize(operandType(IC_RESULT(ic))) > 1)
8420 /* otherwise we can save BIG */
8421 lbl = newiTempLabel(NULL);
8422 lbl1= newiTempLabel(NULL);
8424 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8426 if (IS_AOP_PREG(IC_RESULT(ic))) {
8427 emitcode("dec","%s",
8428 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8429 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8430 emitcode("jnz","%05d$",lbl->key+100);
8432 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8435 emitcode ("sjmp","%05d$",lbl1->key+100);
8436 emitcode ("","%05d$:",lbl->key+100);
8437 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8438 emitcode ("","%05d$:",lbl1->key+100);
8440 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8445 /*-----------------------------------------------------------------*/
8446 /* genReceive - generate code for a receive iCode */
8447 /*-----------------------------------------------------------------*/
8448 static void genReceive (iCode *ic)
8451 D(emitcode(";", "genReceive "););
8453 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8454 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8455 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8456 int size = getSize(operandType(IC_RESULT(ic)));
8457 int offset = fReturnSize_390 - size;
8459 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8460 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8463 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8464 size = AOP_SIZE(IC_RESULT(ic));
8467 emitcode ("pop","acc");
8468 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8473 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8475 assignResultValue(IC_RESULT(ic));
8478 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8481 /*-----------------------------------------------------------------*/
8482 /* gen390Code - generate code for Dallas 390 based controllers */
8483 /*-----------------------------------------------------------------*/
8484 void gen390Code (iCode *lic)
8489 lineHead = lineCurr = NULL;
8493 /* print the allocation information */
8495 printAllocInfo( currFunc, codeOutFile);
8497 /* if debug information required */
8498 if (options.debug && currFunc) {
8499 //jwk if (currFunc) {
8500 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8502 if (IS_STATIC(currFunc->etype))
8503 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8505 emitcode("","G$%s$0$0 ==.",currFunc->name);
8508 /* stack pointer name */
8509 if (options.useXstack)
8515 for (ic = lic ; ic ; ic = ic->next ) {
8517 if ( cln != ic->lineno ) {
8518 if ( options.debug ) {
8520 emitcode("","C$%s$%d$%d$%d ==.",
8521 ic->filename,ic->lineno,
8522 ic->level,ic->block);
8525 emitcode(";","%s %d",ic->filename,ic->lineno);
8528 /* if the result is marked as
8529 spilt and rematerializable or code for
8530 this has already been generated then
8532 if (resultRemat(ic) || ic->generated )
8535 /* depending on the operation */
8554 /* IPOP happens only when trying to restore a
8555 spilt live range, if there is an ifx statement
8556 following this pop then the if statement might
8557 be using some of the registers being popped which
8558 would destory the contents of the register so
8559 we need to check for this condition and handle it */
8561 ic->next->op == IFX &&
8562 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8563 genIfx (ic->next,ic);
8581 genEndFunction (ic);
8601 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8618 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8622 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8629 /* note these two are xlated by algebraic equivalence
8630 during parsing SDCC.y */
8631 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8632 "got '>=' or '<=' shouldn't have come here");
8636 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8648 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8652 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8656 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8683 case GET_VALUE_AT_ADDRESS:
8688 if (POINTER_SET(ic))
8715 addSet(&_G.sendSet,ic);
8720 /* piCode(ic,stdout); */
8726 /* now we are ready to call the
8727 peep hole optimizer */
8728 if (!options.nopeep)
8729 peepHole (&lineHead);
8731 /* now do the actual printing */
8732 printLine (lineHead,codeOutFile);