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"
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
54 char *aopLiteral (value *val, int offset);
60 /* this is the down and dirty file with all kinds of
61 kludgy & hacky stuff. This is what it is all about
62 CODE GENERATION for a specific MCU . some of the
63 routines may be reusable, will have to see */
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
71 unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
72 static char *fReturn[] = {"dpl","dph","dpx", "b","a" };
73 static char *accUse[] = {"a","b"};
75 static short rbank = -1;
87 static void saverbank (int, iCode *,bool);
89 #define RESULTONSTACK(x) \
90 (IC_RESULT(x) && IC_RESULT(x)->aop && \
91 IC_RESULT(x)->aop->type == AOP_STK )
93 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
94 #define MOVA(x) { char *_mova_tmp = strdup(x); \
95 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
97 emitcode("mov","a,%s",_mova_tmp); \
101 #define CLRC emitcode("clr","c")
102 #define SETC emitcode("setb","c")
104 static lineNode *lineHead = NULL;
105 static lineNode *lineCurr = NULL;
107 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
108 0xE0, 0xC0, 0x80, 0x00};
109 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
110 0x07, 0x03, 0x01, 0x00};
117 /*-----------------------------------------------------------------*/
118 /* emitcode - writes the code into a file : for now it is simple */
119 /*-----------------------------------------------------------------*/
120 static void emitcode (char *inst,char *fmt, ...)
123 char lb[MAX_INLINEASM];
130 sprintf(lb,"%s\t",inst);
134 /* for some reason the parser throws in a mysterious "Y" at
135 the end of inline assembly code.
136 Do a make in device/lib and you know all about it.
141 if (strcmp(&inst[i],"Y")==0) {
142 fprintf (stderr, "===> BEWARE of the inline Y bug hack <===\n");
145 sprintf(lb,"%s",inst);
149 sprintf(lb,"%s",inst);
151 vsprintf(lb+(strlen(lb)),fmt,ap);
155 while (isspace(*lbp)) lbp++;
158 lineCurr = (lineCurr ?
159 connectLine(lineCurr,newLineNode(lb)) :
160 (lineHead = newLineNode(lb)));
161 lineCurr->isInline = _G.inLine;
162 lineCurr->isDebug = _G.debugLine;
166 /*-----------------------------------------------------------------*/
167 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
168 /*-----------------------------------------------------------------*/
169 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
171 bool r0iu = FALSE , r1iu = FALSE;
172 bool r0ou = FALSE , r1ou = FALSE;
174 /* the logic: if r0 & r1 used in the instruction
175 then we are in trouble otherwise */
177 /* first check if r0 & r1 are used by this
178 instruction, in which case we are in trouble */
179 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
180 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
185 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
186 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
188 /* if no usage of r0 then return it */
189 if (!r0iu && !r0ou) {
190 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
191 (*aopp)->type = AOP_R0;
193 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
196 /* if no usage of r1 then return it */
197 if (!r1iu && !r1ou) {
198 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
199 (*aopp)->type = AOP_R1;
201 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R1_IDX);
204 /* now we know they both have usage */
205 /* if r0 not used in this instruction */
207 /* push it if not already pushed */
209 emitcode ("push","%s",
210 ds390_regWithIdx(R0_IDX)->dname);
214 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
215 (*aopp)->type = AOP_R0;
217 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
220 /* if r1 not used then */
223 /* push it if not already pushed */
225 emitcode ("push","%s",
226 ds390_regWithIdx(R1_IDX)->dname);
230 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
231 (*aopp)->type = AOP_R1;
232 return ds390_regWithIdx(R1_IDX);
236 /* I said end of world but not quite end of world yet */
237 /* if this is a result then we can push it on the stack*/
239 (*aopp)->type = AOP_STK;
244 /* other wise this is true end of the world */
245 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
246 "getFreePtr should never reach here");
250 /*-----------------------------------------------------------------*/
251 /* newAsmop - creates a new asmOp */
252 /*-----------------------------------------------------------------*/
253 static asmop *newAsmop (short type)
257 ALLOC(aop,sizeof(asmop));
262 /* Turn this off if the world goes to hell. */
265 static int _currentDPS; /* Current processor DPS. */
266 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
267 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
269 /*-----------------------------------------------------------------*/
270 /* genSetDPTR: generate code to select which DPTR is in use (zero */
271 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
272 /* alternate DPTR (DPL1/DPH1/DPX1). */
273 /*-----------------------------------------------------------------*/
274 static void genSetDPTR(int n)
278 /* If we are doing lazy evaluation, simply note the desired
279 * change, but don't emit any code yet.
290 emitcode("mov", "dps, #0x00");
294 emitcode("mov", "dps, #0x01");
298 /*-----------------------------------------------------------------*/
299 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation*/
301 /* Any code that operates on DPTR (NB: not on the individual */
302 /* components, like DPH) *must* call _flushLazyDPS() before using */
303 /* DPTR within a lazy DPS evaluation block. */
305 /* Note that aopPut and aopGet already contain the proper calls to */
306 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
307 /* DPS evaluation block. */
309 /* Also, _flushLazyDPS must be called before any flow control */
310 /* operations that could potentially branch out of the block. */
312 /* Lazy DPS evaluation is simply an optimization (though an */
313 /* important one), so if in doubt, leave it out. */
314 /*-----------------------------------------------------------------*/
315 static void _startLazyDPSEvaluation(void)
322 /*-----------------------------------------------------------------*/
323 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
324 /* desired one. Call before using DPTR within a lazy DPS evaluation*/
326 /*-----------------------------------------------------------------*/
327 static void _flushLazyDPS(void)
335 if (_desiredDPS != _currentDPS)
339 emitcode("inc", "dps");
343 emitcode("dec", "dps");
345 _currentDPS = _desiredDPS;
349 /*-----------------------------------------------------------------*/
350 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
352 /* Forces us back to the safe state (standard DPTR selected). */
353 /*-----------------------------------------------------------------*/
354 static void _endLazyDPSEvaluation(void)
368 /*-----------------------------------------------------------------*/
369 /* pointerCode - returns the code for a pointer type */
370 /*-----------------------------------------------------------------*/
371 static int pointerCode (sym_link *etype)
374 return PTR_TYPE(SPEC_OCLS(etype));
378 /*-----------------------------------------------------------------*/
379 /* aopForSym - for a true symbol */
380 /*-----------------------------------------------------------------*/
381 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
384 memmap *space= SPEC_OCLS(sym->etype);
386 /* if already has one */
390 /* assign depending on the storage class */
391 /* if it is on the stack or indirectly addressable */
392 /* space we need to assign either r0 or r1 to it */
393 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
394 sym->aop = aop = newAsmop(0);
395 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
396 aop->size = getSize(sym->type);
398 /* now assign the address of the variable to
399 the pointer register */
400 if (aop->type != AOP_STK) {
404 emitcode("push","acc");
406 emitcode("mov","a,_bp");
407 emitcode("add","a,#0x%02x",
409 ((char)(sym->stack - _G.nRegsSaved )) :
410 ((char)sym->stack)) & 0xff);
411 emitcode("mov","%s,a",
412 aop->aopu.aop_ptr->name);
415 emitcode("pop","acc");
417 emitcode("mov","%s,#%s",
418 aop->aopu.aop_ptr->name,
420 aop->paged = space->paged;
422 aop->aopu.aop_stk = sym->stack;
426 if (sym->onStack && options.stack10bit)
428 /* It's on the 10 bit stack, which is located in
433 emitcode("push","acc");
435 emitcode("mov","a,_bp");
436 emitcode("add","a,#0x%02x",
438 ((char)(sym->stack - _G.nRegsSaved )) :
439 ((char)sym->stack)) & 0xff);
444 emitcode ("mov","dpx1,#0x40");
445 emitcode ("mov","dph1,#0x00");
446 emitcode ("mov","dpl1, a");
451 emitcode ("mov","dpx,#0x40");
452 emitcode ("mov","dph,#0x00");
453 emitcode ("mov","dpl, a");
457 emitcode("pop","acc");
459 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
460 aop->size = getSize(sym->type);
464 /* if in bit space */
465 if (IN_BITSPACE(space)) {
466 sym->aop = aop = newAsmop (AOP_CRY);
467 aop->aopu.aop_dir = sym->rname ;
468 aop->size = getSize(sym->type);
471 /* if it is in direct space */
472 if (IN_DIRSPACE(space)) {
473 sym->aop = aop = newAsmop (AOP_DIR);
474 aop->aopu.aop_dir = sym->rname ;
475 aop->size = getSize(sym->type);
479 /* special case for a function */
480 if (IS_FUNC(sym->type)) {
481 sym->aop = aop = newAsmop(AOP_IMMD);
482 ALLOC(aop->aopu.aop_immd,strlen(sym->rname)+1);
483 strcpy(aop->aopu.aop_immd,sym->rname);
484 aop->size = FPTRSIZE;
488 /* only remaining is far space */
489 /* in which case DPTR gets the address */
490 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
495 emitcode ("mov","dptr,#%s", sym->rname);
500 emitcode ("mov","dptr,#%s", sym->rname);
502 aop->size = getSize(sym->type);
504 /* if it is in code space */
505 if (IN_CODESPACE(space))
511 /*-----------------------------------------------------------------*/
512 /* aopForRemat - rematerialzes an object */
513 /*-----------------------------------------------------------------*/
514 static asmop *aopForRemat (symbol *sym)
516 iCode *ic = sym->rematiCode;
517 asmop *aop = newAsmop(AOP_IMMD);
523 val += operandLitValue(IC_RIGHT(ic));
524 else if (ic->op == '-')
525 val -= operandLitValue(IC_RIGHT(ic));
529 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
533 sprintf(buffer,"(%s %c 0x%04x)",
534 OP_SYMBOL(IC_LEFT(ic))->rname,
535 val >= 0 ? '+' : '-',
538 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
540 ALLOC(aop->aopu.aop_immd,strlen(buffer)+1);
541 strcpy(aop->aopu.aop_immd,buffer);
545 /*-----------------------------------------------------------------*/
546 /* regsInCommon - two operands have some registers in common */
547 /*-----------------------------------------------------------------*/
548 static bool regsInCommon (operand *op1, operand *op2)
553 /* if they have registers in common */
554 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
557 sym1 = OP_SYMBOL(op1);
558 sym2 = OP_SYMBOL(op2);
560 if (sym1->nRegs == 0 || sym2->nRegs == 0)
563 for (i = 0 ; i < sym1->nRegs ; i++) {
568 for (j = 0 ; j < sym2->nRegs ;j++ ) {
572 if (sym2->regs[j] == sym1->regs[i])
580 /*-----------------------------------------------------------------*/
581 /* operandsEqu - equivalent */
582 /*-----------------------------------------------------------------*/
583 static bool operandsEqu ( operand *op1, operand *op2)
587 /* if they not symbols */
588 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
591 sym1 = OP_SYMBOL(op1);
592 sym2 = OP_SYMBOL(op2);
594 /* if both are itemps & one is spilt
595 and the other is not then false */
596 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
597 sym1->isspilt != sym2->isspilt )
600 /* if they are the same */
604 if (strcmp(sym1->rname,sym2->rname) == 0)
608 /* if left is a tmp & right is not */
612 (sym1->usl.spillLoc == sym2))
619 (sym2->usl.spillLoc == sym1))
625 /*-----------------------------------------------------------------*/
626 /* sameRegs - two asmops have the same registers */
627 /*-----------------------------------------------------------------*/
628 static bool sameRegs (asmop *aop1, asmop *aop2 )
634 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
641 if (aop1->type != AOP_REG ||
642 aop2->type != AOP_REG )
645 if (aop1->size != aop2->size )
648 for (i = 0 ; i < aop1->size ; i++ )
649 if (aop1->aopu.aop_reg[i] !=
650 aop2->aopu.aop_reg[i] )
656 /*-----------------------------------------------------------------*/
657 /* aopOp - allocates an asmop for an operand : */
658 /*-----------------------------------------------------------------*/
659 static void aopOp (operand *op, iCode *ic, bool result, bool useDP2)
668 /* if this a literal */
669 if (IS_OP_LITERAL(op)) {
670 op->aop = aop = newAsmop(AOP_LIT);
671 aop->aopu.aop_lit = op->operand.valOperand;
672 aop->size = getSize(operandType(op));
676 /* if already has a asmop then continue */
680 /* if the underlying symbol has a aop */
681 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
682 op->aop = OP_SYMBOL(op)->aop;
686 /* if this is a true symbol */
687 if (IS_TRUE_SYMOP(op)) {
688 op->aop = aopForSym(ic,OP_SYMBOL(op),result, useDP2);
692 /* this is a temporary : this has
698 e) can be a return use only */
703 /* if the type is a conditional */
704 if (sym->regType == REG_CND) {
705 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
710 /* if it is spilt then two situations
712 b) has a spill location */
713 if (sym->isspilt || sym->nRegs == 0) {
715 /* rematerialize it NOW */
717 sym->aop = op->aop = aop =
719 aop->size = getSize(sym->type);
725 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
726 aop->size = getSize(sym->type);
727 for ( i = 0 ; i < 2 ; i++ )
728 aop->aopu.aop_str[i] = accUse[i];
737 /* a AOP_STR uses DPTR, but DPTR is already in use;
740 fprintf(stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
743 aop = op->aop = sym->aop = newAsmop(AOP_STR);
744 aop->size = getSize(sym->type);
745 for ( i = 0 ; i < fReturnSize_390 ; i++ )
746 aop->aopu.aop_str[i] = fReturn[i];
750 /* else spill location */
751 sym->aop = op->aop = aop =
752 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
753 aop->size = getSize(sym->type);
757 /* must be in a register */
758 sym->aop = op->aop = aop = newAsmop(AOP_REG);
759 aop->size = sym->nRegs;
760 for ( i = 0 ; i < sym->nRegs ;i++)
761 aop->aopu.aop_reg[i] = sym->regs[i];
764 /*-----------------------------------------------------------------*/
765 /* freeAsmop - free up the asmop given to an operand */
766 /*----------------------------------------------------------------*/
767 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
784 /* depending on the asmop type only three cases need work AOP_RO
785 , AOP_R1 && AOP_STK */
790 emitcode ("pop","ar0");
794 bitVectUnSetBit(ic->rUsed,R0_IDX);
800 emitcode ("pop","ar1");
804 bitVectUnSetBit(ic->rUsed,R1_IDX);
810 int stk = aop->aopu.aop_stk + aop->size;
811 bitVectUnSetBit(ic->rUsed,R0_IDX);
812 bitVectUnSetBit(ic->rUsed,R1_IDX);
814 getFreePtr(ic,&aop,FALSE);
816 if (options.stack10bit)
818 /* I'm not sure what to do here yet... */
821 "*** Warning: probably generating bad code for "
822 "10 bit stack mode.\n");
826 emitcode ("mov","a,_bp");
827 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
828 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
830 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
834 emitcode("pop","acc");
835 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
837 emitcode("dec","%s",aop->aopu.aop_ptr->name);
840 freeAsmop(op,NULL,ic,TRUE);
842 emitcode("pop","ar0");
847 emitcode("pop","ar1");
854 /* all other cases just dealloc */
858 OP_SYMBOL(op)->aop = NULL;
859 /* if the symbol has a spill */
861 SPIL_LOC(op)->aop = NULL;
866 /*------------------------------------------------------------------*/
867 /* aopGet - for fetching value of the aop */
869 /* Set canClobberACC if you are aure it is OK to clobber the value */
870 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe,*/
871 /* just less efficient. */
872 /*------------------------------------------------------------------*/
874 static char *aopGet (asmop *aop,
883 /* offset is greater than
885 if (offset > (aop->size - 1) &&
886 aop->type != AOP_LIT)
889 /* depending on type */
894 /* if we need to increment it */
895 while (offset > aop->coff) {
896 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
900 while (offset < aop->coff) {
901 emitcode("dec","%s",aop->aopu.aop_ptr->name);
907 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
908 return (dname ? "acc" : "a");
910 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
911 ALLOC(rs,strlen(s)+1);
918 if (aop->type == AOP_DPTR2)
922 #ifndef KEVIN_BROKE_IT
926 emitcode("xch", "a, ap");
932 while (offset > aop->coff) {
933 emitcode ("inc","dptr");
937 while (offset < aop->coff) {
938 emitcode("lcall","__decdptr");
945 emitcode("movc","a,@a+dptr");
948 emitcode("movx","a,@dptr");
951 if (aop->type == AOP_DPTR2)
955 #ifndef KEVIN_BROKE_IT
959 emitcode("xch", "a, ap");
964 return (dname ? "acc" : "a");
968 sprintf (s,"#%s",aop->aopu.aop_immd);
971 sprintf(s,"#(%s >> %d)",
977 ALLOC(rs,strlen(s)+1);
983 sprintf(s,"(%s + %d)",
987 sprintf(s,"%s",aop->aopu.aop_dir);
988 ALLOC(rs,strlen(s)+1);
994 return aop->aopu.aop_reg[offset]->dname;
996 return aop->aopu.aop_reg[offset]->name;
1000 emitcode("mov","c,%s",aop->aopu.aop_dir);
1001 emitcode("rlc","a") ;
1002 return (dname ? "acc" : "a");
1005 if (!offset && dname)
1007 return aop->aopu.aop_str[offset];
1010 return aopLiteral (aop->aopu.aop_lit,offset);
1013 aop->coff = offset ;
1014 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1018 return aop->aopu.aop_str[offset];
1022 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1023 "aopget got unsupported aop->type");
1026 /*-----------------------------------------------------------------*/
1027 /* aopPut - puts a string for a aop */
1028 /*-----------------------------------------------------------------*/
1029 static void aopPut (asmop *aop, char *s, int offset)
1034 if (aop->size && offset > ( aop->size - 1)) {
1035 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1036 "aopPut got offset > aop->size");
1040 /* will assign value to value */
1041 /* depending on where it is ofcourse */
1042 switch (aop->type) {
1045 sprintf(d,"(%s + %d)",
1046 aop->aopu.aop_dir,offset);
1048 sprintf(d,"%s",aop->aopu.aop_dir);
1051 emitcode("mov","%s,%s",d,s);
1056 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1057 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1059 strcmp(s,"r0") == 0 ||
1060 strcmp(s,"r1") == 0 ||
1061 strcmp(s,"r2") == 0 ||
1062 strcmp(s,"r3") == 0 ||
1063 strcmp(s,"r4") == 0 ||
1064 strcmp(s,"r5") == 0 ||
1065 strcmp(s,"r6") == 0 ||
1066 strcmp(s,"r7") == 0 )
1067 emitcode("mov","%s,%s",
1068 aop->aopu.aop_reg[offset]->dname,s);
1070 emitcode("mov","%s,%s",
1071 aop->aopu.aop_reg[offset]->name,s);
1078 if (aop->type == AOP_DPTR2)
1085 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1086 "aopPut writting to code space");
1090 while (offset > aop->coff) {
1092 emitcode ("inc","dptr");
1095 while (offset < aop->coff) {
1097 emitcode("lcall","__decdptr");
1102 /* if not in accumulater */
1105 emitcode ("movx","@dptr,a");
1107 if (aop->type == AOP_DPTR2)
1115 while (offset > aop->coff) {
1117 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1119 while (offset < aop->coff) {
1121 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1127 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1132 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1134 if (strcmp(s,"r0") == 0 ||
1135 strcmp(s,"r1") == 0 ||
1136 strcmp(s,"r2") == 0 ||
1137 strcmp(s,"r3") == 0 ||
1138 strcmp(s,"r4") == 0 ||
1139 strcmp(s,"r5") == 0 ||
1140 strcmp(s,"r6") == 0 ||
1141 strcmp(s,"r7") == 0 ) {
1143 sprintf(buffer,"a%s",s);
1144 emitcode("mov","@%s,%s",
1145 aop->aopu.aop_ptr->name,buffer);
1147 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1152 if (strcmp(s,"a") == 0)
1153 emitcode("push","acc");
1155 emitcode("push","%s",s);
1160 /* if bit variable */
1161 if (!aop->aopu.aop_dir) {
1162 emitcode("clr","a");
1163 emitcode("rlc","a");
1166 emitcode("clr","%s",aop->aopu.aop_dir);
1169 emitcode("setb","%s",aop->aopu.aop_dir);
1172 emitcode("mov","%s,c",aop->aopu.aop_dir);
1174 lbl = newiTempLabel(NULL);
1176 if (strcmp(s,"a")) {
1179 emitcode("clr","c");
1180 emitcode("jz","%05d$",lbl->key+100);
1181 emitcode("cpl","c");
1182 emitcode("","%05d$:",lbl->key+100);
1183 emitcode("mov","%s,c",aop->aopu.aop_dir);
1190 if (strcmp(aop->aopu.aop_str[offset],s))
1191 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1196 if (!offset && (strcmp(s,"acc") == 0))
1199 if (strcmp(aop->aopu.aop_str[offset],s))
1200 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1204 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1205 "aopPut got unsupported aop->type");
1212 /*-----------------------------------------------------------------*/
1213 /* reAdjustPreg - points a register back to where it should */
1214 /*-----------------------------------------------------------------*/
1215 static void reAdjustPreg (asmop *aop)
1220 if ((size = aop->size) <= 1)
1223 switch (aop->type) {
1227 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1231 if (aop->type == AOP_DPTR2)
1238 emitcode("lcall","__decdptr");
1241 if (aop->type == AOP_DPTR2)
1251 #define AOP(op) op->aop
1252 #define AOP_TYPE(op) AOP(op)->type
1253 #define AOP_SIZE(op) AOP(op)->size
1254 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1255 AOP_TYPE(x) == AOP_R0))
1257 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1258 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1261 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1262 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1263 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1265 /* Workaround for DS80C390 bug: div ab may return bogus results
1266 * if A is accessed in instruction immediately before the div.
1268 * Will be fixed in B4 rev of processor, Dallas claims.
1271 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1272 if (!AOP_NEEDSACC(RIGHT)) \
1274 /* We can load A first, then B, since \
1275 * B (the RIGHT operand) won't clobber A, \
1276 * thus avoiding touching A right before the div. \
1278 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1279 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1281 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1285 /* Just stuff in a nop after loading A. */ \
1286 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1287 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1289 emitcode("nop", "; workaround for DS80C390 div bug."); \
1292 /*-----------------------------------------------------------------*/
1293 /* genNotFloat - generates not for float operations */
1294 /*-----------------------------------------------------------------*/
1295 static void genNotFloat (operand *op, operand *res)
1301 D(emitcode(";", "genNotFloat "););
1303 /* we will put 127 in the first byte of
1305 aopPut(AOP(res),"#127",0);
1306 size = AOP_SIZE(op) - 1;
1309 _startLazyDPSEvaluation();
1310 l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
1314 emitcode("orl","a,%s",
1316 offset++,FALSE,FALSE,FALSE));
1318 _endLazyDPSEvaluation();
1319 tlbl = newiTempLabel(NULL);
1321 tlbl = newiTempLabel(NULL);
1322 aopPut(res->aop,one,1);
1323 emitcode("jz","%05d$",(tlbl->key+100));
1324 aopPut(res->aop,zero,1);
1325 emitcode("","%05d$:",(tlbl->key+100));
1327 size = res->aop->size - 2;
1329 /* put zeros in the rest */
1331 aopPut(res->aop,zero,offset++);
1334 /*-----------------------------------------------------------------*/
1335 /* opIsGptr: returns non-zero if the passed operand is */
1336 /* a generic pointer type. */
1337 /*-----------------------------------------------------------------*/
1338 static int opIsGptr(operand *op)
1340 sym_link *type = operandType(op);
1342 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1349 /*-----------------------------------------------------------------*/
1350 /* getDataSize - get the operand data size */
1351 /*-----------------------------------------------------------------*/
1352 static int getDataSize(operand *op)
1355 size = AOP_SIZE(op);
1356 if (size == GPTRSIZE)
1358 sym_link *type = operandType(op);
1359 if (IS_GENPTR(type))
1361 /* generic pointer; arithmetic operations
1362 * should ignore the high byte (pointer type).
1370 /*-----------------------------------------------------------------*/
1371 /* outAcc - output Acc */
1372 /*-----------------------------------------------------------------*/
1373 static void outAcc(operand *result)
1376 size = getDataSize(result);
1379 aopPut(AOP(result),"a",0);
1382 /* unsigned or positive */
1384 aopPut(AOP(result),zero,offset++);
1389 /*-----------------------------------------------------------------*/
1390 /* outBitC - output a bit C */
1391 /*-----------------------------------------------------------------*/
1392 static void outBitC(operand *result)
1394 /* if the result is bit */
1395 if (AOP_TYPE(result) == AOP_CRY)
1397 aopPut(AOP(result),"c",0);
1401 emitcode("clr","a");
1402 emitcode("rlc","a");
1407 /*-----------------------------------------------------------------*/
1408 /* toBoolean - emit code for orl a,operator(sizeop) */
1409 /*-----------------------------------------------------------------*/
1410 static void toBoolean(operand *oper)
1412 int size = AOP_SIZE(oper) - 1;
1415 /* The generic part of a generic pointer should
1416 * not participate in it's truth value.
1418 * i.e. 0x10000000 is zero.
1422 D(emitcode(";", "toBoolean: generic ptr special case."););
1426 _startLazyDPSEvaluation();
1427 if (AOP_NEEDSACC(oper))
1429 emitcode("push", "b");
1430 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1434 MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1438 if (AOP_NEEDSACC(oper))
1440 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1444 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1447 _endLazyDPSEvaluation();
1449 if (AOP_NEEDSACC(oper))
1451 emitcode("mov", "a,b");
1452 emitcode("pop", "b");
1457 /*-----------------------------------------------------------------*/
1458 /* genNot - generate code for ! operation */
1459 /*-----------------------------------------------------------------*/
1460 static void genNot (iCode *ic)
1463 sym_link *optype = operandType(IC_LEFT(ic));
1465 D(emitcode(";", "genNot "););
1467 /* assign asmOps to operand & result */
1468 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1469 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1471 /* if in bit space then a special case */
1472 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1473 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1474 emitcode("cpl","c");
1475 outBitC(IC_RESULT(ic));
1479 /* if type float then do float */
1480 if (IS_FLOAT(optype)) {
1481 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1485 toBoolean(IC_LEFT(ic));
1487 tlbl = newiTempLabel(NULL);
1488 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1489 emitcode("","%05d$:",tlbl->key+100);
1490 outBitC(IC_RESULT(ic));
1493 /* release the aops */
1494 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1495 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1499 /*-----------------------------------------------------------------*/
1500 /* genCpl - generate code for complement */
1501 /*-----------------------------------------------------------------*/
1502 static void genCpl (iCode *ic)
1507 D(emitcode(";", "genCpl "););
1510 /* assign asmOps to operand & result */
1511 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1512 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1514 /* if both are in bit space then
1516 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1517 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1519 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1520 emitcode("cpl","c");
1521 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1525 size = AOP_SIZE(IC_RESULT(ic));
1526 _startLazyDPSEvaluation();
1528 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1530 emitcode("cpl","a");
1531 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1533 _endLazyDPSEvaluation();
1537 /* release the aops */
1538 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1539 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1542 /*-----------------------------------------------------------------*/
1543 /* genUminusFloat - unary minus for floating points */
1544 /*-----------------------------------------------------------------*/
1545 static void genUminusFloat(operand *op,operand *result)
1547 int size ,offset =0 ;
1549 /* for this we just need to flip the
1550 first it then copy the rest in place */
1551 D(emitcode(";", "genUminusFloat"););
1553 _startLazyDPSEvaluation();
1554 size = AOP_SIZE(op) - 1;
1555 l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1558 emitcode("cpl","acc.7");
1559 aopPut(AOP(result),"a",3);
1563 aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1567 _endLazyDPSEvaluation();
1570 /*-----------------------------------------------------------------*/
1571 /* genUminus - unary minus code generation */
1572 /*-----------------------------------------------------------------*/
1573 static void genUminus (iCode *ic)
1576 sym_link *optype, *rtype;
1578 D(emitcode(";", "genUminus "););
1582 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1583 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1585 /* if both in bit space then special
1587 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1588 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1590 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1591 emitcode("cpl","c");
1592 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1596 optype = operandType(IC_LEFT(ic));
1597 rtype = operandType(IC_RESULT(ic));
1599 /* if float then do float stuff */
1600 if (IS_FLOAT(optype)) {
1601 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1605 /* otherwise subtract from zero */
1606 size = AOP_SIZE(IC_LEFT(ic));
1608 _startLazyDPSEvaluation();
1610 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1611 if (!strcmp(l,"a")) {
1614 emitcode("cpl","a");
1615 emitcode("addc", "a,#0");
1619 emitcode("clr","a");
1620 emitcode("subb","a,%s",l);
1622 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1624 _endLazyDPSEvaluation();
1626 /* if any remaining bytes in the result */
1627 /* we just need to propagate the sign */
1628 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1629 emitcode("rlc","a");
1630 emitcode("subb","a,acc");
1632 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1636 /* release the aops */
1637 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1638 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1641 /*-----------------------------------------------------------------*/
1642 /* saveRegisters - will look for a call and save the registers */
1643 /*-----------------------------------------------------------------*/
1644 static void saveRegisters(iCode *lic)
1652 for (ic = lic ; ic ; ic = ic->next)
1653 if (ic->op == CALL || ic->op == PCALL)
1657 fprintf(stderr,"found parameter push with no function call\n");
1661 /* if the registers have been saved already then
1663 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1666 /* find the registers in use at this time
1667 and push them away to safety */
1668 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1672 if (options.useXstack) {
1673 if (bitVectBitValue(rsave,R0_IDX))
1674 emitcode("mov","b,r0");
1675 emitcode("mov","r0,%s",spname);
1676 for (i = 0 ; i < ds390_nRegs ; i++) {
1677 if (bitVectBitValue(rsave,i)) {
1679 emitcode("mov","a,b");
1681 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1682 emitcode("movx","@r0,a");
1683 emitcode("inc","r0");
1686 emitcode("mov","%s,r0",spname);
1687 if (bitVectBitValue(rsave,R0_IDX))
1688 emitcode("mov","r0,b");
1690 for (i = 0 ; i < ds390_nRegs ; i++) {
1691 if (bitVectBitValue(rsave,i))
1692 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1695 detype = getSpec(operandType(IC_LEFT(ic)));
1697 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1698 IS_ISR(currFunc->etype) &&
1701 saverbank(SPEC_BANK(detype),ic,TRUE);
1704 /*-----------------------------------------------------------------*/
1705 /* unsaveRegisters - pop the pushed registers */
1706 /*-----------------------------------------------------------------*/
1707 static void unsaveRegisters (iCode *ic)
1711 /* find the registers in use at this time
1712 and push them away to safety */
1713 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1716 if (options.useXstack) {
1717 emitcode("mov","r0,%s",spname);
1718 for (i = ds390_nRegs ; i >= 0 ; i--) {
1719 if (bitVectBitValue(rsave,i)) {
1720 emitcode("dec","r0");
1721 emitcode("movx","a,@r0");
1723 emitcode("mov","b,a");
1725 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1729 emitcode("mov","%s,r0",spname);
1730 if (bitVectBitValue(rsave,R0_IDX))
1731 emitcode("mov","r0,b");
1733 for (i = ds390_nRegs ; i >= 0 ; i--) {
1734 if (bitVectBitValue(rsave,i))
1735 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1741 /*-----------------------------------------------------------------*/
1743 /*-----------------------------------------------------------------*/
1744 static void pushSide(operand * oper, int size)
1747 _startLazyDPSEvaluation();
1749 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1750 if (AOP_TYPE(oper) != AOP_REG &&
1751 AOP_TYPE(oper) != AOP_DIR &&
1753 emitcode("mov","a,%s",l);
1754 emitcode("push","acc");
1756 emitcode("push","%s",l);
1758 _endLazyDPSEvaluation();
1761 /*-----------------------------------------------------------------*/
1762 /* assignResultValue - */
1763 /*-----------------------------------------------------------------*/
1764 static void assignResultValue(operand * oper)
1767 int size = AOP_SIZE(oper);
1769 _startLazyDPSEvaluation();
1771 aopPut(AOP(oper),fReturn[offset],offset);
1774 _endLazyDPSEvaluation();
1778 /*-----------------------------------------------------------------*/
1779 /* genXpush - pushes onto the external stack */
1780 /*-----------------------------------------------------------------*/
1781 static void genXpush (iCode *ic)
1783 asmop *aop = newAsmop(0);
1785 int size,offset = 0;
1787 D(emitcode(";", "genXpush "););
1789 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1790 r = getFreePtr(ic,&aop,FALSE);
1793 emitcode("mov","%s,_spx",r->name);
1795 size = AOP_SIZE(IC_LEFT(ic));
1796 _startLazyDPSEvaluation();
1799 char *l = aopGet(AOP(IC_LEFT(ic)),
1800 offset++,FALSE,FALSE,TRUE);
1802 emitcode("movx","@%s,a",r->name);
1803 emitcode("inc","%s",r->name);
1806 _endLazyDPSEvaluation();
1809 emitcode("mov","_spx,%s",r->name);
1811 freeAsmop(NULL,aop,ic,TRUE);
1812 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1815 /*-----------------------------------------------------------------*/
1816 /* genIpush - genrate code for pushing this gets a little complex */
1817 /*-----------------------------------------------------------------*/
1818 static void genIpush (iCode *ic)
1820 int size, offset = 0 ;
1823 D(emitcode(";", "genIpush "););
1826 /* if this is not a parm push : ie. it is spill push
1827 and spill push is always done on the local stack */
1828 if (!ic->parmPush) {
1830 /* and the item is spilt then do nothing */
1831 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1834 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1835 size = AOP_SIZE(IC_LEFT(ic));
1836 /* push it on the stack */
1837 _startLazyDPSEvaluation();
1839 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1844 emitcode("push","%s",l);
1846 _endLazyDPSEvaluation();
1850 /* this is a paramter push: in this case we call
1851 the routine to find the call and save those
1852 registers that need to be saved */
1855 /* if use external stack then call the external
1856 stack pushing routine */
1857 if (options.useXstack) {
1862 /* then do the push */
1863 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1865 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1866 size = AOP_SIZE(IC_LEFT(ic));
1868 _startLazyDPSEvaluation();
1870 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1871 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1872 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1874 emitcode("mov","a,%s",l);
1875 emitcode("push","acc");
1877 emitcode("push","%s",l);
1879 _endLazyDPSEvaluation();
1881 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1884 /*-----------------------------------------------------------------*/
1885 /* genIpop - recover the registers: can happen only for spilling */
1886 /*-----------------------------------------------------------------*/
1887 static void genIpop (iCode *ic)
1891 D(emitcode(";", "genIpop "););
1894 /* if the temp was not pushed then */
1895 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1898 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1899 size = AOP_SIZE(IC_LEFT(ic));
1901 _startLazyDPSEvaluation();
1904 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1907 _endLazyDPSEvaluation();
1909 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1912 /*-----------------------------------------------------------------*/
1913 /* unsaverbank - restores the resgister bank from stack */
1914 /*-----------------------------------------------------------------*/
1915 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1922 if (options.useXstack) {
1924 r = getFreePtr(ic,&aop,FALSE);
1927 emitcode("mov","%s,_spx",r->name);
1928 emitcode("movx","a,@%s",r->name);
1929 emitcode("mov","psw,a");
1930 emitcode("dec","%s",r->name);
1933 emitcode ("pop","psw");
1936 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1937 if (options.useXstack) {
1938 emitcode("movx","a,@%s",r->name);
1939 emitcode("mov","(%s+%d),a",
1940 regs390[i].base,8*bank+regs390[i].offset);
1941 emitcode("dec","%s",r->name);
1944 emitcode("pop","(%s+%d)",
1945 regs390[i].base,8*bank+regs390[i].offset);
1948 if (options.useXstack) {
1950 emitcode("mov","_spx,%s",r->name);
1951 freeAsmop(NULL,aop,ic,TRUE);
1956 /*-----------------------------------------------------------------*/
1957 /* saverbank - saves an entire register bank on the stack */
1958 /*-----------------------------------------------------------------*/
1959 static void saverbank (int bank, iCode *ic, bool pushPsw)
1965 if (options.useXstack) {
1968 r = getFreePtr(ic,&aop,FALSE);
1969 emitcode("mov","%s,_spx",r->name);
1973 for (i = 0 ; i < ds390_nRegs ;i++) {
1974 if (options.useXstack) {
1975 emitcode("inc","%s",r->name);
1976 emitcode("mov","a,(%s+%d)",
1977 regs390[i].base,8*bank+regs390[i].offset);
1978 emitcode("movx","@%s,a",r->name);
1980 emitcode("push","(%s+%d)",
1981 regs390[i].base,8*bank+regs390[i].offset);
1985 if (options.useXstack) {
1986 emitcode("mov","a,psw");
1987 emitcode("movx","@%s,a",r->name);
1988 emitcode("inc","%s",r->name);
1989 emitcode("mov","_spx,%s",r->name);
1990 freeAsmop (NULL,aop,ic,TRUE);
1993 emitcode("push","psw");
1995 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2001 /*-----------------------------------------------------------------*/
2002 /* genCall - generates a call statement */
2003 /*-----------------------------------------------------------------*/
2004 static void genCall (iCode *ic)
2008 D(emitcode(";", "genCall "););
2010 /* if caller saves & we have not saved then */
2014 /* if we are calling a function that is not using
2015 the same register bank then we need to save the
2016 destination registers on the stack */
2017 detype = getSpec(operandType(IC_LEFT(ic)));
2019 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2020 IS_ISR(currFunc->etype) &&
2023 saverbank(SPEC_BANK(detype),ic,TRUE);
2025 /* if send set is not empty the assign */
2029 for (sic = setFirstItem(_G.sendSet) ; sic ;
2030 sic = setNextItem(_G.sendSet))
2032 int size, offset = 0;
2034 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
2035 size = AOP_SIZE(IC_LEFT(sic));
2037 _startLazyDPSEvaluation();
2039 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2040 FALSE, FALSE, TRUE);
2041 if (strcmp(l,fReturn[offset]))
2042 emitcode("mov","%s,%s",
2047 _endLazyDPSEvaluation();
2048 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2053 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2054 OP_SYMBOL(IC_LEFT(ic))->rname :
2055 OP_SYMBOL(IC_LEFT(ic))->name));
2057 /* if we need assign a result value */
2058 if ((IS_ITEMP(IC_RESULT(ic)) &&
2059 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2060 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2061 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2064 /* Not really related to LAZY_DPS_OPT, but don't want
2065 * another testing flag right now...
2067 #define FAR_RETURN_OPT
2068 #ifdef FAR_RETURN_OPT
2069 if (isOperandInFarSpace(IC_RESULT(ic))
2070 && getSize(operandType(IC_RESULT(ic))) <= 2)
2072 int size = getSize(operandType(IC_RESULT(ic)));
2074 /* Special case for 1 or 2 byte return in far space. */
2075 emitcode(";", "Kevin function call abuse #1");
2080 emitcode("mov", "b,%s", fReturn[1]);
2083 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2084 aopPut(AOP(IC_RESULT(ic)),"a",0);
2088 aopPut(AOP(IC_RESULT(ic)),"b",1);
2090 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2096 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2099 assignResultValue(IC_RESULT(ic));
2101 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2104 if (!isOperandInFarSpace(IC_RESULT(ic)))
2107 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2110 assignResultValue(IC_RESULT(ic));
2112 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2116 /* Result is in far space, and requires DPTR to access
2117 * it. Push the result onto the stack and restore from
2120 int size = getSize(operandType(IC_RESULT(ic)));
2121 int offset = size - 1;
2124 emitcode(";", "Kevin function call abuse #1");
2126 /* first push the right side on to the stack */
2127 /* NB: this relies on the fact that "a" is the last
2128 * register in fReturn. If it were not, the MOVA
2129 * would potentially clobber a returned byte in A.
2132 l = fReturn[offset--];
2134 emitcode ("push","acc");
2137 /* now assign DPTR to result */
2138 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2139 size = AOP_SIZE(IC_RESULT(ic));
2140 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
2142 emitcode ("pop","acc");
2143 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
2145 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2150 /* adjust the stack for parameters if
2152 if (IC_LEFT(ic)->parmBytes) {
2154 if (IC_LEFT(ic)->parmBytes > 3) {
2155 emitcode("mov","a,%s",spname);
2156 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2157 emitcode("mov","%s,a",spname);
2159 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2160 emitcode("dec","%s",spname);
2164 /* if register bank was saved then pop them */
2166 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2168 /* if we hade saved some registers then unsave them */
2169 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2170 unsaveRegisters (ic);
2175 /*-----------------------------------------------------------------*/
2176 /* genPcall - generates a call by pointer statement */
2177 /*-----------------------------------------------------------------*/
2178 static void genPcall (iCode *ic)
2181 symbol *rlbl = newiTempLabel(NULL);
2183 D(emitcode(";", "genPcall "););
2186 /* if caller saves & we have not saved then */
2190 /* if we are calling a function that is not using
2191 the same register bank then we need to save the
2192 destination registers on the stack */
2193 detype = getSpec(operandType(IC_LEFT(ic)));
2195 IS_ISR(currFunc->etype) &&
2196 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2197 saverbank(SPEC_BANK(detype),ic,TRUE);
2200 /* push the return address on to the stack */
2201 emitcode("mov","a,#%05d$",(rlbl->key+100));
2202 emitcode("push","acc");
2203 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2204 emitcode("push","acc");
2206 if (options.model == MODEL_FLAT24)
2208 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2209 emitcode("push","acc");
2212 /* now push the calling address */
2213 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2215 pushSide(IC_LEFT(ic), FPTRSIZE);
2217 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2219 /* if send set is not empty the assign */
2223 for (sic = setFirstItem(_G.sendSet) ; sic ;
2224 sic = setNextItem(_G.sendSet))
2226 int size, offset = 0;
2228 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2229 size = AOP_SIZE(IC_LEFT(sic));
2230 _startLazyDPSEvaluation();
2233 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2235 if (strcmp(l,fReturn[offset]))
2237 emitcode("mov","%s,%s",
2243 _endLazyDPSEvaluation();
2244 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2250 emitcode("","%05d$:",(rlbl->key+100));
2253 /* if we need assign a result value */
2254 if ((IS_ITEMP(IC_RESULT(ic)) &&
2255 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2256 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2257 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2260 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2263 assignResultValue(IC_RESULT(ic));
2265 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2268 /* adjust the stack for parameters if
2270 if (IC_LEFT(ic)->parmBytes) {
2272 if (IC_LEFT(ic)->parmBytes > 3) {
2273 emitcode("mov","a,%s",spname);
2274 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2275 emitcode("mov","%s,a",spname);
2277 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2278 emitcode("dec","%s",spname);
2282 /* if register bank was saved then unsave them */
2284 (SPEC_BANK(currFunc->etype) !=
2286 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2288 /* if we hade saved some registers then
2291 unsaveRegisters (ic);
2295 /*-----------------------------------------------------------------*/
2296 /* resultRemat - result is rematerializable */
2297 /*-----------------------------------------------------------------*/
2298 static int resultRemat (iCode *ic)
2300 if (SKIP_IC(ic) || ic->op == IFX)
2303 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2304 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2305 if (sym->remat && !POINTER_SET(ic))
2312 #if defined(__BORLANDC__) || defined(_MSC_VER)
2313 #define STRCASECMP stricmp
2315 #define STRCASECMP strcasecmp
2318 /*-----------------------------------------------------------------*/
2319 /* inExcludeList - return 1 if the string is in exclude Reg list */
2320 /*-----------------------------------------------------------------*/
2321 static bool inExcludeList(char *s)
2325 if (options.excludeRegs[i] &&
2326 STRCASECMP(options.excludeRegs[i],"none") == 0)
2329 for ( i = 0 ; options.excludeRegs[i]; i++) {
2330 if (options.excludeRegs[i] &&
2331 STRCASECMP(s,options.excludeRegs[i]) == 0)
2337 /*-----------------------------------------------------------------*/
2338 /* genFunction - generated code for function entry */
2339 /*-----------------------------------------------------------------*/
2340 static void genFunction (iCode *ic)
2345 D(emitcode(";", "genFunction "););
2348 /* create the function header */
2349 emitcode(";","-----------------------------------------");
2350 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2351 emitcode(";","-----------------------------------------");
2353 emitcode("","%s:",sym->rname);
2354 fetype = getSpec(operandType(IC_LEFT(ic)));
2356 /* if critical function then turn interrupts off */
2357 if (SPEC_CRTCL(fetype))
2358 emitcode("clr","ea");
2360 /* here we need to generate the equates for the
2361 register bank if required */
2362 if (SPEC_BANK(fetype) != rbank) {
2365 rbank = SPEC_BANK(fetype);
2366 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2367 if (strcmp(regs390[i].base,"0") == 0)
2368 emitcode("","%s = 0x%02x",
2370 8*rbank+regs390[i].offset);
2372 emitcode ("","%s = %s + 0x%02x",
2375 8*rbank+regs390[i].offset);
2379 /* if this is an interrupt service routine then
2380 save acc, b, dpl, dph */
2381 if (IS_ISR(sym->etype)) {
2383 if (!inExcludeList("acc"))
2384 emitcode ("push","acc");
2385 if (!inExcludeList("b"))
2386 emitcode ("push","b");
2387 if (!inExcludeList("dpl"))
2388 emitcode ("push","dpl");
2389 if (!inExcludeList("dph"))
2390 emitcode ("push","dph");
2391 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2393 emitcode ("push", "dpx");
2394 /* Make sure we're using standard DPTR */
2395 emitcode ("push", "dps");
2396 emitcode ("mov", "dps, #0x00");
2397 if (options.stack10bit)
2399 /* This ISR could conceivably use DPTR2. Better save it. */
2400 emitcode ("push", "dpl1");
2401 emitcode ("push", "dph1");
2402 emitcode ("push", "dpx1");
2403 emitcode ("push", "ap");
2406 /* if this isr has no bank i.e. is going to
2407 run with bank 0 , then we need to save more
2409 if (!SPEC_BANK(sym->etype)) {
2411 /* if this function does not call any other
2412 function then we can be economical and
2413 save only those registers that are used */
2414 if (! sym->hasFcall) {
2417 /* if any registers used */
2418 if (sym->regsUsed) {
2419 /* save the registers used */
2420 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2421 if (bitVectBitValue(sym->regsUsed,i) ||
2422 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2423 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2428 /* this function has a function call cannot
2429 determines register usage so we will have the
2431 saverbank(0,ic,FALSE);
2435 /* if callee-save to be used for this function
2436 then save the registers being used in this function */
2437 if (sym->calleeSave) {
2440 /* if any registers used */
2441 if (sym->regsUsed) {
2442 /* save the registers used */
2443 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2444 if (bitVectBitValue(sym->regsUsed,i) ||
2445 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2446 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2454 /* set the register bank to the desired value */
2455 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2456 emitcode("push","psw");
2457 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2460 if (IS_RENT(sym->etype) || options.stackAuto) {
2462 if (options.useXstack) {
2463 emitcode("mov","r0,%s",spname);
2464 emitcode("mov","a,_bp");
2465 emitcode("movx","@r0,a");
2466 emitcode("inc","%s",spname);
2470 /* set up the stack */
2471 emitcode ("push","_bp"); /* save the callers stack */
2473 emitcode ("mov","_bp,%s",spname);
2476 /* adjust the stack for the function */
2481 werror(W_STACK_OVERFLOW,sym->name);
2483 if (i > 3 && sym->recvSize < 4) {
2485 emitcode ("mov","a,sp");
2486 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2487 emitcode ("mov","sp,a");
2492 emitcode("inc","sp");
2497 emitcode ("mov","a,_spx");
2498 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2499 emitcode ("mov","_spx,a");
2504 /*-----------------------------------------------------------------*/
2505 /* genEndFunction - generates epilogue for functions */
2506 /*-----------------------------------------------------------------*/
2507 static void genEndFunction (iCode *ic)
2509 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2511 D(emitcode(";", "genEndFunction "););
2513 if (IS_RENT(sym->etype) || options.stackAuto)
2515 emitcode ("mov","%s,_bp",spname);
2518 /* if use external stack but some variables were
2519 added to the local stack then decrement the
2521 if (options.useXstack && sym->stack) {
2522 emitcode("mov","a,sp");
2523 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2524 emitcode("mov","sp,a");
2528 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2529 if (options.useXstack) {
2530 emitcode("mov","r0,%s",spname);
2531 emitcode("movx","a,@r0");
2532 emitcode("mov","_bp,a");
2533 emitcode("dec","%s",spname);
2537 emitcode ("pop","_bp");
2541 /* restore the register bank */
2542 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2543 emitcode ("pop","psw");
2545 if (IS_ISR(sym->etype)) {
2547 /* now we need to restore the registers */
2548 /* if this isr has no bank i.e. is going to
2549 run with bank 0 , then we need to save more
2551 if (!SPEC_BANK(sym->etype)) {
2553 /* if this function does not call any other
2554 function then we can be economical and
2555 save only those registers that are used */
2556 if (! sym->hasFcall) {
2559 /* if any registers used */
2560 if (sym->regsUsed) {
2561 /* save the registers used */
2562 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2563 if (bitVectBitValue(sym->regsUsed,i) ||
2564 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2565 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2570 /* this function has a function call cannot
2571 determines register usage so we will have the
2573 unsaverbank(0,ic,FALSE);
2577 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2579 if (options.stack10bit)
2581 emitcode ("pop", "ap");
2582 emitcode ("pop", "dpx1");
2583 emitcode ("pop", "dph1");
2584 emitcode ("pop", "dpl1");
2586 emitcode ("pop", "dps");
2587 emitcode ("pop", "dpx");
2589 if (!inExcludeList("dph"))
2590 emitcode ("pop","dph");
2591 if (!inExcludeList("dpl"))
2592 emitcode ("pop","dpl");
2593 if (!inExcludeList("b"))
2594 emitcode ("pop","b");
2595 if (!inExcludeList("acc"))
2596 emitcode ("pop","acc");
2598 if (SPEC_CRTCL(sym->etype))
2599 emitcode("setb","ea");
2601 /* if debug then send end of function */
2602 /* if (options.debug && currFunc) { */
2605 emitcode("","C$%s$%d$%d$%d ==.",
2606 ic->filename,currFunc->lastLine,
2607 ic->level,ic->block);
2608 if (IS_STATIC(currFunc->etype))
2609 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2611 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2615 emitcode ("reti","");
2618 if (SPEC_CRTCL(sym->etype))
2619 emitcode("setb","ea");
2621 if (sym->calleeSave) {
2624 /* if any registers used */
2625 if (sym->regsUsed) {
2626 /* save the registers used */
2627 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2628 if (bitVectBitValue(sym->regsUsed,i) ||
2629 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2630 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2636 /* if debug then send end of function */
2639 emitcode("","C$%s$%d$%d$%d ==.",
2640 ic->filename,currFunc->lastLine,
2641 ic->level,ic->block);
2642 if (IS_STATIC(currFunc->etype))
2643 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2645 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2649 emitcode ("ret","");
2654 /*-----------------------------------------------------------------*/
2655 /* genRet - generate code for return statement */
2656 /*-----------------------------------------------------------------*/
2657 static void genRet (iCode *ic)
2659 int size,offset = 0 , pushed = 0;
2661 D(emitcode(";", "genRet "););
2663 /* if we have no return value then
2664 just generate the "ret" */
2668 /* we have something to return then
2669 move the return value into place */
2670 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2671 size = AOP_SIZE(IC_LEFT(ic));
2673 _startLazyDPSEvaluation();
2676 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2677 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2679 emitcode("push","%s",l);
2682 l = aopGet(AOP(IC_LEFT(ic)),offset,
2684 if (strcmp(fReturn[offset],l))
2685 emitcode("mov","%s,%s",fReturn[offset++],l);
2688 _endLazyDPSEvaluation();
2693 if (strcmp(fReturn[pushed],"a"))
2694 emitcode("pop",fReturn[pushed]);
2696 emitcode("pop","acc");
2699 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2702 /* generate a jump to the return label
2703 if the next is not the return statement */
2704 if (!(ic->next && ic->next->op == LABEL &&
2705 IC_LABEL(ic->next) == returnLabel))
2707 emitcode("ljmp","%05d$",(returnLabel->key+100));
2711 /*-----------------------------------------------------------------*/
2712 /* genLabel - generates a label */
2713 /*-----------------------------------------------------------------*/
2714 static void genLabel (iCode *ic)
2716 /* special case never generate */
2717 if (IC_LABEL(ic) == entryLabel)
2720 D(emitcode(";", "genLabel "););
2722 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2725 /*-----------------------------------------------------------------*/
2726 /* genGoto - generates a ljmp */
2727 /*-----------------------------------------------------------------*/
2728 static void genGoto (iCode *ic)
2730 D(emitcode(";", "genGoto "););
2731 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2734 /*-----------------------------------------------------------------*/
2735 /* findLabelBackwards: walks back through the iCode chain looking */
2736 /* for the given label. Returns number of iCode instructions */
2737 /* between that label and given ic. */
2738 /* Returns zero if label not found. */
2739 /*-----------------------------------------------------------------*/
2740 static int findLabelBackwards(iCode *ic, int key)
2749 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2751 /* printf("findLabelBackwards = %d\n", count); */
2759 /*-----------------------------------------------------------------*/
2760 /* genPlusIncr :- does addition with increment if possible */
2761 /*-----------------------------------------------------------------*/
2762 static bool genPlusIncr (iCode *ic)
2764 unsigned int icount ;
2765 unsigned int size = getDataSize(IC_RESULT(ic));
2767 /* will try to generate an increment */
2768 /* if the right side is not a literal
2770 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2773 /* if the literal value of the right hand side
2774 is greater than 4 then it is not worth it */
2775 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2778 /* if increment 16 bits in register */
2780 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2781 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2782 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2789 /* If the next instruction is a goto and the goto target
2790 * is <= 5 instructions previous to this, we can generate
2791 * jumps straight to that target.
2793 if (ic->next && ic->next->op == GOTO
2794 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2795 && labelRange <= 5 )
2797 emitcode(";", "tail increment optimized (range %d)", labelRange);
2798 tlbl = IC_LABEL(ic->next);
2803 tlbl = newiTempLabel(NULL);
2806 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2807 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2808 IS_AOP_PREG(IC_RESULT(ic)))
2809 emitcode("cjne","%s,#0x00,%05d$"
2810 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2813 emitcode("clr","a");
2814 emitcode("cjne","a,%s,%05d$"
2815 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2819 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2822 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2823 IS_AOP_PREG(IC_RESULT(ic)))
2824 emitcode("cjne","%s,#0x00,%05d$"
2825 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2828 emitcode("cjne","a,%s,%05d$"
2829 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2832 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2836 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2837 IS_AOP_PREG(IC_RESULT(ic)))
2838 emitcode("cjne","%s,#0x00,%05d$"
2839 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2842 emitcode("cjne","a,%s,%05d$"
2843 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2846 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2851 emitcode("","%05d$:",tlbl->key+100);
2856 /* if the sizes are greater than 1 then we cannot */
2857 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2858 AOP_SIZE(IC_LEFT(ic)) > 1 )
2861 /* we can if the aops of the left & result match or
2862 if they are in registers and the registers are the
2865 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2866 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2867 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2870 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2871 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2872 aopPut(AOP(IC_RESULT(ic)),"a",0);
2875 _startLazyDPSEvaluation();
2878 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2880 _endLazyDPSEvaluation();
2889 /*-----------------------------------------------------------------*/
2890 /* outBitAcc - output a bit in acc */
2891 /*-----------------------------------------------------------------*/
2892 static void outBitAcc(operand *result)
2894 symbol *tlbl = newiTempLabel(NULL);
2895 /* if the result is a bit */
2896 if (AOP_TYPE(result) == AOP_CRY){
2897 aopPut(AOP(result),"a",0);
2900 emitcode("jz","%05d$",tlbl->key+100);
2901 emitcode("mov","a,%s",one);
2902 emitcode("","%05d$:",tlbl->key+100);
2907 /*-----------------------------------------------------------------*/
2908 /* genPlusBits - generates code for addition of two bits */
2909 /*-----------------------------------------------------------------*/
2910 static void genPlusBits (iCode *ic)
2912 D(emitcode(";", "genPlusBits "););
2913 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2914 symbol *lbl = newiTempLabel(NULL);
2915 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2916 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2917 emitcode("cpl","c");
2918 emitcode("","%05d$:",(lbl->key+100));
2919 outBitC(IC_RESULT(ic));
2922 emitcode("clr","a");
2923 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2924 emitcode("rlc","a");
2925 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2926 emitcode("addc","a,#0x00");
2927 outAcc(IC_RESULT(ic));
2931 static void adjustArithmeticResult(iCode *ic)
2933 if (opIsGptr(IC_RESULT(ic)) &&
2934 opIsGptr(IC_LEFT(ic)) &&
2935 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2937 aopPut(AOP(IC_RESULT(ic)),
2938 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2942 if (opIsGptr(IC_RESULT(ic)) &&
2943 opIsGptr(IC_RIGHT(ic)) &&
2944 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2946 aopPut(AOP(IC_RESULT(ic)),
2947 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2951 if (opIsGptr(IC_RESULT(ic)) &&
2952 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2953 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2954 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2955 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2957 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2958 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2963 #define AOP_OP_3(ic) \
2964 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2965 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2966 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2967 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2968 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2970 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2972 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2975 #define AOP_OP_3(ic) \
2976 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2977 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2978 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
2979 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2980 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2981 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2983 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2985 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2988 #define AOP_OP_3_NOFATAL(ic, rc) \
2989 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2990 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2991 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2992 isOperandInFarSpace(IC_RESULT(ic))) \
2994 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
2999 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3000 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3002 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3003 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3005 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3007 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3011 #define AOP_OP_2(ic) \
3012 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3013 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3018 #define AOP_SET_LOCALS(ic) \
3019 left = IC_LEFT(ic); \
3020 right = IC_RIGHT(ic); \
3021 result = IC_RESULT(ic);
3023 /*-----------------------------------------------------------------*/
3024 /* genPlus - generates code for addition */
3025 /*-----------------------------------------------------------------*/
3026 static void genPlus (iCode *ic)
3028 int size, offset = 0;
3029 bool pushResult = FALSE;
3032 D(emitcode(";", "genPlus "););
3034 /* special cases :- */
3037 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
3038 aopOp (IC_LEFT(ic),ic,FALSE,
3039 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3040 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
3041 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
3047 aopOp (IC_RESULT(ic),ic,TRUE,
3048 ((AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)
3049 || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR)));
3052 AOP_OP_3_NOFATAL(ic, pushResult);
3055 D(emitcode(";", "genPlus: must push result: 3 ops in far space"););
3061 /* if literal, literal on the right or
3062 if left requires ACC or right is already
3064 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)
3065 || ((AOP_NEEDSACC(IC_LEFT(ic))) && !(AOP_NEEDSACC(IC_RIGHT(ic))))
3066 || AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC )
3068 operand *t = IC_RIGHT(ic);
3069 IC_RIGHT(ic) = IC_LEFT(ic);
3071 emitcode(";", "Swapped plus args.");
3074 /* if both left & right are in bit
3076 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3077 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3082 /* if left in bit space & right literal */
3083 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3084 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3085 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3086 /* if result in bit space */
3087 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3088 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
3089 emitcode("cpl","c");
3090 outBitC(IC_RESULT(ic));
3092 size = getDataSize(IC_RESULT(ic));
3093 _startLazyDPSEvaluation();
3095 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3096 emitcode("addc","a,#00");
3097 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3099 _endLazyDPSEvaluation();
3104 /* if I can do an increment instead
3105 of add then GOOD for ME */
3106 if (genPlusIncr (ic) == TRUE)
3108 emitcode(";", "did genPlusIncr");
3113 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3115 _startLazyDPSEvaluation();
3118 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3120 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3122 emitcode("add","a,%s",
3123 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3125 emitcode("addc","a,%s",
3126 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3128 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3130 emitcode("add","a,%s",
3131 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3133 emitcode("addc","a,%s",
3134 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3138 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3142 emitcode("push", "acc");
3146 _endLazyDPSEvaluation();
3150 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3152 size = getDataSize(IC_LEFT(ic));
3153 rSize = getDataSize(IC_RESULT(ic));
3155 /* If the pushed data is bigger than the result,
3156 * simply discard unused bytes. Icky, but works.
3158 * Should we throw a warning here? We're losing data...
3160 while (size > rSize)
3162 D(emitcode(";", "discarding unused result byte."););
3163 emitcode("pop", "acc");
3169 emitcode("clr", "a");
3170 /* Conversly, we haven't pushed enough here.
3171 * just zero-pad, and all is well.
3173 while (size < rSize)
3175 emitcode("push", "acc");
3181 _startLazyDPSEvaluation();
3184 emitcode("pop", "acc");
3185 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3187 _endLazyDPSEvaluation();
3190 adjustArithmeticResult(ic);
3193 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3194 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3195 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3198 /*-----------------------------------------------------------------*/
3199 /* genMinusDec :- does subtraction with deccrement if possible */
3200 /*-----------------------------------------------------------------*/
3201 static bool genMinusDec (iCode *ic)
3203 unsigned int icount ;
3204 unsigned int size = getDataSize(IC_RESULT(ic));
3206 /* will try to generate an increment */
3207 /* if the right side is not a literal
3209 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3212 /* if the literal value of the right hand side
3213 is greater than 4 then it is not worth it */
3214 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3217 /* if decrement 16 bits in register */
3218 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3219 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3220 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3227 /* If the next instruction is a goto and the goto target
3228 * is <= 5 instructions previous to this, we can generate
3229 * jumps straight to that target.
3231 if (ic->next && ic->next->op == GOTO
3232 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3233 && labelRange <= 5 )
3235 emitcode(";", "tail decrement optimized (range %d)", labelRange);
3236 tlbl = IC_LABEL(ic->next);
3241 tlbl = newiTempLabel(NULL);
3245 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3246 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3247 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3248 IS_AOP_PREG(IC_RESULT(ic)))
3249 emitcode("cjne","%s,#0xff,%05d$"
3250 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3253 emitcode("mov","a,#0xff");
3254 emitcode("cjne","a,%s,%05d$"
3255 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3258 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3261 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3262 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3263 IS_AOP_PREG(IC_RESULT(ic)))
3264 emitcode("cjne","%s,#0xff,%05d$"
3265 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3268 emitcode("cjne","a,%s,%05d$"
3269 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3272 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3276 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3277 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3278 IS_AOP_PREG(IC_RESULT(ic)))
3279 emitcode("cjne","%s,#0xff,%05d$"
3280 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3283 emitcode("cjne","a,%s,%05d$"
3284 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3287 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3291 emitcode("","%05d$:",tlbl->key+100);
3296 /* if the sizes are greater than 1 then we cannot */
3297 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3298 AOP_SIZE(IC_LEFT(ic)) > 1 )
3301 /* we can if the aops of the left & result match or
3302 if they are in registers and the registers are the
3305 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3306 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3307 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3309 _startLazyDPSEvaluation();
3312 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3314 _endLazyDPSEvaluation();
3322 /*-----------------------------------------------------------------*/
3323 /* addSign - complete with sign */
3324 /*-----------------------------------------------------------------*/
3325 static void addSign(operand *result, int offset, int sign)
3327 int size = (getDataSize(result) - offset);
3330 emitcode("rlc","a");
3331 emitcode("subb","a,acc");
3333 aopPut(AOP(result),"a",offset++);
3336 aopPut(AOP(result),zero,offset++);
3340 /*-----------------------------------------------------------------*/
3341 /* genMinusBits - generates code for subtraction of two bits */
3342 /*-----------------------------------------------------------------*/
3343 static void genMinusBits (iCode *ic)
3345 symbol *lbl = newiTempLabel(NULL);
3347 D(emitcode(";", "genMinusBits "););
3349 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3350 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3351 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3352 emitcode("cpl","c");
3353 emitcode("","%05d$:",(lbl->key+100));
3354 outBitC(IC_RESULT(ic));
3357 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3358 emitcode("subb","a,acc");
3359 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3360 emitcode("inc","a");
3361 emitcode("","%05d$:",(lbl->key+100));
3362 aopPut(AOP(IC_RESULT(ic)),"a",0);
3363 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3367 /*-----------------------------------------------------------------*/
3368 /* genMinus - generates code for subtraction */
3369 /*-----------------------------------------------------------------*/
3370 static void genMinus (iCode *ic)
3372 int size, offset = 0;
3374 unsigned long lit = 0L;
3375 bool pushResult = FALSE;
3377 D(emitcode(";", "genMinus "););
3379 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3380 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3381 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3382 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3388 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3390 /* special cases :- */
3391 /* if both left & right are in bit space */
3392 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3393 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3398 /* if I can do an decrement instead
3399 of subtract then GOOD for ME */
3400 if (genMinusDec (ic) == TRUE)
3405 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3407 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3411 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3416 /* if literal, add a,#-lit, else normal subb */
3417 _startLazyDPSEvaluation();
3419 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3420 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3421 emitcode("subb","a,%s",
3422 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3424 /* first add without previous c */
3426 emitcode("add","a,#0x%02x",
3427 (unsigned int)(lit & 0x0FFL));
3429 emitcode("addc","a,#0x%02x",
3430 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3435 emitcode("push", "acc");
3439 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3443 _endLazyDPSEvaluation();
3447 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3449 size = getDataSize(IC_LEFT(ic));
3450 rSize = getDataSize(IC_RESULT(ic));
3452 /* If the pushed data is bigger than the result,
3453 * simply discard unused bytes. Icky, but works.
3455 * Should we throw a warning here? We're losing data...
3457 while (size > getDataSize(IC_RESULT(ic)))
3459 emitcode(";", "discarding unused result byte.");
3460 emitcode("pop", "acc");
3466 emitcode("clr", "a");
3467 /* Conversly, we haven't pushed enough here.
3468 * just zero-pad, and all is well.
3470 while (size < rSize)
3472 emitcode("push", "acc");
3480 emitcode("pop", "acc");
3481 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3485 adjustArithmeticResult(ic);
3488 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3489 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3490 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3494 /*-----------------------------------------------------------------*/
3495 /* genMultbits :- multiplication of bits */
3496 /*-----------------------------------------------------------------*/
3497 static void genMultbits (operand *left,
3501 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3502 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3507 /*-----------------------------------------------------------------*/
3508 /* genMultOneByte : 8 bit multiplication & division */
3509 /*-----------------------------------------------------------------*/
3510 static void genMultOneByte (operand *left,
3514 sym_link *opetype = operandType(result);
3519 /* (if two literals, the value is computed before) */
3520 /* if one literal, literal on the right */
3521 if (AOP_TYPE(left) == AOP_LIT){
3527 size = AOP_SIZE(result);
3528 /* signed or unsigned */
3529 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3530 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3532 emitcode("mul","ab");
3533 /* if result size = 1, mul signed = mul unsigned */
3534 aopPut(AOP(result),"a",0);
3536 if (SPEC_USIGN(opetype)){
3537 aopPut(AOP(result),"b",1);
3539 /* for filling the MSBs */
3540 emitcode("clr","a");
3543 emitcode("mov","a,b");
3545 /* adjust the MSB if left or right neg */
3547 /* if one literal */
3548 if (AOP_TYPE(right) == AOP_LIT){
3549 /* AND literal negative */
3550 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3551 /* adjust MSB (c==0 after mul) */
3552 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3556 lbl = newiTempLabel(NULL);
3557 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3558 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3559 emitcode("","%05d$:",(lbl->key+100));
3560 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3561 lbl = newiTempLabel(NULL);
3562 emitcode("jc","%05d$",(lbl->key+100));
3563 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3564 emitcode("","%05d$:",(lbl->key+100));
3567 lbl = newiTempLabel(NULL);
3568 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3569 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3570 emitcode("","%05d$:",(lbl->key+100));
3571 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3572 lbl = newiTempLabel(NULL);
3573 emitcode("jc","%05d$",(lbl->key+100));
3574 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3575 emitcode("","%05d$:",(lbl->key+100));
3577 aopPut(AOP(result),"a",1);
3580 emitcode("rlc","a");
3581 emitcode("subb","a,acc");
3588 aopPut(AOP(result),"a",offset++);
3592 /*-----------------------------------------------------------------*/
3593 /* genMult - generates code for multiplication */
3594 /*-----------------------------------------------------------------*/
3595 static void genMult (iCode *ic)
3597 operand *left = IC_LEFT(ic);
3598 operand *right = IC_RIGHT(ic);
3599 operand *result= IC_RESULT(ic);
3601 D(emitcode(";", "genMult "););
3603 /* assign the amsops */
3606 aopOp (left,ic,FALSE, FALSE);
3607 aopOp (right,ic,FALSE, TRUE);
3608 aopOp (result,ic,TRUE, FALSE);
3611 /* special cases first */
3613 if (AOP_TYPE(left) == AOP_CRY &&
3614 AOP_TYPE(right)== AOP_CRY) {
3615 genMultbits(left,right,result);
3619 /* if both are of size == 1 */
3620 if (AOP_SIZE(left) == 1 &&
3621 AOP_SIZE(right) == 1 ) {
3622 genMultOneByte(left,right,result);
3626 /* should have been converted to function call */
3630 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3631 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3632 freeAsmop(result,NULL,ic,TRUE);
3635 /*-----------------------------------------------------------------*/
3636 /* genDivbits :- division of bits */
3637 /*-----------------------------------------------------------------*/
3638 static void genDivbits (operand *left,
3645 /* the result must be bit */
3646 LOAD_AB_FOR_DIV(left, right, l);
3647 emitcode("div","ab");
3648 emitcode("rrc","a");
3649 aopPut(AOP(result),"c",0);
3652 /*-----------------------------------------------------------------*/
3653 /* genDivOneByte : 8 bit division */
3654 /*-----------------------------------------------------------------*/
3655 static void genDivOneByte (operand *left,
3659 sym_link *opetype = operandType(result);
3664 size = AOP_SIZE(result) - 1;
3666 /* signed or unsigned */
3667 if (SPEC_USIGN(opetype)) {
3668 /* unsigned is easy */
3669 LOAD_AB_FOR_DIV(left, right, l);
3670 emitcode("div","ab");
3671 aopPut(AOP(result),"a",0);
3673 aopPut(AOP(result),zero,offset++);
3677 /* signed is a little bit more difficult */
3679 /* save the signs of the operands */
3680 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3682 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3683 emitcode("push","acc"); /* save it on the stack */
3685 /* now sign adjust for both left & right */
3686 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3688 lbl = newiTempLabel(NULL);
3689 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3690 emitcode("cpl","a");
3691 emitcode("inc","a");
3692 emitcode("","%05d$:",(lbl->key+100));
3693 emitcode("mov","b,a");
3695 /* sign adjust left side */
3696 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3699 lbl = newiTempLabel(NULL);
3700 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3701 emitcode("cpl","a");
3702 emitcode("inc","a");
3703 emitcode("","%05d$:",(lbl->key+100));
3705 /* now the division */
3706 emitcode("nop", "; workaround for DS80C390 div bug.");
3707 emitcode("div","ab");
3708 /* we are interested in the lower order
3710 emitcode("mov","b,a");
3711 lbl = newiTempLabel(NULL);
3712 emitcode("pop","acc");
3713 /* if there was an over flow we don't
3714 adjust the sign of the result */
3715 emitcode("jb","ov,%05d$",(lbl->key+100));
3716 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3718 emitcode("clr","a");
3719 emitcode("subb","a,b");
3720 emitcode("mov","b,a");
3721 emitcode("","%05d$:",(lbl->key+100));
3723 /* now we are done */
3724 aopPut(AOP(result),"b",0);
3726 emitcode("mov","c,b.7");
3727 emitcode("subb","a,acc");
3730 aopPut(AOP(result),"a",offset++);
3734 /*-----------------------------------------------------------------*/
3735 /* genDiv - generates code for division */
3736 /*-----------------------------------------------------------------*/
3737 static void genDiv (iCode *ic)
3739 operand *left = IC_LEFT(ic);
3740 operand *right = IC_RIGHT(ic);
3741 operand *result= IC_RESULT(ic);
3743 D(emitcode(";", "genDiv "););
3745 /* assign the amsops */
3748 aopOp (left,ic,FALSE, FALSE);
3749 aopOp (right,ic,FALSE, TRUE);
3750 aopOp (result,ic,TRUE, FALSE);
3753 /* special cases first */
3755 if (AOP_TYPE(left) == AOP_CRY &&
3756 AOP_TYPE(right)== AOP_CRY) {
3757 genDivbits(left,right,result);
3761 /* if both are of size == 1 */
3762 if (AOP_SIZE(left) == 1 &&
3763 AOP_SIZE(right) == 1 ) {
3764 genDivOneByte(left,right,result);
3768 /* should have been converted to function call */
3771 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3772 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3773 freeAsmop(result,NULL,ic,TRUE);
3776 /*-----------------------------------------------------------------*/
3777 /* genModbits :- modulus of bits */
3778 /*-----------------------------------------------------------------*/
3779 static void genModbits (operand *left,
3786 /* the result must be bit */
3787 LOAD_AB_FOR_DIV(left, right, l);
3788 emitcode("div","ab");
3789 emitcode("mov","a,b");
3790 emitcode("rrc","a");
3791 aopPut(AOP(result),"c",0);
3794 /*-----------------------------------------------------------------*/
3795 /* genModOneByte : 8 bit modulus */
3796 /*-----------------------------------------------------------------*/
3797 static void genModOneByte (operand *left,
3801 sym_link *opetype = operandType(result);
3805 /* signed or unsigned */
3806 if (SPEC_USIGN(opetype)) {
3807 /* unsigned is easy */
3808 LOAD_AB_FOR_DIV(left, right, l);
3809 emitcode("div","ab");
3810 aopPut(AOP(result),"b",0);
3814 /* signed is a little bit more difficult */
3816 /* save the signs of the operands */
3817 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3820 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3821 emitcode("push","acc"); /* save it on the stack */
3823 /* now sign adjust for both left & right */
3824 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3827 lbl = newiTempLabel(NULL);
3828 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3829 emitcode("cpl","a");
3830 emitcode("inc","a");
3831 emitcode("","%05d$:",(lbl->key+100));
3832 emitcode("mov","b,a");
3834 /* sign adjust left side */
3835 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3838 lbl = newiTempLabel(NULL);
3839 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3840 emitcode("cpl","a");
3841 emitcode("inc","a");
3842 emitcode("","%05d$:",(lbl->key+100));
3844 /* now the multiplication */
3845 emitcode("nop", "; workaround for DS80C390 div bug.");
3846 emitcode("div","ab");
3847 /* we are interested in the lower order
3849 lbl = newiTempLabel(NULL);
3850 emitcode("pop","acc");
3851 /* if there was an over flow we don't
3852 adjust the sign of the result */
3853 emitcode("jb","ov,%05d$",(lbl->key+100));
3854 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3856 emitcode("clr","a");
3857 emitcode("subb","a,b");
3858 emitcode("mov","b,a");
3859 emitcode("","%05d$:",(lbl->key+100));
3861 /* now we are done */
3862 aopPut(AOP(result),"b",0);
3866 /*-----------------------------------------------------------------*/
3867 /* genMod - generates code for division */
3868 /*-----------------------------------------------------------------*/
3869 static void genMod (iCode *ic)
3871 operand *left = IC_LEFT(ic);
3872 operand *right = IC_RIGHT(ic);
3873 operand *result= IC_RESULT(ic);
3875 D(emitcode(";", "genMod "););
3877 /* assign the amsops */
3880 aopOp (left,ic,FALSE, FALSE);
3881 aopOp (right,ic,FALSE, TRUE);
3882 aopOp (result,ic,TRUE, FALSE);
3885 /* special cases first */
3887 if (AOP_TYPE(left) == AOP_CRY &&
3888 AOP_TYPE(right)== AOP_CRY) {
3889 genModbits(left,right,result);
3893 /* if both are of size == 1 */
3894 if (AOP_SIZE(left) == 1 &&
3895 AOP_SIZE(right) == 1 ) {
3896 genModOneByte(left,right,result);
3900 /* should have been converted to function call */
3904 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3905 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3906 freeAsmop(result,NULL,ic,TRUE);
3909 /*-----------------------------------------------------------------*/
3910 /* genIfxJump :- will create a jump depending on the ifx */
3911 /*-----------------------------------------------------------------*/
3912 static void genIfxJump (iCode *ic, char *jval)
3915 symbol *tlbl = newiTempLabel(NULL);
3918 D(emitcode(";", "genIfxJump "););
3920 /* if true label then we jump if condition
3922 if ( IC_TRUE(ic) ) {
3924 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3925 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3928 /* false label is present */
3929 jlbl = IC_FALSE(ic) ;
3930 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3931 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3933 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3934 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3936 emitcode(inst,"%05d$",tlbl->key+100);
3937 emitcode("ljmp","%05d$",jlbl->key+100);
3938 emitcode("","%05d$:",tlbl->key+100);
3940 /* mark the icode as generated */
3944 /*-----------------------------------------------------------------*/
3945 /* genCmp :- greater or less than comparison */
3946 /*-----------------------------------------------------------------*/
3947 static void genCmp (operand *left,operand *right,
3948 iCode *ic, iCode *ifx, int sign)
3950 int size, offset = 0 ;
3951 unsigned long lit = 0L;
3954 D(emitcode(";", "genCmp"););
3956 result = IC_RESULT(ic);
3958 /* if left & right are bit variables */
3959 if (AOP_TYPE(left) == AOP_CRY &&
3960 AOP_TYPE(right) == AOP_CRY ) {
3961 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3962 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3964 /* subtract right from left if at the
3965 end the carry flag is set then we know that
3966 left is greater than right */
3967 size = max(AOP_SIZE(left),AOP_SIZE(right));
3969 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3970 if((size == 1) && !sign &&
3971 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3972 symbol *lbl = newiTempLabel(NULL);
3973 emitcode("cjne","%s,%s,%05d$",
3974 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3975 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3977 emitcode("","%05d$:",lbl->key+100);
3979 if (AOP_TYPE(right) == AOP_LIT)
3981 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3982 /* optimize if(x < 0) or if(x >= 0) */
3991 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3993 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3994 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3996 aopOp(result,ic,FALSE, FALSE);
3998 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx)
4000 freeAsmop(result,NULL,ic,TRUE);
4001 genIfxJump (ifx,"acc.7");
4006 emitcode("rlc","a");
4008 goto release_freedLR;
4016 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
4017 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4018 emitcode(";", "genCmp #2");
4019 if (sign && (size == 0))
4021 emitcode(";", "genCmp #3");
4022 emitcode("xrl","a,#0x80");
4023 if (AOP_TYPE(right) == AOP_LIT)
4025 unsigned long lit = (unsigned long)
4026 floatFromVal(AOP(right)->aopu.aop_lit);
4027 emitcode(";", "genCmp #3.1");
4028 emitcode("subb","a,#0x%02x",
4029 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
4033 emitcode(";", "genCmp #3.2");
4034 if (AOP_NEEDSACC(right))
4036 emitcode("push", "acc");
4038 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
4039 FALSE,FALSE,FALSE));
4040 emitcode("xrl","b,#0x80");
4041 if (AOP_NEEDSACC(right))
4043 emitcode("pop", "acc");
4045 emitcode("subb","a,b");
4052 emitcode(";", "genCmp #4");
4053 if (AOP_NEEDSACC(right))
4056 emitcode(";", "genCmp #4.1");
4057 emitcode("xch", "a, b");
4058 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
4059 emitcode("xch", "a, b");
4064 emitcode(";", "genCmp #4.2");
4065 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
4068 emitcode("subb","a,%s",s);
4075 /* Don't need the left & right operands any more; do need the result. */
4076 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4077 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4079 aopOp(result,ic,FALSE, FALSE);
4083 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result))
4089 /* if the result is used in the next
4090 ifx conditional branch then generate
4091 code a little differently */
4094 genIfxJump (ifx,"c");
4100 /* leave the result in acc */
4102 freeAsmop(result,NULL,ic,TRUE);
4105 /*-----------------------------------------------------------------*/
4106 /* genCmpGt :- greater than comparison */
4107 /*-----------------------------------------------------------------*/
4108 static void genCmpGt (iCode *ic, iCode *ifx)
4110 operand *left, *right;
4111 sym_link *letype , *retype;
4114 D(emitcode(";", "genCmpGt "););
4117 right= IC_RIGHT(ic);
4119 letype = getSpec(operandType(left));
4120 retype =getSpec(operandType(right));
4121 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4123 /* assign the left & right amsops */
4126 genCmp(right, left, ic, ifx, sign);
4129 /*-----------------------------------------------------------------*/
4130 /* genCmpLt - less than comparisons */
4131 /*-----------------------------------------------------------------*/
4132 static void genCmpLt (iCode *ic, iCode *ifx)
4134 operand *left, *right;
4135 sym_link *letype , *retype;
4138 D(emitcode(";", "genCmpLt "););
4141 right= IC_RIGHT(ic);
4143 letype = getSpec(operandType(left));
4144 retype =getSpec(operandType(right));
4145 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4147 /* assign the left & right amsops */
4150 genCmp(left, right, ic, ifx, sign);
4153 /*-----------------------------------------------------------------*/
4154 /* gencjneshort - compare and jump if not equal */
4155 /*-----------------------------------------------------------------*/
4156 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4158 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4160 unsigned long lit = 0L;
4162 D(emitcode(";", "gencjneshort"););
4164 /* if the left side is a literal or
4165 if the right is in a pointer register and left
4167 if ((AOP_TYPE(left) == AOP_LIT) ||
4168 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4174 if(AOP_TYPE(right) == AOP_LIT)
4175 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4177 if (opIsGptr(left) || opIsGptr(right))
4179 /* We are comparing a generic pointer to something.
4180 * Exclude the generic type byte from the comparison.
4183 D(emitcode(";", "cjneshort: generic ptr special case.");)
4187 /* if the right side is a literal then anything goes */
4188 if (AOP_TYPE(right) == AOP_LIT &&
4189 AOP_TYPE(left) != AOP_DIR ) {
4191 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4193 emitcode("cjne","a,%s,%05d$",
4194 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4200 /* if the right side is in a register or in direct space or
4201 if the left is a pointer register & right is not */
4202 else if (AOP_TYPE(right) == AOP_REG ||
4203 AOP_TYPE(right) == AOP_DIR ||
4204 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4205 (IS_AOP_PREG(left) && !IS_AOP_PREG(right)))
4209 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4210 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4211 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4212 emitcode("jnz","%05d$",lbl->key+100);
4214 emitcode("cjne","a,%s,%05d$",
4215 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4220 /* right is a pointer reg need both a & b */
4222 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4224 emitcode("mov","b,%s",l);
4225 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4226 emitcode("cjne","a,b,%05d$",lbl->key+100);
4232 /*-----------------------------------------------------------------*/
4233 /* gencjne - compare and jump if not equal */
4234 /*-----------------------------------------------------------------*/
4235 static void gencjne(operand *left, operand *right, symbol *lbl)
4237 symbol *tlbl = newiTempLabel(NULL);
4239 D(emitcode(";", "gencjne"););
4241 gencjneshort(left, right, lbl);
4243 emitcode("mov","a,%s",one);
4244 emitcode("sjmp","%05d$",tlbl->key+100);
4245 emitcode("","%05d$:",lbl->key+100);
4246 emitcode("clr","a");
4247 emitcode("","%05d$:",tlbl->key+100);
4250 /*-----------------------------------------------------------------*/
4251 /* genCmpEq - generates code for equal to */
4252 /*-----------------------------------------------------------------*/
4253 static void genCmpEq (iCode *ic, iCode *ifx)
4255 operand *left, *right, *result;
4257 D(emitcode(";", "genCmpEq "););
4262 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4263 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4264 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4267 /* if literal, literal on the right or
4268 if the right is in a pointer register and left
4270 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4271 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4272 operand *t = IC_RIGHT(ic);
4273 IC_RIGHT(ic) = IC_LEFT(ic);
4277 if (ifx && /* !AOP_SIZE(result) */
4278 OP_SYMBOL(result) &&
4279 OP_SYMBOL(result)->regType == REG_CND)
4282 /* if they are both bit variables */
4283 if (AOP_TYPE(left) == AOP_CRY &&
4284 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4285 if(AOP_TYPE(right) == AOP_LIT){
4286 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4288 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4289 emitcode("cpl","c");
4290 } else if(lit == 1L) {
4291 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4293 emitcode("clr","c");
4295 /* AOP_TYPE(right) == AOP_CRY */
4297 symbol *lbl = newiTempLabel(NULL);
4298 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4299 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4300 emitcode("cpl","c");
4301 emitcode("","%05d$:",(lbl->key+100));
4303 /* if true label then we jump if condition
4305 tlbl = newiTempLabel(NULL);
4306 if ( IC_TRUE(ifx) ) {
4307 emitcode("jnc","%05d$",tlbl->key+100);
4308 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4310 emitcode("jc","%05d$",tlbl->key+100);
4311 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4313 emitcode("","%05d$:",tlbl->key+100);
4315 tlbl = newiTempLabel(NULL);
4316 gencjneshort(left, right, tlbl);
4317 if ( IC_TRUE(ifx) ) {
4318 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4319 emitcode("","%05d$:",tlbl->key+100);
4321 symbol *lbl = newiTempLabel(NULL);
4322 emitcode("sjmp","%05d$",lbl->key+100);
4323 emitcode("","%05d$:",tlbl->key+100);
4324 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4325 emitcode("","%05d$:",lbl->key+100);
4328 /* mark the icode as generated */
4331 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4332 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4336 /* if they are both bit variables */
4337 if (AOP_TYPE(left) == AOP_CRY &&
4338 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4339 if(AOP_TYPE(right) == AOP_LIT){
4340 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4342 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4343 emitcode("cpl","c");
4344 } else if(lit == 1L) {
4345 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4347 emitcode("clr","c");
4349 /* AOP_TYPE(right) == AOP_CRY */
4351 symbol *lbl = newiTempLabel(NULL);
4352 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4353 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4354 emitcode("cpl","c");
4355 emitcode("","%05d$:",(lbl->key+100));
4358 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4359 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4361 aopOp(result,ic,TRUE, FALSE);
4364 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4369 genIfxJump (ifx,"c");
4372 /* if the result is used in an arithmetic operation
4373 then put the result in place */
4376 gencjne(left,right,newiTempLabel(NULL));
4378 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4379 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4381 aopOp(result,ic,TRUE, FALSE);
4383 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4384 aopPut(AOP(result),"a",0);
4388 genIfxJump (ifx,"a");
4391 /* if the result is used in an arithmetic operation
4392 then put the result in place */
4393 if (AOP_TYPE(result) != AOP_CRY)
4395 /* leave the result in acc */
4399 freeAsmop(result,NULL,ic,TRUE);
4402 /*-----------------------------------------------------------------*/
4403 /* ifxForOp - returns the icode containing the ifx for operand */
4404 /*-----------------------------------------------------------------*/
4405 static iCode *ifxForOp ( operand *op, iCode *ic )
4407 /* if true symbol then needs to be assigned */
4408 if (IS_TRUE_SYMOP(op))
4411 /* if this has register type condition and
4412 the next instruction is ifx with the same operand
4413 and live to of the operand is upto the ifx only then */
4415 ic->next->op == IFX &&
4416 IC_COND(ic->next)->key == op->key &&
4417 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4422 /*-----------------------------------------------------------------*/
4423 /* genAndOp - for && operation */
4424 /*-----------------------------------------------------------------*/
4425 static void genAndOp (iCode *ic)
4427 operand *left,*right, *result;
4430 D(emitcode(";", "genAndOp "););
4432 /* note here that && operations that are in an
4433 if statement are taken away by backPatchLabels
4434 only those used in arthmetic operations remain */
4438 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4439 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4440 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4443 /* if both are bit variables */
4444 if (AOP_TYPE(left) == AOP_CRY &&
4445 AOP_TYPE(right) == AOP_CRY ) {
4446 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4447 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4450 tlbl = newiTempLabel(NULL);
4452 emitcode("jz","%05d$",tlbl->key+100);
4454 emitcode("","%05d$:",tlbl->key+100);
4458 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4459 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4460 freeAsmop(result,NULL,ic,TRUE);
4464 /*-----------------------------------------------------------------*/
4465 /* genOrOp - for || operation */
4466 /*-----------------------------------------------------------------*/
4467 static void genOrOp (iCode *ic)
4469 operand *left,*right, *result;
4472 D(emitcode(";", "genOrOp "););
4474 /* note here that || operations that are in an
4475 if statement are taken away by backPatchLabels
4476 only those used in arthmetic operations remain */
4480 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4481 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4482 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4485 /* if both are bit variables */
4486 if (AOP_TYPE(left) == AOP_CRY &&
4487 AOP_TYPE(right) == AOP_CRY ) {
4488 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4489 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4492 tlbl = newiTempLabel(NULL);
4494 emitcode("jnz","%05d$",tlbl->key+100);
4496 emitcode("","%05d$:",tlbl->key+100);
4500 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4501 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4502 freeAsmop(result,NULL,ic,TRUE);
4505 /*-----------------------------------------------------------------*/
4506 /* isLiteralBit - test if lit == 2^n */
4507 /*-----------------------------------------------------------------*/
4508 static int isLiteralBit(unsigned long lit)
4510 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4511 0x100L,0x200L,0x400L,0x800L,
4512 0x1000L,0x2000L,0x4000L,0x8000L,
4513 0x10000L,0x20000L,0x40000L,0x80000L,
4514 0x100000L,0x200000L,0x400000L,0x800000L,
4515 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4516 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4519 for(idx = 0; idx < 32; idx++)
4525 /*-----------------------------------------------------------------*/
4526 /* continueIfTrue - */
4527 /*-----------------------------------------------------------------*/
4528 static void continueIfTrue (iCode *ic)
4531 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4535 /*-----------------------------------------------------------------*/
4537 /*-----------------------------------------------------------------*/
4538 static void jumpIfTrue (iCode *ic)
4541 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4545 /*-----------------------------------------------------------------*/
4546 /* jmpTrueOrFalse - */
4547 /*-----------------------------------------------------------------*/
4548 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4550 // ugly but optimized by peephole
4552 symbol *nlbl = newiTempLabel(NULL);
4553 emitcode("sjmp","%05d$",nlbl->key+100);
4554 emitcode("","%05d$:",tlbl->key+100);
4555 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4556 emitcode("","%05d$:",nlbl->key+100);
4559 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4560 emitcode("","%05d$:",tlbl->key+100);
4565 /*-----------------------------------------------------------------*/
4566 /* genAnd - code for and */
4567 /*-----------------------------------------------------------------*/
4568 static void genAnd (iCode *ic, iCode *ifx)
4570 operand *left, *right, *result;
4572 unsigned long lit = 0L;
4576 D(emitcode(";", "genAnd "););
4581 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4582 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4583 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4587 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4589 AOP_TYPE(left), AOP_TYPE(right));
4590 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4592 AOP_SIZE(left), AOP_SIZE(right));
4595 /* if left is a literal & right is not then exchange them */
4596 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4597 AOP_NEEDSACC(left)) {
4598 operand *tmp = right ;
4603 /* if result = right then exchange them */
4604 if(sameRegs(AOP(result),AOP(right))){
4605 operand *tmp = right ;
4610 /* if right is bit then exchange them */
4611 if (AOP_TYPE(right) == AOP_CRY &&
4612 AOP_TYPE(left) != AOP_CRY){
4613 operand *tmp = right ;
4617 if(AOP_TYPE(right) == AOP_LIT)
4618 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4620 size = AOP_SIZE(result);
4623 // result = bit & yy;
4624 if (AOP_TYPE(left) == AOP_CRY){
4625 // c = bit & literal;
4626 if(AOP_TYPE(right) == AOP_LIT){
4628 if(size && sameRegs(AOP(result),AOP(left)))
4631 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4634 if(size && (AOP_TYPE(result) == AOP_CRY)){
4635 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4638 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4642 emitcode("clr","c");
4645 if (AOP_TYPE(right) == AOP_CRY){
4647 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4648 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4651 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4653 emitcode("rrc","a");
4654 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4662 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4663 genIfxJump(ifx, "c");
4667 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4668 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4669 if((AOP_TYPE(right) == AOP_LIT) &&
4670 (AOP_TYPE(result) == AOP_CRY) &&
4671 (AOP_TYPE(left) != AOP_CRY)){
4672 int posbit = isLiteralBit(lit);
4676 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4679 emitcode("mov","c,acc.%d",posbit&0x07);
4683 sprintf(buffer,"acc.%d",posbit&0x07);
4684 genIfxJump(ifx, buffer);
4689 symbol *tlbl = newiTempLabel(NULL);
4690 int sizel = AOP_SIZE(left);
4692 emitcode("setb","c");
4694 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4695 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4697 if((posbit = isLiteralBit(bytelit)) != 0)
4698 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4700 if(bytelit != 0x0FFL)
4701 emitcode("anl","a,%s",
4702 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4703 emitcode("jnz","%05d$",tlbl->key+100);
4708 // bit = left & literal
4710 emitcode("clr","c");
4711 emitcode("","%05d$:",tlbl->key+100);
4713 // if(left & literal)
4716 jmpTrueOrFalse(ifx, tlbl);
4724 /* if left is same as result */
4725 if(sameRegs(AOP(result),AOP(left))){
4726 for(;size--; offset++) {
4727 if(AOP_TYPE(right) == AOP_LIT){
4728 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4732 aopPut(AOP(result),zero,offset);
4734 if (IS_AOP_PREG(result)) {
4735 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4736 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4737 aopPut(AOP(result),"a",offset);
4739 emitcode("anl","%s,%s",
4740 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4741 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4743 if (AOP_TYPE(left) == AOP_ACC)
4744 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4746 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4747 if (IS_AOP_PREG(result)) {
4748 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4749 aopPut(AOP(result),"a",offset);
4752 emitcode("anl","%s,a",
4753 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4758 // left & result in different registers
4759 if(AOP_TYPE(result) == AOP_CRY){
4761 // if(size), result in bit
4762 // if(!size && ifx), conditional oper: if(left & right)
4763 symbol *tlbl = newiTempLabel(NULL);
4764 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4766 emitcode("setb","c");
4768 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4769 emitcode("anl","a,%s",
4770 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4771 emitcode("jnz","%05d$",tlbl->key+100);
4776 emitcode("","%05d$:",tlbl->key+100);
4779 jmpTrueOrFalse(ifx, tlbl);
4782 for(;(size--);offset++)
4785 // result = left & right
4786 if(AOP_TYPE(right) == AOP_LIT)
4788 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4791 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4795 else if (bytelit == 0)
4797 aopPut(AOP(result),zero,offset);
4800 D(emitcode(";", "better literal AND."););
4801 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4802 emitcode("anl", "a, %s", aopGet(AOP(right),offset,
4803 FALSE,FALSE,FALSE));
4808 // faster than result <- left, anl result,right
4809 // and better if result is SFR
4810 if (AOP_TYPE(left) == AOP_ACC)
4812 emitcode("anl","a,%s",aopGet(AOP(right),offset,
4813 FALSE,FALSE,FALSE));
4817 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4818 emitcode("anl","a,%s",
4819 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4822 aopPut(AOP(result),"a",offset);
4828 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4829 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4830 freeAsmop(result,NULL,ic,TRUE);
4833 /*-----------------------------------------------------------------*/
4834 /* genOr - code for or */
4835 /*-----------------------------------------------------------------*/
4836 static void genOr (iCode *ic, iCode *ifx)
4838 operand *left, *right, *result;
4840 unsigned long lit = 0L;
4842 D(emitcode(";", "genOr "););
4847 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4848 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4849 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4853 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4855 AOP_TYPE(left), AOP_TYPE(right));
4856 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4858 AOP_SIZE(left), AOP_SIZE(right));
4861 /* if left is a literal & right is not then exchange them */
4862 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4863 AOP_NEEDSACC(left)) {
4864 operand *tmp = right ;
4869 /* if result = right then exchange them */
4870 if(sameRegs(AOP(result),AOP(right))){
4871 operand *tmp = right ;
4876 /* if right is bit then exchange them */
4877 if (AOP_TYPE(right) == AOP_CRY &&
4878 AOP_TYPE(left) != AOP_CRY){
4879 operand *tmp = right ;
4883 if(AOP_TYPE(right) == AOP_LIT)
4884 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4886 size = AOP_SIZE(result);
4890 if (AOP_TYPE(left) == AOP_CRY){
4891 if(AOP_TYPE(right) == AOP_LIT){
4892 // c = bit & literal;
4894 // lit != 0 => result = 1
4895 if(AOP_TYPE(result) == AOP_CRY){
4897 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4899 continueIfTrue(ifx);
4902 emitcode("setb","c");
4904 // lit == 0 => result = left
4905 if(size && sameRegs(AOP(result),AOP(left)))
4907 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4910 if (AOP_TYPE(right) == AOP_CRY){
4912 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4913 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4917 symbol *tlbl = newiTempLabel(NULL);
4918 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4919 emitcode("setb","c");
4920 emitcode("jb","%s,%05d$",
4921 AOP(left)->aopu.aop_dir,tlbl->key+100);
4923 emitcode("jnz","%05d$",tlbl->key+100);
4924 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4925 jmpTrueOrFalse(ifx, tlbl);
4929 emitcode("","%05d$:",tlbl->key+100);
4938 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4939 genIfxJump(ifx, "c");
4943 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4944 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4945 if((AOP_TYPE(right) == AOP_LIT) &&
4946 (AOP_TYPE(result) == AOP_CRY) &&
4947 (AOP_TYPE(left) != AOP_CRY)){
4951 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4953 continueIfTrue(ifx);
4956 // lit = 0, result = boolean(left)
4958 emitcode("setb","c");
4961 symbol *tlbl = newiTempLabel(NULL);
4962 emitcode("jnz","%05d$",tlbl->key+100);
4964 emitcode("","%05d$:",tlbl->key+100);
4966 genIfxJump (ifx,"a");
4974 /* if left is same as result */
4975 if(sameRegs(AOP(result),AOP(left)))
4977 for(;size--; offset++)
4979 if(AOP_TYPE(right) == AOP_LIT){
4980 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4986 if (IS_AOP_PREG(left))
4988 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4989 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4990 aopPut(AOP(result),"a",offset);
4994 emitcode("orl","%s,%s",
4995 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4996 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5002 if (AOP_TYPE(left) == AOP_ACC)
5004 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5008 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5009 if (IS_AOP_PREG(left))
5011 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5012 aopPut(AOP(result),"a",offset);
5016 emitcode("orl","%s,a",
5017 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5025 // left & result in different registers
5026 if(AOP_TYPE(result) == AOP_CRY)
5029 // if(size), result in bit
5030 // if(!size && ifx), conditional oper: if(left | right)
5031 symbol *tlbl = newiTempLabel(NULL);
5032 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5034 emitcode("setb","c");
5036 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5037 emitcode("orl","a,%s",
5038 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5039 emitcode("jnz","%05d$",tlbl->key+100);
5044 emitcode("","%05d$:",tlbl->key+100);
5047 jmpTrueOrFalse(ifx, tlbl);
5051 for(;(size--);offset++)
5054 // result = left & right
5055 if(AOP_TYPE(right) == AOP_LIT)
5057 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5060 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5064 D(emitcode(";", "better literal OR."););
5065 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5066 emitcode("orl", "a, %s", aopGet(AOP(right),offset,
5067 FALSE,FALSE,FALSE));
5072 // faster than result <- left, anl result,right
5073 // and better if result is SFR
5074 if (AOP_TYPE(left) == AOP_ACC)
5076 emitcode("orl","a,%s",aopGet(AOP(right),offset,
5077 FALSE,FALSE,FALSE));
5081 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5082 emitcode("orl","a,%s",
5083 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5086 aopPut(AOP(result),"a",offset);
5092 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5093 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5094 freeAsmop(result,NULL,ic,TRUE);
5097 /*-----------------------------------------------------------------*/
5098 /* genXor - code for xclusive or */
5099 /*-----------------------------------------------------------------*/
5100 static void genXor (iCode *ic, iCode *ifx)
5102 operand *left, *right, *result;
5104 unsigned long lit = 0L;
5106 D(emitcode(";", "genXor "););
5111 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
5112 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
5113 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
5117 emitcode("","; Type res[%d] = l[%d]&r[%d]",
5119 AOP_TYPE(left), AOP_TYPE(right));
5120 emitcode("","; Size res[%d] = l[%d]&r[%d]",
5122 AOP_SIZE(left), AOP_SIZE(right));
5125 /* if left is a literal & right is not ||
5126 if left needs acc & right does not */
5127 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5128 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5129 operand *tmp = right ;
5134 /* if result = right then exchange them */
5135 if(sameRegs(AOP(result),AOP(right))){
5136 operand *tmp = right ;
5141 /* if right is bit then exchange them */
5142 if (AOP_TYPE(right) == AOP_CRY &&
5143 AOP_TYPE(left) != AOP_CRY){
5144 operand *tmp = right ;
5148 if(AOP_TYPE(right) == AOP_LIT)
5149 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5151 size = AOP_SIZE(result);
5155 if (AOP_TYPE(left) == AOP_CRY){
5156 if(AOP_TYPE(right) == AOP_LIT){
5157 // c = bit & literal;
5159 // lit>>1 != 0 => result = 1
5160 if(AOP_TYPE(result) == AOP_CRY){
5162 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5164 continueIfTrue(ifx);
5167 emitcode("setb","c");
5171 // lit == 0, result = left
5172 if(size && sameRegs(AOP(result),AOP(left)))
5174 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5176 // lit == 1, result = not(left)
5177 if(size && sameRegs(AOP(result),AOP(left))){
5178 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5181 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5182 emitcode("cpl","c");
5189 symbol *tlbl = newiTempLabel(NULL);
5190 if (AOP_TYPE(right) == AOP_CRY){
5192 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5195 int sizer = AOP_SIZE(right);
5197 // if val>>1 != 0, result = 1
5198 emitcode("setb","c");
5200 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5202 // test the msb of the lsb
5203 emitcode("anl","a,#0xfe");
5204 emitcode("jnz","%05d$",tlbl->key+100);
5208 emitcode("rrc","a");
5210 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5211 emitcode("cpl","c");
5212 emitcode("","%05d$:",(tlbl->key+100));
5219 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5220 genIfxJump(ifx, "c");
5224 if(sameRegs(AOP(result),AOP(left))){
5225 /* if left is same as result */
5226 for(;size--; offset++) {
5227 if(AOP_TYPE(right) == AOP_LIT){
5228 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5231 if (IS_AOP_PREG(left)) {
5232 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5233 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5234 aopPut(AOP(result),"a",offset);
5236 emitcode("xrl","%s,%s",
5237 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5238 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5240 if (AOP_TYPE(left) == AOP_ACC)
5241 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5243 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5244 if (IS_AOP_PREG(left)) {
5245 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5246 aopPut(AOP(result),"a",offset);
5248 emitcode("xrl","%s,a",
5249 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5254 // left & result in different registers
5255 if(AOP_TYPE(result) == AOP_CRY){
5257 // if(size), result in bit
5258 // if(!size && ifx), conditional oper: if(left ^ right)
5259 symbol *tlbl = newiTempLabel(NULL);
5260 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5262 emitcode("setb","c");
5264 if((AOP_TYPE(right) == AOP_LIT) &&
5265 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5266 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5268 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5269 emitcode("xrl","a,%s",
5270 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5272 emitcode("jnz","%05d$",tlbl->key+100);
5277 emitcode("","%05d$:",tlbl->key+100);
5280 jmpTrueOrFalse(ifx, tlbl);
5281 } else for(;(size--);offset++)
5284 // result = left & right
5285 if(AOP_TYPE(right) == AOP_LIT)
5287 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5290 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5294 D(emitcode(";", "better literal XOR."););
5295 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5296 emitcode("xrl", "a, %s", aopGet(AOP(right),offset,
5297 FALSE,FALSE,FALSE));
5301 // faster than result <- left, anl result,right
5302 // and better if result is SFR
5303 if (AOP_TYPE(left) == AOP_ACC)
5305 emitcode("xrl","a,%s",aopGet(AOP(right),offset,
5306 FALSE,FALSE,FALSE));
5310 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5311 emitcode("xrl","a,%s",
5312 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5315 aopPut(AOP(result),"a",offset);
5320 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5321 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5322 freeAsmop(result,NULL,ic,TRUE);
5325 /*-----------------------------------------------------------------*/
5326 /* genInline - write the inline code out */
5327 /*-----------------------------------------------------------------*/
5328 static void genInline (iCode *ic)
5330 char buffer[MAX_INLINEASM];
5334 D(emitcode(";", "genInline "););
5336 _G.inLine += (!options.asmpeep);
5337 strcpy(buffer,IC_INLINE(ic));
5339 /* emit each line as a code */
5358 /* emitcode("",buffer); */
5359 _G.inLine -= (!options.asmpeep);
5362 /*-----------------------------------------------------------------*/
5363 /* genRRC - rotate right with carry */
5364 /*-----------------------------------------------------------------*/
5365 static void genRRC (iCode *ic)
5367 operand *left , *result ;
5368 int size, offset = 0;
5371 D(emitcode(";", "genRRC "););
5373 /* rotate right with carry */
5375 result=IC_RESULT(ic);
5376 aopOp (left,ic,FALSE, FALSE);
5377 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5379 /* move it to the result */
5380 size = AOP_SIZE(result);
5384 _startLazyDPSEvaluation();
5386 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5388 emitcode("rrc","a");
5389 if (AOP_SIZE(result) > 1)
5390 aopPut(AOP(result),"a",offset--);
5392 _endLazyDPSEvaluation();
5394 /* now we need to put the carry into the
5395 highest order byte of the result */
5396 if (AOP_SIZE(result) > 1) {
5397 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5400 emitcode("mov","acc.7,c");
5401 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5402 freeAsmop(left,NULL,ic,TRUE);
5403 freeAsmop(result,NULL,ic,TRUE);
5406 /*-----------------------------------------------------------------*/
5407 /* genRLC - generate code for rotate left with carry */
5408 /*-----------------------------------------------------------------*/
5409 static void genRLC (iCode *ic)
5411 operand *left , *result ;
5412 int size, offset = 0;
5415 D(emitcode(";", "genRLC "););
5417 /* rotate right with carry */
5419 result=IC_RESULT(ic);
5420 aopOp (left,ic,FALSE, FALSE);
5421 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5423 /* move it to the result */
5424 size = AOP_SIZE(result);
5427 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5429 emitcode("add","a,acc");
5430 if (AOP_SIZE(result) > 1)
5432 aopPut(AOP(result),"a",offset++);
5435 _startLazyDPSEvaluation();
5437 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5439 emitcode("rlc","a");
5440 if (AOP_SIZE(result) > 1)
5441 aopPut(AOP(result),"a",offset++);
5443 _endLazyDPSEvaluation();
5445 /* now we need to put the carry into the
5446 highest order byte of the result */
5447 if (AOP_SIZE(result) > 1) {
5448 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5451 emitcode("mov","acc.0,c");
5452 aopPut(AOP(result),"a",0);
5453 freeAsmop(left,NULL,ic,TRUE);
5454 freeAsmop(result,NULL,ic,TRUE);
5457 /*-----------------------------------------------------------------*/
5458 /* genGetHbit - generates code get highest order bit */
5459 /*-----------------------------------------------------------------*/
5460 static void genGetHbit (iCode *ic)
5462 operand *left, *result;
5464 result=IC_RESULT(ic);
5465 aopOp (left,ic,FALSE, FALSE);
5466 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5468 D(emitcode(";", "genGetHbit "););
5470 /* get the highest order byte into a */
5471 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5472 if(AOP_TYPE(result) == AOP_CRY){
5473 emitcode("rlc","a");
5478 emitcode("anl","a,#0x01");
5483 freeAsmop(left,NULL,ic,TRUE);
5484 freeAsmop(result,NULL,ic,TRUE);
5487 /*-----------------------------------------------------------------*/
5488 /* AccRol - rotate left accumulator by known count */
5489 /*-----------------------------------------------------------------*/
5490 static void AccRol (int shCount)
5492 shCount &= 0x0007; // shCount : 0..7
5504 emitcode("swap","a");
5508 emitcode("swap","a");
5511 emitcode("swap","a");
5524 /*-----------------------------------------------------------------*/
5525 /* AccLsh - left shift accumulator by known count */
5526 /*-----------------------------------------------------------------*/
5527 static void AccLsh (int shCount)
5531 emitcode("add","a,acc");
5534 emitcode("add","a,acc");
5535 emitcode("add","a,acc");
5537 /* rotate left accumulator */
5539 /* and kill the lower order bits */
5540 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5545 /*-----------------------------------------------------------------*/
5546 /* AccRsh - right shift accumulator by known count */
5547 /*-----------------------------------------------------------------*/
5548 static void AccRsh (int shCount)
5553 emitcode("rrc","a");
5555 /* rotate right accumulator */
5556 AccRol(8 - shCount);
5557 /* and kill the higher order bits */
5558 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5565 /*-----------------------------------------------------------------*/
5566 /* AccSRsh - signed right shift accumulator by known count */
5567 /*-----------------------------------------------------------------*/
5568 static void AccSRsh (int shCount)
5573 emitcode("mov","c,acc.7");
5574 emitcode("rrc","a");
5575 } else if(shCount == 2){
5576 emitcode("mov","c,acc.7");
5577 emitcode("rrc","a");
5578 emitcode("mov","c,acc.7");
5579 emitcode("rrc","a");
5581 tlbl = newiTempLabel(NULL);
5582 /* rotate right accumulator */
5583 AccRol(8 - shCount);
5584 /* and kill the higher order bits */
5585 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5586 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5587 emitcode("orl","a,#0x%02x",
5588 (unsigned char)~SRMask[shCount]);
5589 emitcode("","%05d$:",tlbl->key+100);
5597 /*-----------------------------------------------------------------*/
5598 /* shiftR1Left2Result - shift right one byte from left to result */
5599 /*-----------------------------------------------------------------*/
5600 static void shiftR1Left2Result (operand *left, int offl,
5601 operand *result, int offr,
5602 int shCount, int sign)
5604 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5605 /* shift right accumulator */
5610 aopPut(AOP(result),"a",offr);
5616 /*-----------------------------------------------------------------*/
5617 /* shiftL1Left2Result - shift left one byte from left to result */
5618 /*-----------------------------------------------------------------*/
5619 static void shiftL1Left2Result (operand *left, int offl,
5620 operand *result, int offr, int shCount)
5623 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5625 /* shift left accumulator */
5627 aopPut(AOP(result),"a",offr);
5633 /*-----------------------------------------------------------------*/
5634 /* movLeft2Result - move byte from left to result */
5635 /*-----------------------------------------------------------------*/
5636 static void movLeft2Result (operand *left, int offl,
5637 operand *result, int offr, int sign)
5640 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5641 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5643 if (*l == '@' && (IS_AOP_PREG(result))) {
5644 emitcode("mov","a,%s",l);
5645 aopPut(AOP(result),"a",offr);
5648 aopPut(AOP(result),l,offr);
5650 /* MSB sign in acc.7 ! */
5651 if(getDataSize(left) == offl+1){
5652 emitcode("mov","a,%s",l);
5653 aopPut(AOP(result),"a",offr);
5663 /*-----------------------------------------------------------------*/
5664 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5665 /*-----------------------------------------------------------------*/
5666 static void AccAXRrl1 (char *x)
5668 emitcode("rrc","a");
5669 emitcode("xch","a,%s", x);
5670 emitcode("rrc","a");
5671 emitcode("xch","a,%s", x);
5677 /*-----------------------------------------------------------------*/
5678 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5679 /*-----------------------------------------------------------------*/
5680 static void AccAXLrl1 (char *x)
5682 emitcode("xch","a,%s",x);
5683 emitcode("rlc","a");
5684 emitcode("xch","a,%s",x);
5685 emitcode("rlc","a");
5691 /*-----------------------------------------------------------------*/
5692 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5693 /*-----------------------------------------------------------------*/
5694 static void AccAXLsh1 (char *x)
5696 emitcode("xch","a,%s",x);
5697 emitcode("add","a,acc");
5698 emitcode("xch","a,%s",x);
5699 emitcode("rlc","a");
5705 /*-----------------------------------------------------------------*/
5706 /* AccAXLsh - left shift a:x by known count (0..7) */
5707 /*-----------------------------------------------------------------*/
5708 static void AccAXLsh (char *x, int shCount)
5722 case 5 : // AAAAABBB:CCCCCDDD
5723 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5724 emitcode("anl","a,#0x%02x",
5725 SLMask[shCount]); // BBB00000:CCCCCDDD
5726 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5727 AccRol(shCount); // DDDCCCCC:BBB00000
5728 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5729 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5730 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5731 emitcode("anl","a,#0x%02x",
5732 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5733 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5734 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5736 case 6 : // AAAAAABB:CCCCCCDD
5737 emitcode("anl","a,#0x%02x",
5738 SRMask[shCount]); // 000000BB:CCCCCCDD
5739 emitcode("mov","c,acc.0"); // c = B
5740 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5741 AccAXRrl1(x); // BCCCCCCD:D000000B
5742 AccAXRrl1(x); // BBCCCCCC:DD000000
5744 case 7 : // a:x <<= 7
5745 emitcode("anl","a,#0x%02x",
5746 SRMask[shCount]); // 0000000B:CCCCCCCD
5747 emitcode("mov","c,acc.0"); // c = B
5748 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5749 AccAXRrl1(x); // BCCCCCCC:D0000000
5759 /*-----------------------------------------------------------------*/
5760 /* AccAXRsh - right shift a:x known count (0..7) */
5761 /*-----------------------------------------------------------------*/
5762 static void AccAXRsh (char *x, int shCount)
5769 AccAXRrl1(x); // 0->a:x
5773 AccAXRrl1(x); // 0->a:x
5775 AccAXRrl1(x); // 0->a:x
5779 case 5 : // AAAAABBB:CCCCCDDD = a:x
5780 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5781 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5782 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5783 emitcode("anl","a,#0x%02x",
5784 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5785 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5786 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5787 emitcode("anl","a,#0x%02x",
5788 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5789 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5790 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5791 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5793 case 6 : // AABBBBBB:CCDDDDDD
5794 emitcode("mov","c,acc.7");
5795 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5796 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5797 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5798 emitcode("anl","a,#0x%02x",
5799 SRMask[shCount]); // 000000AA:BBBBBBCC
5801 case 7 : // ABBBBBBB:CDDDDDDD
5802 emitcode("mov","c,acc.7"); // c = A
5803 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5804 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5805 emitcode("anl","a,#0x%02x",
5806 SRMask[shCount]); // 0000000A:BBBBBBBC
5816 /*-----------------------------------------------------------------*/
5817 /* AccAXRshS - right shift signed a:x known count (0..7) */
5818 /*-----------------------------------------------------------------*/
5819 static void AccAXRshS (char *x, int shCount)
5826 emitcode("mov","c,acc.7");
5827 AccAXRrl1(x); // s->a:x
5830 emitcode("mov","c,acc.7");
5831 AccAXRrl1(x); // s->a:x
5832 emitcode("mov","c,acc.7");
5833 AccAXRrl1(x); // s->a:x
5837 case 5 : // AAAAABBB:CCCCCDDD = a:x
5838 tlbl = newiTempLabel(NULL);
5839 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5840 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5841 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5842 emitcode("anl","a,#0x%02x",
5843 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5844 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5845 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5846 emitcode("anl","a,#0x%02x",
5847 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5848 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5849 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5850 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5851 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5852 emitcode("orl","a,#0x%02x",
5853 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5854 emitcode("","%05d$:",tlbl->key+100);
5855 break; // SSSSAAAA:BBBCCCCC
5856 case 6 : // AABBBBBB:CCDDDDDD
5857 tlbl = newiTempLabel(NULL);
5858 emitcode("mov","c,acc.7");
5859 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5860 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5861 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5862 emitcode("anl","a,#0x%02x",
5863 SRMask[shCount]); // 000000AA:BBBBBBCC
5864 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5865 emitcode("orl","a,#0x%02x",
5866 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5867 emitcode("","%05d$:",tlbl->key+100);
5869 case 7 : // ABBBBBBB:CDDDDDDD
5870 tlbl = newiTempLabel(NULL);
5871 emitcode("mov","c,acc.7"); // c = A
5872 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5873 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5874 emitcode("anl","a,#0x%02x",
5875 SRMask[shCount]); // 0000000A:BBBBBBBC
5876 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5877 emitcode("orl","a,#0x%02x",
5878 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5879 emitcode("","%05d$:",tlbl->key+100);
5889 /*-----------------------------------------------------------------*/
5890 /* shiftL2Left2Result - shift left two bytes from left to result */
5891 /*-----------------------------------------------------------------*/
5892 static void shiftL2Left2Result (operand *left, int offl,
5893 operand *result, int offr, int shCount)
5895 if(sameRegs(AOP(result), AOP(left)) &&
5896 ((offl + MSB16) == offr)){
5897 /* don't crash result[offr] */
5898 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5899 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5901 movLeft2Result(left,offl, result, offr, 0);
5902 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5904 /* ax << shCount (x = lsb(result))*/
5905 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5906 aopPut(AOP(result),"a",offr+MSB16);
5912 /*-----------------------------------------------------------------*/
5913 /* shiftR2Left2Result - shift right two bytes from left to result */
5914 /*-----------------------------------------------------------------*/
5915 static void shiftR2Left2Result (operand *left, int offl,
5916 operand *result, int offr,
5917 int shCount, int sign)
5919 if(sameRegs(AOP(result), AOP(left)) &&
5920 ((offl + MSB16) == offr)){
5921 /* don't crash result[offr] */
5922 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5923 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5925 movLeft2Result(left,offl, result, offr, 0);
5926 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5928 /* a:x >> shCount (x = lsb(result))*/
5930 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5932 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5933 if(getDataSize(result) > 1)
5934 aopPut(AOP(result),"a",offr+MSB16);
5940 /*-----------------------------------------------------------------*/
5941 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5942 /*-----------------------------------------------------------------*/
5943 static void shiftLLeftOrResult (operand *left, int offl,
5944 operand *result, int offr, int shCount)
5946 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5947 /* shift left accumulator */
5949 /* or with result */
5950 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5951 /* back to result */
5952 aopPut(AOP(result),"a",offr);
5958 /*-----------------------------------------------------------------*/
5959 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5960 /*-----------------------------------------------------------------*/
5961 static void shiftRLeftOrResult (operand *left, int offl,
5962 operand *result, int offr, int shCount)
5964 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5965 /* shift right accumulator */
5967 /* or with result */
5968 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5969 /* back to result */
5970 aopPut(AOP(result),"a",offr);
5976 /*-----------------------------------------------------------------*/
5977 /* genlshOne - left shift a one byte quantity by known count */
5978 /*-----------------------------------------------------------------*/
5979 static void genlshOne (operand *result, operand *left, int shCount)
5981 D(emitcode(";", "genlshOne "););
5982 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5988 /*-----------------------------------------------------------------*/
5989 /* genlshTwo - left shift two bytes by known amount != 0 */
5990 /*-----------------------------------------------------------------*/
5991 static void genlshTwo (operand *result,operand *left, int shCount)
5995 D(emitcode(";", "genlshTwo "););
5997 size = getDataSize(result);
5999 /* if shCount >= 8 */
6005 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6007 movLeft2Result(left, LSB, result, MSB16, 0);
6009 aopPut(AOP(result),zero,LSB);
6012 /* 1 <= shCount <= 7 */
6015 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6017 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6024 /*-----------------------------------------------------------------*/
6025 /* shiftLLong - shift left one long from left to result */
6026 /* offl = LSB or MSB16 */
6027 /*-----------------------------------------------------------------*/
6028 static void shiftLLong (operand *left, operand *result, int offr )
6031 int size = AOP_SIZE(result);
6033 if(size >= LSB+offr){
6034 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
6036 emitcode("add","a,acc");
6037 if (sameRegs(AOP(left),AOP(result)) &&
6038 size >= MSB16+offr && offr != LSB )
6039 emitcode("xch","a,%s",
6040 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
6042 aopPut(AOP(result),"a",LSB+offr);
6045 if(size >= MSB16+offr){
6046 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6047 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
6050 emitcode("rlc","a");
6051 if (sameRegs(AOP(left),AOP(result)) &&
6052 size >= MSB24+offr && offr != LSB)
6053 emitcode("xch","a,%s",
6054 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
6056 aopPut(AOP(result),"a",MSB16+offr);
6059 if(size >= MSB24+offr){
6060 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6061 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
6064 emitcode("rlc","a");
6065 if (sameRegs(AOP(left),AOP(result)) &&
6066 size >= MSB32+offr && offr != LSB )
6067 emitcode("xch","a,%s",
6068 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
6070 aopPut(AOP(result),"a",MSB24+offr);
6073 if(size > MSB32+offr){
6074 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6075 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
6078 emitcode("rlc","a");
6079 aopPut(AOP(result),"a",MSB32+offr);
6082 aopPut(AOP(result),zero,LSB);
6088 /*-----------------------------------------------------------------*/
6089 /* genlshFour - shift four byte by a known amount != 0 */
6090 /*-----------------------------------------------------------------*/
6091 static void genlshFour (operand *result, operand *left, int shCount)
6095 D(emitcode(";", "genlshFour "););
6097 size = AOP_SIZE(result);
6099 /* if shifting more that 3 bytes */
6100 if (shCount >= 24 ) {
6103 /* lowest order of left goes to the highest
6104 order of the destination */
6105 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6107 movLeft2Result(left, LSB, result, MSB32, 0);
6108 aopPut(AOP(result),zero,LSB);
6109 aopPut(AOP(result),zero,MSB16);
6110 aopPut(AOP(result),zero,MSB32);
6114 /* more than two bytes */
6115 else if ( shCount >= 16 ) {
6116 /* lower order two bytes goes to higher order two bytes */
6118 /* if some more remaining */
6120 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6122 movLeft2Result(left, MSB16, result, MSB32, 0);
6123 movLeft2Result(left, LSB, result, MSB24, 0);
6125 aopPut(AOP(result),zero,MSB16);
6126 aopPut(AOP(result),zero,LSB);
6130 /* if more than 1 byte */
6131 else if ( shCount >= 8 ) {
6132 /* lower order three bytes goes to higher order three bytes */
6136 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6138 movLeft2Result(left, LSB, result, MSB16, 0);
6140 else{ /* size = 4 */
6142 movLeft2Result(left, MSB24, result, MSB32, 0);
6143 movLeft2Result(left, MSB16, result, MSB24, 0);
6144 movLeft2Result(left, LSB, result, MSB16, 0);
6145 aopPut(AOP(result),zero,LSB);
6147 else if(shCount == 1)
6148 shiftLLong(left, result, MSB16);
6150 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6151 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6152 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6153 aopPut(AOP(result),zero,LSB);
6158 /* 1 <= shCount <= 7 */
6159 else if(shCount <= 2){
6160 shiftLLong(left, result, LSB);
6162 shiftLLong(result, result, LSB);
6164 /* 3 <= shCount <= 7, optimize */
6166 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6167 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6168 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6175 /*-----------------------------------------------------------------*/
6176 /* genLeftShiftLiteral - left shifting by known count */
6177 /*-----------------------------------------------------------------*/
6178 static void genLeftShiftLiteral (operand *left,
6183 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6186 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
6188 freeAsmop(right,NULL,ic,TRUE);
6190 aopOp(left,ic,FALSE, FALSE);
6191 aopOp(result,ic,FALSE, TRUE);
6193 size = getSize(operandType(result));
6196 emitcode("; shift left ","result %d, left %d",size,
6200 /* I suppose that the left size >= result size */
6203 movLeft2Result(left, size, result, size, 0);
6207 else if(shCount >= (size * 8))
6209 aopPut(AOP(result),zero,size);
6213 genlshOne (result,left,shCount);
6217 case 3: /* bug: this is for generic pointers, I bet. */
6218 genlshTwo (result,left,shCount);
6222 genlshFour (result,left,shCount);
6226 freeAsmop(left,NULL,ic,TRUE);
6227 freeAsmop(result,NULL,ic,TRUE);
6231 /*-----------------------------------------------------------------*/
6232 /* genLeftShift - generates code for left shifting */
6233 /*-----------------------------------------------------------------*/
6234 static void genLeftShift (iCode *ic)
6236 operand *left,*right, *result;
6239 symbol *tlbl , *tlbl1;
6241 D(emitcode(";", "genLeftShift "););
6243 right = IC_RIGHT(ic);
6245 result = IC_RESULT(ic);
6247 aopOp(right,ic,FALSE, FALSE);
6250 /* if the shift count is known then do it
6251 as efficiently as possible */
6252 if (AOP_TYPE(right) == AOP_LIT) {
6253 genLeftShiftLiteral (left,right,result,ic);
6258 /* shift count is unknown then we have to form
6259 a loop get the loop count in B : Note: we take
6260 only the lower order byte since shifting
6261 more that 32 bits make no sense anyway, ( the
6262 largest size of an object can be only 32 bits ) */
6264 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6265 emitcode("inc","b");
6266 freeAsmop (right,NULL,ic,TRUE);
6267 aopOp(left,ic,FALSE, FALSE);
6268 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6270 /* now move the left to the result if they are not the
6272 if (!sameRegs(AOP(left),AOP(result)) &&
6273 AOP_SIZE(result) > 1) {
6275 size = AOP_SIZE(result);
6277 _startLazyDPSEvaluation();
6279 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6280 if (*l == '@' && (IS_AOP_PREG(result))) {
6282 emitcode("mov","a,%s",l);
6283 aopPut(AOP(result),"a",offset);
6285 aopPut(AOP(result),l,offset);
6288 _endLazyDPSEvaluation();
6291 tlbl = newiTempLabel(NULL);
6292 size = AOP_SIZE(result);
6294 tlbl1 = newiTempLabel(NULL);
6296 /* if it is only one byte then */
6298 symbol *tlbl1 = newiTempLabel(NULL);
6300 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6302 emitcode("sjmp","%05d$",tlbl1->key+100);
6303 emitcode("","%05d$:",tlbl->key+100);
6304 emitcode("add","a,acc");
6305 emitcode("","%05d$:",tlbl1->key+100);
6306 emitcode("djnz","b,%05d$",tlbl->key+100);
6307 aopPut(AOP(result),"a",0);
6311 reAdjustPreg(AOP(result));
6313 emitcode("sjmp","%05d$",tlbl1->key+100);
6314 emitcode("","%05d$:",tlbl->key+100);
6315 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6317 emitcode("add","a,acc");
6318 aopPut(AOP(result),"a",offset++);
6319 _startLazyDPSEvaluation();
6321 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6323 emitcode("rlc","a");
6324 aopPut(AOP(result),"a",offset++);
6326 _endLazyDPSEvaluation();
6327 reAdjustPreg(AOP(result));
6329 emitcode("","%05d$:",tlbl1->key+100);
6330 emitcode("djnz","b,%05d$",tlbl->key+100);
6332 freeAsmop(left,NULL,ic,TRUE);
6333 freeAsmop(result,NULL,ic,TRUE);
6338 /*-----------------------------------------------------------------*/
6339 /* genrshOne - right shift a one byte quantity by known count */
6340 /*-----------------------------------------------------------------*/
6341 static void genrshOne (operand *result, operand *left,
6342 int shCount, int sign)
6344 D(emitcode(";", "genrshOne"););
6345 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6351 /*-----------------------------------------------------------------*/
6352 /* genrshTwo - right shift two bytes by known amount != 0 */
6353 /*-----------------------------------------------------------------*/
6354 static void genrshTwo (operand *result,operand *left,
6355 int shCount, int sign)
6357 D(emitcode(";", "genrshTwo"););
6359 /* if shCount >= 8 */
6363 shiftR1Left2Result(left, MSB16, result, LSB,
6366 movLeft2Result(left, MSB16, result, LSB, sign);
6367 addSign(result, MSB16, sign);
6370 /* 1 <= shCount <= 7 */
6372 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6378 /*-----------------------------------------------------------------*/
6379 /* shiftRLong - shift right one long from left to result */
6380 /* offl = LSB or MSB16 */
6381 /*-----------------------------------------------------------------*/
6382 static void shiftRLong (operand *left, int offl,
6383 operand *result, int sign)
6386 emitcode("clr","c");
6387 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6389 emitcode("mov","c,acc.7");
6390 emitcode("rrc","a");
6391 aopPut(AOP(result),"a",MSB32-offl);
6393 /* add sign of "a" */
6394 addSign(result, MSB32, sign);
6396 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6397 emitcode("rrc","a");
6398 aopPut(AOP(result),"a",MSB24-offl);
6400 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6401 emitcode("rrc","a");
6402 aopPut(AOP(result),"a",MSB16-offl);
6405 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6406 emitcode("rrc","a");
6407 aopPut(AOP(result),"a",LSB);
6414 /*-----------------------------------------------------------------*/
6415 /* genrshFour - shift four byte by a known amount != 0 */
6416 /*-----------------------------------------------------------------*/
6417 static void genrshFour (operand *result, operand *left,
6418 int shCount, int sign)
6420 D(emitcode(";", "genrshFour"););
6422 /* if shifting more that 3 bytes */
6423 if(shCount >= 24 ) {
6426 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6428 movLeft2Result(left, MSB32, result, LSB, sign);
6429 addSign(result, MSB16, sign);
6431 else if(shCount >= 16){
6434 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6436 movLeft2Result(left, MSB24, result, LSB, 0);
6437 movLeft2Result(left, MSB32, result, MSB16, sign);
6439 addSign(result, MSB24, sign);
6441 else if(shCount >= 8){
6444 shiftRLong(left, MSB16, result, sign);
6445 else if(shCount == 0){
6446 movLeft2Result(left, MSB16, result, LSB, 0);
6447 movLeft2Result(left, MSB24, result, MSB16, 0);
6448 movLeft2Result(left, MSB32, result, MSB24, sign);
6449 addSign(result, MSB32, sign);
6452 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6453 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6454 /* the last shift is signed */
6455 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6456 addSign(result, MSB32, sign);
6459 else{ /* 1 <= shCount <= 7 */
6461 shiftRLong(left, LSB, result, sign);
6463 shiftRLong(result, LSB, result, sign);
6466 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6467 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6468 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6476 /*-----------------------------------------------------------------*/
6477 /* genRightShiftLiteral - right shifting by known count */
6478 /*-----------------------------------------------------------------*/
6479 static void genRightShiftLiteral (operand *left,
6485 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6488 D(emitcode(";", "genRightShiftLiteral"););
6490 freeAsmop(right,NULL,ic,TRUE);
6492 aopOp(left,ic,FALSE, FALSE);
6493 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6496 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6500 size = getDataSize(left);
6501 /* test the LEFT size !!! */
6503 /* I suppose that the left size >= result size */
6505 size = getDataSize(result);
6507 movLeft2Result(left, size, result, size, 0);
6510 else if(shCount >= (size * 8)){
6512 /* get sign in acc.7 */
6513 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6514 addSign(result, LSB, sign);
6518 genrshOne (result,left,shCount,sign);
6522 genrshTwo (result,left,shCount,sign);
6526 genrshFour (result,left,shCount,sign);
6532 freeAsmop(left,NULL,ic,TRUE);
6533 freeAsmop(result,NULL,ic,TRUE);
6538 /*-----------------------------------------------------------------*/
6539 /* genSignedRightShift - right shift of signed number */
6540 /*-----------------------------------------------------------------*/
6541 static void genSignedRightShift (iCode *ic)
6543 operand *right, *left, *result;
6546 symbol *tlbl, *tlbl1 ;
6548 D(emitcode(";", "genSignedRightShift "););
6550 /* we do it the hard way put the shift count in b
6551 and loop thru preserving the sign */
6553 right = IC_RIGHT(ic);
6555 result = IC_RESULT(ic);
6557 aopOp(right,ic,FALSE, FALSE);
6560 if ( AOP_TYPE(right) == AOP_LIT) {
6561 genRightShiftLiteral (left,right,result,ic,1);
6565 /* shift count is unknown then we have to form
6566 a loop get the loop count in B : Note: we take
6567 only the lower order byte since shifting
6568 more that 32 bits make no sense anyway, ( the
6569 largest size of an object can be only 32 bits ) */
6571 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6572 emitcode("inc","b");
6573 freeAsmop (right,NULL,ic,TRUE);
6574 aopOp(left,ic,FALSE, FALSE);
6575 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6577 /* now move the left to the result if they are not the
6579 if (!sameRegs(AOP(left),AOP(result)) &&
6580 AOP_SIZE(result) > 1) {
6582 size = AOP_SIZE(result);
6584 _startLazyDPSEvaluation();
6586 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6587 if (*l == '@' && IS_AOP_PREG(result)) {
6589 emitcode("mov","a,%s",l);
6590 aopPut(AOP(result),"a",offset);
6592 aopPut(AOP(result),l,offset);
6595 _endLazyDPSEvaluation();
6598 /* mov the highest order bit to OVR */
6599 tlbl = newiTempLabel(NULL);
6600 tlbl1= newiTempLabel(NULL);
6602 size = AOP_SIZE(result);
6604 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6605 emitcode("rlc","a");
6606 emitcode("mov","ov,c");
6607 /* if it is only one byte then */
6609 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6611 emitcode("sjmp","%05d$",tlbl1->key+100);
6612 emitcode("","%05d$:",tlbl->key+100);
6613 emitcode("mov","c,ov");
6614 emitcode("rrc","a");
6615 emitcode("","%05d$:",tlbl1->key+100);
6616 emitcode("djnz","b,%05d$",tlbl->key+100);
6617 aopPut(AOP(result),"a",0);
6621 reAdjustPreg(AOP(result));
6622 emitcode("sjmp","%05d$",tlbl1->key+100);
6623 emitcode("","%05d$:",tlbl->key+100);
6624 emitcode("mov","c,ov");
6625 _startLazyDPSEvaluation();
6627 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6629 emitcode("rrc","a");
6630 aopPut(AOP(result),"a",offset--);
6632 _endLazyDPSEvaluation();
6633 reAdjustPreg(AOP(result));
6634 emitcode("","%05d$:",tlbl1->key+100);
6635 emitcode("djnz","b,%05d$",tlbl->key+100);
6638 freeAsmop(left,NULL,ic,TRUE);
6639 freeAsmop(result,NULL,ic,TRUE);
6642 /*-----------------------------------------------------------------*/
6643 /* genRightShift - generate code for right shifting */
6644 /*-----------------------------------------------------------------*/
6645 static void genRightShift (iCode *ic)
6647 operand *right, *left, *result;
6651 symbol *tlbl, *tlbl1 ;
6653 D(emitcode(";", "genRightShift "););
6655 /* if signed then we do it the hard way preserve the
6656 sign bit moving it inwards */
6657 retype = getSpec(operandType(IC_RESULT(ic)));
6659 if (!SPEC_USIGN(retype)) {
6660 genSignedRightShift (ic);
6664 /* signed & unsigned types are treated the same : i.e. the
6665 signed is NOT propagated inwards : quoting from the
6666 ANSI - standard : "for E1 >> E2, is equivalent to division
6667 by 2**E2 if unsigned or if it has a non-negative value,
6668 otherwise the result is implementation defined ", MY definition
6669 is that the sign does not get propagated */
6671 right = IC_RIGHT(ic);
6673 result = IC_RESULT(ic);
6675 aopOp(right,ic,FALSE, FALSE);
6678 /* if the shift count is known then do it
6679 as efficiently as possible */
6680 if (AOP_TYPE(right) == AOP_LIT) {
6681 genRightShiftLiteral (left,right,result,ic, 0);
6686 /* shift count is unknown then we have to form
6687 a loop get the loop count in B : Note: we take
6688 only the lower order byte since shifting
6689 more that 32 bits make no sense anyway, ( the
6690 largest size of an object can be only 32 bits ) */
6692 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6693 emitcode("inc","b");
6694 freeAsmop (right,NULL,ic,TRUE);
6695 aopOp(left,ic,FALSE, FALSE);
6696 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6698 /* now move the left to the result if they are not the
6700 if (!sameRegs(AOP(left),AOP(result)) &&
6701 AOP_SIZE(result) > 1) {
6703 size = AOP_SIZE(result);
6705 _startLazyDPSEvaluation();
6707 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6708 if (*l == '@' && IS_AOP_PREG(result)) {
6710 emitcode("mov","a,%s",l);
6711 aopPut(AOP(result),"a",offset);
6713 aopPut(AOP(result),l,offset);
6716 _endLazyDPSEvaluation();
6719 tlbl = newiTempLabel(NULL);
6720 tlbl1= newiTempLabel(NULL);
6721 size = AOP_SIZE(result);
6724 /* if it is only one byte then */
6726 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6728 emitcode("sjmp","%05d$",tlbl1->key+100);
6729 emitcode("","%05d$:",tlbl->key+100);
6731 emitcode("rrc","a");
6732 emitcode("","%05d$:",tlbl1->key+100);
6733 emitcode("djnz","b,%05d$",tlbl->key+100);
6734 aopPut(AOP(result),"a",0);
6738 reAdjustPreg(AOP(result));
6739 emitcode("sjmp","%05d$",tlbl1->key+100);
6740 emitcode("","%05d$:",tlbl->key+100);
6742 _startLazyDPSEvaluation();
6744 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6746 emitcode("rrc","a");
6747 aopPut(AOP(result),"a",offset--);
6749 _endLazyDPSEvaluation();
6750 reAdjustPreg(AOP(result));
6752 emitcode("","%05d$:",tlbl1->key+100);
6753 emitcode("djnz","b,%05d$",tlbl->key+100);
6756 freeAsmop(left,NULL,ic,TRUE);
6757 freeAsmop(result,NULL,ic,TRUE);
6760 /*-----------------------------------------------------------------*/
6761 /* genUnpackBits - generates code for unpacking bits */
6762 /*-----------------------------------------------------------------*/
6763 static void genUnpackBits (operand *result, char *rname, int ptype)
6770 D(emitcode(";", "genUnpackBits "););
6772 etype = getSpec(operandType(result));
6774 /* read the first byte */
6779 emitcode("mov","a,@%s",rname);
6783 emitcode("movx","a,@%s",rname);
6787 emitcode("movx","a,@dptr");
6791 emitcode("clr","a");
6792 emitcode("movc","a","@a+dptr");
6796 emitcode("lcall","__gptrget");
6800 /* if we have bitdisplacement then it fits */
6801 /* into this byte completely or if length is */
6802 /* less than a byte */
6803 if ((shCnt = SPEC_BSTR(etype)) ||
6804 (SPEC_BLEN(etype) <= 8)) {
6806 /* shift right acc */
6809 emitcode("anl","a,#0x%02x",
6810 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6811 aopPut(AOP(result),"a",offset);
6815 /* bit field did not fit in a byte */
6816 rlen = SPEC_BLEN(etype) - 8;
6817 aopPut(AOP(result),"a",offset++);
6824 emitcode("inc","%s",rname);
6825 emitcode("mov","a,@%s",rname);
6829 emitcode("inc","%s",rname);
6830 emitcode("movx","a,@%s",rname);
6834 emitcode("inc","dptr");
6835 emitcode("movx","a,@dptr");
6839 emitcode("clr","a");
6840 emitcode("inc","dptr");
6841 emitcode("movc","a","@a+dptr");
6845 emitcode("inc","dptr");
6846 emitcode("lcall","__gptrget");
6851 /* if we are done */
6855 aopPut(AOP(result),"a",offset++);
6860 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6861 aopPut(AOP(result),"a",offset);
6868 /*-----------------------------------------------------------------*/
6869 /* genDataPointerGet - generates code when ptr offset is known */
6870 /*-----------------------------------------------------------------*/
6871 static void genDataPointerGet (operand *left,
6877 int size , offset = 0;
6878 aopOp(result,ic,TRUE, FALSE);
6880 /* get the string representation of the name */
6881 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6882 size = AOP_SIZE(result);
6883 _startLazyDPSEvaluation();
6886 sprintf(buffer,"(%s + %d)",l+1,offset);
6888 sprintf(buffer,"%s",l+1);
6889 aopPut(AOP(result),buffer,offset++);
6891 _endLazyDPSEvaluation();
6893 freeAsmop(left,NULL,ic,TRUE);
6894 freeAsmop(result,NULL,ic,TRUE);
6897 /*-----------------------------------------------------------------*/
6898 /* genNearPointerGet - emitcode for near pointer fetch */
6899 /*-----------------------------------------------------------------*/
6900 static void genNearPointerGet (operand *left,
6907 sym_link *rtype, *retype, *letype;
6908 sym_link *ltype = operandType(left);
6911 rtype = operandType(result);
6912 retype= getSpec(rtype);
6913 letype= getSpec(ltype);
6915 aopOp(left,ic,FALSE, FALSE);
6917 /* if left is rematerialisable and
6918 result is not bit variable type and
6919 the left is pointer to data space i.e
6920 lower 128 bytes of space */
6921 if (AOP_TYPE(left) == AOP_IMMD &&
6922 !IS_BITVAR(retype) &&
6923 !IS_BITVAR(letype) &&
6924 DCL_TYPE(ltype) == POINTER) {
6925 genDataPointerGet (left,result,ic);
6929 /* if the value is already in a pointer register
6930 then don't need anything more */
6931 if (!AOP_INPREG(AOP(left))) {
6932 /* otherwise get a free pointer register */
6934 preg = getFreePtr(ic,&aop,FALSE);
6935 emitcode("mov","%s,%s",
6937 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6938 rname = preg->name ;
6940 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6942 freeAsmop(left,NULL,ic,TRUE);
6943 aopOp (result,ic,FALSE, FALSE);
6945 /* if bitfield then unpack the bits */
6946 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6947 genUnpackBits (result,rname,POINTER);
6949 /* we have can just get the values */
6950 int size = AOP_SIZE(result);
6954 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6956 emitcode("mov","a,@%s",rname);
6957 aopPut(AOP(result),"a",offset);
6959 sprintf(buffer,"@%s",rname);
6960 aopPut(AOP(result),buffer,offset);
6964 emitcode("inc","%s",rname);
6968 /* now some housekeeping stuff */
6970 /* we had to allocate for this iCode */
6971 freeAsmop(NULL,aop,ic,TRUE);
6973 /* we did not allocate which means left
6974 already in a pointer register, then
6975 if size > 0 && this could be used again
6976 we have to point it back to where it
6978 if (AOP_SIZE(result) > 1 &&
6979 !OP_SYMBOL(left)->remat &&
6980 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6982 int size = AOP_SIZE(result) - 1;
6984 emitcode("dec","%s",rname);
6989 freeAsmop(result,NULL,ic,TRUE);
6993 /*-----------------------------------------------------------------*/
6994 /* genPagedPointerGet - emitcode for paged pointer fetch */
6995 /*-----------------------------------------------------------------*/
6996 static void genPagedPointerGet (operand *left,
7003 sym_link *rtype, *retype, *letype;
7005 rtype = operandType(result);
7006 retype= getSpec(rtype);
7007 letype= getSpec(operandType(left));
7008 aopOp(left,ic,FALSE, FALSE);
7010 /* if the value is already in a pointer register
7011 then don't need anything more */
7012 if (!AOP_INPREG(AOP(left))) {
7013 /* otherwise get a free pointer register */
7015 preg = getFreePtr(ic,&aop,FALSE);
7016 emitcode("mov","%s,%s",
7018 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
7019 rname = preg->name ;
7021 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
7023 freeAsmop(left,NULL,ic,TRUE);
7024 aopOp (result,ic,FALSE, FALSE);
7026 /* if bitfield then unpack the bits */
7027 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7028 genUnpackBits (result,rname,PPOINTER);
7030 /* we have can just get the values */
7031 int size = AOP_SIZE(result);
7036 emitcode("movx","a,@%s",rname);
7037 aopPut(AOP(result),"a",offset);
7042 emitcode("inc","%s",rname);
7046 /* now some housekeeping stuff */
7048 /* we had to allocate for this iCode */
7049 freeAsmop(NULL,aop,ic,TRUE);
7051 /* we did not allocate which means left
7052 already in a pointer register, then
7053 if size > 0 && this could be used again
7054 we have to point it back to where it
7056 if (AOP_SIZE(result) > 1 &&
7057 !OP_SYMBOL(left)->remat &&
7058 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7060 int size = AOP_SIZE(result) - 1;
7062 emitcode("dec","%s",rname);
7067 freeAsmop(result,NULL,ic,TRUE);
7072 /*-----------------------------------------------------------------*/
7073 /* genFarPointerGet - gget value from far space */
7074 /*-----------------------------------------------------------------*/
7075 static void genFarPointerGet (operand *left,
7076 operand *result, iCode *ic)
7079 sym_link *retype = getSpec(operandType(result));
7080 sym_link *letype = getSpec(operandType(left));
7081 D(emitcode(";", "genFarPointerGet"););
7083 aopOp(left,ic,FALSE, FALSE);
7085 /* if the operand is already in dptr
7086 then we do nothing else we move the value to dptr */
7087 if (AOP_TYPE(left) != AOP_STR) {
7088 /* if this is remateriazable */
7089 if (AOP_TYPE(left) == AOP_IMMD)
7091 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7095 /* we need to get it byte by byte */
7096 _startLazyDPSEvaluation();
7097 if (AOP_TYPE(left) != AOP_DPTR)
7099 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7100 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7101 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7105 /* We need to generate a load to DPTR indirect through DPTR. */
7106 D(emitcode(";", "genFarPointerGet -- indirection special case."););
7107 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7108 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7109 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7110 emitcode("pop", "dph");
7111 emitcode("pop", "dpl");
7113 _endLazyDPSEvaluation();
7116 /* so dptr know contains the address */
7117 freeAsmop(left,NULL,ic,TRUE);
7118 aopOp(result,ic,FALSE, TRUE);
7120 /* if bit then unpack */
7121 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7122 genUnpackBits(result,"dptr",FPOINTER);
7124 size = AOP_SIZE(result);
7127 _startLazyDPSEvaluation();
7133 emitcode("movx","a,@dptr");
7135 emitcode("inc","dptr");
7137 aopPut(AOP(result),"a",offset++);
7139 _endLazyDPSEvaluation();
7142 freeAsmop(result,NULL,ic,TRUE);
7145 /*-----------------------------------------------------------------*/
7146 /* emitcodePointerGet - gget value from code space */
7147 /*-----------------------------------------------------------------*/
7148 static void emitcodePointerGet (operand *left,
7149 operand *result, iCode *ic)
7152 sym_link *retype = getSpec(operandType(result));
7154 aopOp(left,ic,FALSE, FALSE);
7156 /* if the operand is already in dptr
7157 then we do nothing else we move the value to dptr */
7158 if (AOP_TYPE(left) != AOP_STR) {
7159 /* if this is remateriazable */
7160 if (AOP_TYPE(left) == AOP_IMMD)
7162 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7165 { /* we need to get it byte by byte */
7166 _startLazyDPSEvaluation();
7167 if (AOP_TYPE(left) != AOP_DPTR)
7169 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7170 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7171 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7175 /* We need to generate a load to DPTR indirect through DPTR. */
7176 D(emitcode(";", "gencodePointerGet -- indirection special case."););
7177 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7178 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7179 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7180 emitcode("pop", "dph");
7181 emitcode("pop", "dpl");
7183 _endLazyDPSEvaluation();
7186 /* so dptr know contains the address */
7187 freeAsmop(left,NULL,ic,TRUE);
7188 aopOp(result,ic,FALSE, TRUE);
7190 /* if bit then unpack */
7191 if (IS_BITVAR(retype))
7192 genUnpackBits(result,"dptr",CPOINTER);
7194 size = AOP_SIZE(result);
7197 _startLazyDPSEvaluation();
7203 emitcode("clr","a");
7204 emitcode("movc","a,@a+dptr");
7206 emitcode("inc","dptr");
7207 aopPut(AOP(result),"a",offset++);
7209 _endLazyDPSEvaluation();
7212 freeAsmop(result,NULL,ic,TRUE);
7215 /*-----------------------------------------------------------------*/
7216 /* genGenPointerGet - gget value from generic pointer space */
7217 /*-----------------------------------------------------------------*/
7218 static void genGenPointerGet (operand *left,
7219 operand *result, iCode *ic)
7222 sym_link *retype = getSpec(operandType(result));
7223 sym_link *letype = getSpec(operandType(left));
7225 aopOp(left,ic,FALSE, TRUE);
7227 /* if the operand is already in dptr
7228 then we do nothing else we move the value to dptr */
7229 if (AOP_TYPE(left) != AOP_STR) {
7230 /* if this is remateriazable */
7231 if (AOP_TYPE(left) == AOP_IMMD) {
7232 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7233 emitcode("mov","b,#%d",pointerCode(retype));
7235 else { /* we need to get it byte by byte */
7236 _startLazyDPSEvaluation();
7237 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7238 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7239 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7240 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7241 _endLazyDPSEvaluation();
7244 /* so dptr know contains the address */
7245 freeAsmop(left,NULL,ic,TRUE);
7246 aopOp(result,ic,FALSE, TRUE);
7248 /* if bit then unpack */
7249 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7250 genUnpackBits(result,"dptr",GPOINTER);
7252 size = AOP_SIZE(result);
7256 emitcode("lcall","__gptrget");
7257 aopPut(AOP(result),"a",offset++);
7259 emitcode("inc","dptr");
7263 freeAsmop(result,NULL,ic,TRUE);
7266 /*-----------------------------------------------------------------*/
7267 /* genPointerGet - generate code for pointer get */
7268 /*-----------------------------------------------------------------*/
7269 static void genPointerGet (iCode *ic)
7271 operand *left, *result ;
7272 sym_link *type, *etype;
7275 D(emitcode(";", "genPointerGet "););
7278 result = IC_RESULT(ic) ;
7280 /* depending on the type of pointer we need to
7281 move it to the correct pointer register */
7282 type = operandType(left);
7283 etype = getSpec(type);
7284 /* if left is of type of pointer then it is simple */
7285 if (IS_PTR(type) && !IS_FUNC(type->next))
7286 p_type = DCL_TYPE(type);
7288 /* we have to go by the storage class */
7289 p_type = PTR_TYPE(SPEC_OCLS(etype));
7292 /* now that we have the pointer type we assign
7293 the pointer values */
7298 genNearPointerGet (left,result,ic);
7302 genPagedPointerGet(left,result,ic);
7306 genFarPointerGet (left,result,ic);
7310 emitcodePointerGet (left,result,ic);
7314 genGenPointerGet (left,result,ic);
7320 /*-----------------------------------------------------------------*/
7321 /* genPackBits - generates code for packed bit storage */
7322 /*-----------------------------------------------------------------*/
7323 static void genPackBits (sym_link *etype ,
7325 char *rname, int p_type)
7333 blen = SPEC_BLEN(etype);
7334 bstr = SPEC_BSTR(etype);
7336 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7339 /* if the bit lenth is less than or */
7340 /* it exactly fits a byte then */
7341 if (SPEC_BLEN(etype) <= 8 ) {
7342 shCount = SPEC_BSTR(etype) ;
7344 /* shift left acc */
7347 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7352 emitcode ("mov","b,a");
7353 emitcode("mov","a,@%s",rname);
7357 emitcode ("mov","b,a");
7358 emitcode("movx","a,@dptr");
7362 emitcode ("push","b");
7363 emitcode ("push","acc");
7364 emitcode ("lcall","__gptrget");
7365 emitcode ("pop","b");
7369 emitcode ("anl","a,#0x%02x",(unsigned char)
7370 ((unsigned char)(0xFF << (blen+bstr)) |
7371 (unsigned char)(0xFF >> (8-bstr)) ) );
7372 emitcode ("orl","a,b");
7373 if (p_type == GPOINTER)
7374 emitcode("pop","b");
7380 emitcode("mov","@%s,a",rname);
7384 emitcode("movx","@dptr,a");
7388 emitcode("lcall","__gptrput");
7393 if ( SPEC_BLEN(etype) <= 8 )
7396 emitcode("inc","%s",rname);
7397 rLen = SPEC_BLEN(etype) ;
7399 /* now generate for lengths greater than one byte */
7402 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7412 emitcode("mov","@%s,a",rname);
7414 emitcode("mov","@%s,%s",rname,l);
7419 emitcode("movx","@dptr,a");
7424 emitcode("lcall","__gptrput");
7427 emitcode ("inc","%s",rname);
7432 /* last last was not complete */
7434 /* save the byte & read byte */
7437 emitcode ("mov","b,a");
7438 emitcode("mov","a,@%s",rname);
7442 emitcode ("mov","b,a");
7443 emitcode("movx","a,@dptr");
7447 emitcode ("push","b");
7448 emitcode ("push","acc");
7449 emitcode ("lcall","__gptrget");
7450 emitcode ("pop","b");
7454 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << rLen) );
7455 emitcode ("orl","a,b");
7458 if (p_type == GPOINTER)
7459 emitcode("pop","b");
7464 emitcode("mov","@%s,a",rname);
7468 emitcode("movx","@dptr,a");
7472 emitcode("lcall","__gptrput");
7476 /*-----------------------------------------------------------------*/
7477 /* genDataPointerSet - remat pointer to data space */
7478 /*-----------------------------------------------------------------*/
7479 static void genDataPointerSet(operand *right,
7483 int size, offset = 0 ;
7484 char *l, buffer[256];
7486 aopOp(right,ic,FALSE, FALSE);
7488 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7489 size = AOP_SIZE(right);
7492 sprintf(buffer,"(%s + %d)",l+1,offset);
7494 sprintf(buffer,"%s",l+1);
7495 emitcode("mov","%s,%s",buffer,
7496 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7499 freeAsmop(right,NULL,ic,TRUE);
7500 freeAsmop(result,NULL,ic,TRUE);
7503 /*-----------------------------------------------------------------*/
7504 /* genNearPointerSet - emitcode for near pointer put */
7505 /*-----------------------------------------------------------------*/
7506 static void genNearPointerSet (operand *right,
7513 sym_link *retype, *letype;
7514 sym_link *ptype = operandType(result);
7516 retype= getSpec(operandType(right));
7517 letype= getSpec(ptype);
7519 aopOp(result,ic,FALSE, FALSE);
7521 /* if the result is rematerializable &
7522 in data space & not a bit variable */
7523 if (AOP_TYPE(result) == AOP_IMMD &&
7524 DCL_TYPE(ptype) == POINTER &&
7525 !IS_BITVAR(retype) &&
7526 !IS_BITVAR(letype)) {
7527 genDataPointerSet (right,result,ic);
7531 /* if the value is already in a pointer register
7532 then don't need anything more */
7533 if (!AOP_INPREG(AOP(result))) {
7534 /* otherwise get a free pointer register */
7536 preg = getFreePtr(ic,&aop,FALSE);
7537 emitcode("mov","%s,%s",
7539 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7540 rname = preg->name ;
7542 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7544 freeAsmop(result,NULL,ic,TRUE);
7545 aopOp (right,ic,FALSE, FALSE);
7547 /* if bitfield then unpack the bits */
7548 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7549 genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
7551 /* we have can just get the values */
7552 int size = AOP_SIZE(right);
7556 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7559 emitcode("mov","@%s,a",rname);
7561 emitcode("mov","@%s,%s",rname,l);
7563 emitcode("inc","%s",rname);
7568 /* now some housekeeping stuff */
7570 /* we had to allocate for this iCode */
7571 freeAsmop(NULL,aop,ic,TRUE);
7573 /* we did not allocate which means left
7574 already in a pointer register, then
7575 if size > 0 && this could be used again
7576 we have to point it back to where it
7578 if (AOP_SIZE(right) > 1 &&
7579 !OP_SYMBOL(result)->remat &&
7580 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7582 int size = AOP_SIZE(right) - 1;
7584 emitcode("dec","%s",rname);
7589 freeAsmop(right,NULL,ic,TRUE);
7594 /*-----------------------------------------------------------------*/
7595 /* genPagedPointerSet - emitcode for Paged pointer put */
7596 /*-----------------------------------------------------------------*/
7597 static void genPagedPointerSet (operand *right,
7604 sym_link *retype, *letype;
7606 retype= getSpec(operandType(right));
7607 letype= getSpec(operandType(result));
7609 aopOp(result,ic,FALSE, FALSE);
7611 /* if the value is already in a pointer register
7612 then don't need anything more */
7613 if (!AOP_INPREG(AOP(result))) {
7614 /* otherwise get a free pointer register */
7616 preg = getFreePtr(ic,&aop,FALSE);
7617 emitcode("mov","%s,%s",
7619 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7620 rname = preg->name ;
7622 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7624 freeAsmop(result,NULL,ic,TRUE);
7625 aopOp (right,ic,FALSE, FALSE);
7627 /* if bitfield then unpack the bits */
7628 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7629 genPackBits ((IS_BITVAR(retype) ? retype : letype) ,right,rname,PPOINTER);
7631 /* we have can just get the values */
7632 int size = AOP_SIZE(right);
7636 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7639 emitcode("movx","@%s,a",rname);
7642 emitcode("inc","%s",rname);
7648 /* now some housekeeping stuff */
7650 /* we had to allocate for this iCode */
7651 freeAsmop(NULL,aop,ic,TRUE);
7653 /* we did not allocate which means left
7654 already in a pointer register, then
7655 if size > 0 && this could be used again
7656 we have to point it back to where it
7658 if (AOP_SIZE(right) > 1 &&
7659 !OP_SYMBOL(result)->remat &&
7660 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7662 int size = AOP_SIZE(right) - 1;
7664 emitcode("dec","%s",rname);
7669 freeAsmop(right,NULL,ic,TRUE);
7674 /*-----------------------------------------------------------------*/
7675 /* genFarPointerSet - set value from far space */
7676 /*-----------------------------------------------------------------*/
7677 static void genFarPointerSet (operand *right,
7678 operand *result, iCode *ic)
7681 sym_link *retype = getSpec(operandType(right));
7682 sym_link *letype = getSpec(operandType(result));
7684 aopOp(result,ic,FALSE, FALSE);
7686 /* if the operand is already in dptr
7687 then we do nothing else we move the value to dptr */
7688 if (AOP_TYPE(result) != AOP_STR) {
7689 /* if this is remateriazable */
7690 if (AOP_TYPE(result) == AOP_IMMD)
7691 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7694 /* we need to get it byte by byte */
7695 _startLazyDPSEvaluation();
7696 if (AOP_TYPE(result) != AOP_DPTR)
7698 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7699 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7700 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7704 /* We need to generate a load to DPTR indirect through DPTR. */
7705 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7706 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7707 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7708 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7709 emitcode("pop", "dph");
7710 emitcode("pop", "dpl");
7712 _endLazyDPSEvaluation();
7715 /* so dptr know contains the address */
7716 freeAsmop(result,NULL,ic,TRUE);
7717 aopOp(right,ic,FALSE, TRUE);
7719 /* if bit then unpack */
7720 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7721 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",FPOINTER);
7723 size = AOP_SIZE(right);
7726 _startLazyDPSEvaluation();
7728 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7734 emitcode("movx","@dptr,a");
7736 emitcode("inc","dptr");
7738 _endLazyDPSEvaluation();
7741 freeAsmop(right,NULL,ic,TRUE);
7744 /*-----------------------------------------------------------------*/
7745 /* genGenPointerSet - set value from generic pointer space */
7746 /*-----------------------------------------------------------------*/
7747 static void genGenPointerSet (operand *right,
7748 operand *result, iCode *ic)
7751 sym_link *retype = getSpec(operandType(right));
7752 sym_link *letype = getSpec(operandType(result));
7754 aopOp(result,ic,FALSE, TRUE);
7756 /* if the operand is already in dptr
7757 then we do nothing else we move the value to dptr */
7758 if (AOP_TYPE(result) != AOP_STR) {
7759 _startLazyDPSEvaluation();
7760 /* if this is remateriazable */
7761 if (AOP_TYPE(result) == AOP_IMMD) {
7762 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7763 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7765 else { /* we need to get it byte by byte */
7766 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7767 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7768 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7769 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7771 _endLazyDPSEvaluation();
7773 /* so dptr know contains the address */
7774 freeAsmop(result,NULL,ic,TRUE);
7775 aopOp(right,ic,FALSE, TRUE);
7777 /* if bit then unpack */
7778 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7779 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",GPOINTER);
7781 size = AOP_SIZE(right);
7784 _startLazyDPSEvaluation();
7786 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7792 emitcode("lcall","__gptrput");
7794 emitcode("inc","dptr");
7796 _endLazyDPSEvaluation();
7799 freeAsmop(right,NULL,ic,TRUE);
7802 /*-----------------------------------------------------------------*/
7803 /* genPointerSet - stores the value into a pointer location */
7804 /*-----------------------------------------------------------------*/
7805 static void genPointerSet (iCode *ic)
7807 operand *right, *result ;
7808 sym_link *type, *etype;
7811 D(emitcode(";", "genPointerSet "););
7813 right = IC_RIGHT(ic);
7814 result = IC_RESULT(ic) ;
7816 /* depending on the type of pointer we need to
7817 move it to the correct pointer register */
7818 type = operandType(result);
7819 etype = getSpec(type);
7820 /* if left is of type of pointer then it is simple */
7821 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7822 p_type = DCL_TYPE(type);
7825 /* we have to go by the storage class */
7826 p_type = PTR_TYPE(SPEC_OCLS(etype));
7829 /* now that we have the pointer type we assign
7830 the pointer values */
7835 genNearPointerSet (right,result,ic);
7839 genPagedPointerSet (right,result,ic);
7843 genFarPointerSet (right,result,ic);
7847 genGenPointerSet (right,result,ic);
7853 /*-----------------------------------------------------------------*/
7854 /* genIfx - generate code for Ifx statement */
7855 /*-----------------------------------------------------------------*/
7856 static void genIfx (iCode *ic, iCode *popIc)
7858 operand *cond = IC_COND(ic);
7861 D(emitcode(";", "genIfx "););
7863 aopOp(cond,ic,FALSE, FALSE);
7865 /* get the value into acc */
7866 if (AOP_TYPE(cond) != AOP_CRY)
7870 /* the result is now in the accumulator */
7871 freeAsmop(cond,NULL,ic,TRUE);
7873 /* if there was something to be popped then do it */
7877 /* if the condition is a bit variable */
7878 if (isbit && IS_ITEMP(cond) &&
7880 genIfxJump(ic,SPIL_LOC(cond)->rname);
7882 if (isbit && !IS_ITEMP(cond))
7883 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7890 /*-----------------------------------------------------------------*/
7891 /* genAddrOf - generates code for address of */
7892 /*-----------------------------------------------------------------*/
7893 static void genAddrOf (iCode *ic)
7895 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7898 D(emitcode(";", "genAddrOf "););
7900 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7902 /* if the operand is on the stack then we
7903 need to get the stack offset of this
7906 /* if it has an offset then we need to compute
7909 emitcode("mov","a,_bp");
7910 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7911 aopPut(AOP(IC_RESULT(ic)),"a",0);
7913 /* we can just move _bp */
7914 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7916 /* fill the result with zero */
7917 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7920 if (options.stack10bit && size < (FPTRSIZE - 1))
7923 "*** warning: pointer to stack var truncated.\n");
7930 if (options.stack10bit && offset == 2)
7932 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7936 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7943 /* object not on stack then we need the name */
7944 size = AOP_SIZE(IC_RESULT(ic));
7948 char s[SDCC_NAME_MAX];
7950 sprintf(s,"#(%s >> %d)",
7954 sprintf(s,"#%s",sym->rname);
7955 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7959 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7963 /*-----------------------------------------------------------------*/
7964 /* genFarFarAssign - assignment when both are in far space */
7965 /*-----------------------------------------------------------------*/
7966 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7968 int size = AOP_SIZE(right);
7975 /* This is a net loss for size == 1, but a big gain
7978 D(emitcode(";", "genFarFarAssign (improved)"););
7980 aopOp(result,ic,TRUE, TRUE);
7982 _startLazyDPSEvaluation();
7986 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7990 _endLazyDPSEvaluation();
7991 freeAsmop(result,NULL,ic,FALSE);
7992 freeAsmop(right,NULL,ic,FALSE);
7997 D(emitcode(";", "genFarFarAssign "););
7999 /* first push the right side on to the stack */
8000 _startLazyDPSEvaluation();
8002 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
8004 emitcode ("push","acc");
8007 freeAsmop(right,NULL,ic,FALSE);
8008 /* now assign DPTR to result */
8009 aopOp(result,ic,FALSE, FALSE);
8010 size = AOP_SIZE(result);
8012 emitcode ("pop","acc");
8013 aopPut(AOP(result),"a",--offset);
8015 freeAsmop(result,NULL,ic,FALSE);
8016 _endLazyDPSEvaluation();
8020 /*-----------------------------------------------------------------*/
8021 /* genAssign - generate code for assignment */
8022 /*-----------------------------------------------------------------*/
8023 static void genAssign (iCode *ic)
8025 operand *result, *right;
8027 unsigned long lit = 0L;
8029 D(emitcode(";", "genAssign "););
8031 result = IC_RESULT(ic);
8032 right = IC_RIGHT(ic) ;
8034 /* if they are the same */
8035 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8038 aopOp(right,ic,FALSE, FALSE);
8040 emitcode(";", "genAssign: resultIsFar = %s",
8041 isOperandInFarSpace(result) ?
8044 /* special case both in far space */
8045 if ((AOP_TYPE(right) == AOP_DPTR ||
8046 AOP_TYPE(right) == AOP_DPTR2) &&
8047 /* IS_TRUE_SYMOP(result) && */
8048 isOperandInFarSpace(result)) {
8050 genFarFarAssign (result,right,ic);
8054 aopOp(result,ic,TRUE, FALSE);
8056 /* if they are the same registers */
8057 if (sameRegs(AOP(right),AOP(result)))
8060 /* if the result is a bit */
8061 if (AOP_TYPE(result) == AOP_CRY) {
8063 /* if the right size is a literal then
8064 we know what the value is */
8065 if (AOP_TYPE(right) == AOP_LIT) {
8066 if (((int) operandLitValue(right)))
8067 aopPut(AOP(result),one,0);
8069 aopPut(AOP(result),zero,0);
8073 /* the right is also a bit variable */
8074 if (AOP_TYPE(right) == AOP_CRY) {
8075 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8076 aopPut(AOP(result),"c",0);
8082 aopPut(AOP(result),"a",0);
8086 /* bit variables done */
8088 size = AOP_SIZE(result);
8090 if(AOP_TYPE(right) == AOP_LIT)
8091 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8094 (AOP_TYPE(result) != AOP_REG) &&
8095 (AOP_TYPE(right) == AOP_LIT) &&
8096 !IS_FLOAT(operandType(right))
8097 #ifndef LAZY_DPS_OPT
8103 D(emitcode(";", "Kevin's better literal load code"););
8104 _startLazyDPSEvaluation();
8105 while (size && ((unsigned int)(lit >> (offset*8)) != 0))
8108 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
8113 /* And now fill the rest with zeros. */
8116 emitcode("clr","a");
8120 aopPut(AOP(result), "a", offset++);
8122 _endLazyDPSEvaluation();
8124 emitcode("clr","a");
8126 _startLazyDPSEvaluation();
8129 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
8130 aopPut(AOP(result),"a",size);
8133 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
8136 _endLazyDPSEvaluation();
8141 _startLazyDPSEvaluation();
8145 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8149 _endLazyDPSEvaluation();
8153 freeAsmop (right,NULL,ic,FALSE);
8154 freeAsmop (result,NULL,ic,TRUE);
8157 /*-----------------------------------------------------------------*/
8158 /* genJumpTab - generates code for jump table */
8159 /*-----------------------------------------------------------------*/
8160 static void genJumpTab (iCode *ic)
8165 D(emitcode(";", "genJumpTab "););
8167 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
8168 /* get the condition into accumulator */
8169 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
8171 /* multiply by four! */
8172 emitcode("add","a,acc");
8173 emitcode("add","a,acc");
8174 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8176 jtab = newiTempLabel(NULL);
8177 emitcode("mov","dptr,#%05d$",jtab->key+100);
8178 emitcode("jmp","@a+dptr");
8179 emitcode("","%05d$:",jtab->key+100);
8180 /* now generate the jump labels */
8181 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8182 jtab = setNextItem(IC_JTLABELS(ic)))
8183 emitcode("ljmp","%05d$",jtab->key+100);
8187 /*-----------------------------------------------------------------*/
8188 /* genCast - gen code for casting */
8189 /*-----------------------------------------------------------------*/
8190 static void genCast (iCode *ic)
8192 operand *result = IC_RESULT(ic);
8193 sym_link *ctype = operandType(IC_LEFT(ic));
8194 sym_link *rtype = operandType(IC_RIGHT(ic));
8195 operand *right = IC_RIGHT(ic);
8198 D(emitcode(";", "genCast "););
8200 /* if they are equivalent then do nothing */
8201 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8204 aopOp(right,ic,FALSE, FALSE) ;
8205 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
8207 /* if the result is a bit */
8208 if (AOP_TYPE(result) == AOP_CRY) {
8209 /* if the right size is a literal then
8210 we know what the value is */
8211 if (AOP_TYPE(right) == AOP_LIT) {
8212 if (((int) operandLitValue(right)))
8213 aopPut(AOP(result),one,0);
8215 aopPut(AOP(result),zero,0);
8220 /* the right is also a bit variable */
8221 if (AOP_TYPE(right) == AOP_CRY) {
8222 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8223 aopPut(AOP(result),"c",0);
8229 aopPut(AOP(result),"a",0);
8233 /* if they are the same size : or less */
8234 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8236 /* if they are in the same place */
8237 if (sameRegs(AOP(right),AOP(result)))
8240 /* if they in different places then copy */
8241 size = AOP_SIZE(result);
8243 _startLazyDPSEvaluation();
8246 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8250 _endLazyDPSEvaluation();
8255 /* if the result is of type pointer */
8256 if (IS_PTR(ctype)) {
8259 sym_link *type = operandType(right);
8261 /* pointer to generic pointer */
8262 if (IS_GENPTR(ctype)) {
8267 p_type = DCL_TYPE(type);
8271 #if OLD_CAST_BEHAVIOR
8272 /* KV: we are converting a non-pointer type to
8273 * a generic pointer. This (ifdef'd out) code
8274 * says that the resulting generic pointer
8275 * should have the same class as the storage
8276 * location of the non-pointer variable.
8278 * For example, converting an int (which happens
8279 * to be stored in DATA space) to a pointer results
8280 * in a DATA generic pointer; if the original int
8281 * in XDATA space, so will be the resulting pointer.
8283 * I don't like that behavior, and thus this change:
8284 * all such conversions will be forced to XDATA and
8285 * throw a warning. If you want some non-XDATA
8286 * type, or you want to suppress the warning, you
8287 * must go through an intermediate cast, like so:
8289 * char _generic *gp = (char _xdata *)(intVar);
8291 sym_link *etype = getSpec(type);
8293 /* we have to go by the storage class */
8294 if (SPEC_OCLS(etype) != generic)
8296 p_type = PTR_TYPE(SPEC_OCLS(etype));
8301 /* Converting unknown class (i.e. register variable)
8302 * to generic pointer. This is not good, but
8303 * we'll make a guess (and throw a warning).
8306 werror(W_INT_TO_GEN_PTR_CAST);
8310 /* the first two bytes are known */
8311 size = GPTRSIZE - 1;
8313 _startLazyDPSEvaluation();
8316 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8320 _endLazyDPSEvaluation();
8322 /* the last byte depending on type */
8339 /* this should never happen */
8340 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8341 "got unknown pointer type");
8344 aopPut(AOP(result),l, GPTRSIZE - 1);
8348 /* just copy the pointers */
8349 size = AOP_SIZE(result);
8351 _startLazyDPSEvaluation();
8354 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8358 _endLazyDPSEvaluation();
8362 /* so we now know that the size of destination is greater
8363 than the size of the source */
8364 /* we move to result for the size of source */
8365 size = AOP_SIZE(right);
8367 _startLazyDPSEvaluation();
8370 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8374 _endLazyDPSEvaluation();
8376 /* now depending on the sign of the source && destination */
8377 size = AOP_SIZE(result) - AOP_SIZE(right);
8378 /* if unsigned or not an integral type */
8379 /* also, if the source is a bit, we don't need to sign extend, because
8380 * it can't possibly have set the sign bit.
8382 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype) || AOP_TYPE(right) == AOP_CRY)
8386 aopPut(AOP(result),zero,offset++);
8391 /* we need to extend the sign :{ */
8392 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8395 emitcode("rlc","a");
8396 emitcode("subb","a,acc");
8398 aopPut(AOP(result),"a",offset++);
8401 /* we are done hurray !!!! */
8404 freeAsmop(right,NULL,ic,TRUE);
8405 freeAsmop(result,NULL,ic,TRUE);
8409 /*-----------------------------------------------------------------*/
8410 /* genDjnz - generate decrement & jump if not zero instrucion */
8411 /*-----------------------------------------------------------------*/
8412 static int genDjnz (iCode *ic, iCode *ifx)
8418 /* if the if condition has a false label
8419 then we cannot save */
8423 /* if the minus is not of the form
8425 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8426 !IS_OP_LITERAL(IC_RIGHT(ic)))
8429 if (operandLitValue(IC_RIGHT(ic)) != 1)
8432 /* if the size of this greater than one then no
8434 if (getSize(operandType(IC_RESULT(ic))) > 1)
8437 /* otherwise we can save BIG */
8438 lbl = newiTempLabel(NULL);
8439 lbl1= newiTempLabel(NULL);
8441 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8443 if (IS_AOP_PREG(IC_RESULT(ic))) {
8444 emitcode("dec","%s",
8445 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8446 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8447 emitcode("jnz","%05d$",lbl->key+100);
8449 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8452 emitcode ("sjmp","%05d$",lbl1->key+100);
8453 emitcode ("","%05d$:",lbl->key+100);
8454 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8455 emitcode ("","%05d$:",lbl1->key+100);
8457 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8462 /*-----------------------------------------------------------------*/
8463 /* genReceive - generate code for a receive iCode */
8464 /*-----------------------------------------------------------------*/
8465 static void genReceive (iCode *ic)
8468 D(emitcode(";", "genReceive "););
8470 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8471 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8472 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8473 int size = getSize(operandType(IC_RESULT(ic)));
8474 int offset = fReturnSize_390 - size;
8476 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8477 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8480 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8481 size = AOP_SIZE(IC_RESULT(ic));
8484 emitcode ("pop","acc");
8485 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8490 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8492 assignResultValue(IC_RESULT(ic));
8495 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8498 /*-----------------------------------------------------------------*/
8499 /* gen390Code - generate code for Dallas 390 based controllers */
8500 /*-----------------------------------------------------------------*/
8501 void gen390Code (iCode *lic)
8506 lineHead = lineCurr = NULL;
8510 /* print the allocation information */
8512 printAllocInfo( currFunc, codeOutFile);
8514 /* if debug information required */
8515 if (options.debug && currFunc) {
8516 //jwk if (currFunc) {
8517 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8519 if (IS_STATIC(currFunc->etype))
8520 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8522 emitcode("","G$%s$0$0 ==.",currFunc->name);
8525 /* stack pointer name */
8526 if (options.useXstack)
8532 for (ic = lic ; ic ; ic = ic->next ) {
8534 if ( cln != ic->lineno ) {
8535 if ( options.debug ) {
8537 emitcode("","C$%s$%d$%d$%d ==.",
8538 ic->filename,ic->lineno,
8539 ic->level,ic->block);
8542 emitcode(";","%s %d",ic->filename,ic->lineno);
8545 /* if the result is marked as
8546 spilt and rematerializable or code for
8547 this has already been generated then
8549 if (resultRemat(ic) || ic->generated )
8552 /* depending on the operation */
8571 /* IPOP happens only when trying to restore a
8572 spilt live range, if there is an ifx statement
8573 following this pop then the if statement might
8574 be using some of the registers being popped which
8575 would destory the contents of the register so
8576 we need to check for this condition and handle it */
8578 ic->next->op == IFX &&
8579 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8580 genIfx (ic->next,ic);
8598 genEndFunction (ic);
8618 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8635 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8639 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8646 /* note these two are xlated by algebraic equivalence
8647 during parsing SDCC.y */
8648 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8649 "got '>=' or '<=' shouldn't have come here");
8653 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8665 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8669 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8673 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8700 case GET_VALUE_AT_ADDRESS:
8705 if (POINTER_SET(ic))
8732 addSet(&_G.sendSet,ic);
8737 /* piCode(ic,stdout); */
8743 /* now we are ready to call the
8744 peep hole optimizer */
8745 if (!options.nopeep)
8746 peepHole (&lineHead);
8748 /* now do the actual printing */
8749 printLine (lineHead,codeOutFile);