1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
42 #ifdef HAVE_SYS_ISA_DEFS_H
43 #include <sys/isa_defs.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
55 char *aopLiteral (value *val, int offset);
61 /* this is the down and dirty file with all kinds of
62 kludgy & hacky stuff. This is what it is all about
63 CODE GENERATION for a specific MCU . some of the
64 routines may be reusable, will have to see */
66 static char *zero = "#0x00";
67 static char *one = "#0x01";
72 unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
73 static char *fReturn[] = {"dpl","dph","dpx", "b","a" };
74 static char *accUse[] = {"a","b"};
76 static short rbank = -1;
88 static void saverbank (int, iCode *,bool);
90 #define RESULTONSTACK(x) \
91 (IC_RESULT(x) && IC_RESULT(x)->aop && \
92 IC_RESULT(x)->aop->type == AOP_STK )
94 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
95 #define MOVA(x) { char *_mova_tmp = strdup(x); \
96 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
98 emitcode("mov","a,%s",_mova_tmp); \
102 #define CLRC emitcode("clr","c")
103 #define SETC emitcode("setb","c")
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
108 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
109 0xE0, 0xC0, 0x80, 0x00};
110 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
111 0x07, 0x03, 0x01, 0x00};
118 /*-----------------------------------------------------------------*/
119 /* emitcode - writes the code into a file : for now it is simple */
120 /*-----------------------------------------------------------------*/
121 static void emitcode (char *inst,char *fmt, ...)
124 char lb[MAX_INLINEASM];
131 sprintf(lb,"%s\t",inst);
135 /* for some reason the parser throws in a mysterious "Y" at
136 the end of inline assembly code.
137 Do a make in device/lib and you know all about it.
142 if (strcmp(&inst[i],"Y")==0) {
143 fprintf (stderr, "===> BEWARE of the inline Y bug hack <===\n");
146 sprintf(lb,"%s",inst);
150 sprintf(lb,"%s",inst);
152 vsprintf(lb+(strlen(lb)),fmt,ap);
156 while (isspace(*lbp)) lbp++;
159 lineCurr = (lineCurr ?
160 connectLine(lineCurr,newLineNode(lb)) :
161 (lineHead = newLineNode(lb)));
162 lineCurr->isInline = _G.inLine;
163 lineCurr->isDebug = _G.debugLine;
167 /*-----------------------------------------------------------------*/
168 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
169 /*-----------------------------------------------------------------*/
170 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
172 bool r0iu = FALSE , r1iu = FALSE;
173 bool r0ou = FALSE , r1ou = FALSE;
175 /* the logic: if r0 & r1 used in the instruction
176 then we are in trouble otherwise */
178 /* first check if r0 & r1 are used by this
179 instruction, in which case we are in trouble */
180 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
181 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
186 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
187 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
189 /* if no usage of r0 then return it */
190 if (!r0iu && !r0ou) {
191 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
192 (*aopp)->type = AOP_R0;
194 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
197 /* if no usage of r1 then return it */
198 if (!r1iu && !r1ou) {
199 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
200 (*aopp)->type = AOP_R1;
202 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R1_IDX);
205 /* now we know they both have usage */
206 /* if r0 not used in this instruction */
208 /* push it if not already pushed */
210 emitcode ("push","%s",
211 ds390_regWithIdx(R0_IDX)->dname);
215 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
216 (*aopp)->type = AOP_R0;
218 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
221 /* if r1 not used then */
224 /* push it if not already pushed */
226 emitcode ("push","%s",
227 ds390_regWithIdx(R1_IDX)->dname);
231 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
232 (*aopp)->type = AOP_R1;
233 return ds390_regWithIdx(R1_IDX);
237 /* I said end of world but not quite end of world yet */
238 /* if this is a result then we can push it on the stack*/
240 (*aopp)->type = AOP_STK;
245 /* other wise this is true end of the world */
246 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
247 "getFreePtr should never reach here");
251 /*-----------------------------------------------------------------*/
252 /* newAsmop - creates a new asmOp */
253 /*-----------------------------------------------------------------*/
254 static asmop *newAsmop (short type)
258 aop = Safe_calloc(sizeof(asmop));
263 /* Turn this off if the world goes to hell. */
266 static int _currentDPS; /* Current processor DPS. */
267 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
268 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
270 /*-----------------------------------------------------------------*/
271 /* genSetDPTR: generate code to select which DPTR is in use (zero */
272 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
273 /* alternate DPTR (DPL1/DPH1/DPX1). */
274 /*-----------------------------------------------------------------*/
275 static void genSetDPTR(int n)
279 /* If we are doing lazy evaluation, simply note the desired
280 * change, but don't emit any code yet.
291 emitcode("mov", "dps, #0x00");
295 emitcode("mov", "dps, #0x01");
299 /*-----------------------------------------------------------------*/
300 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation*/
302 /* Any code that operates on DPTR (NB: not on the individual */
303 /* components, like DPH) *must* call _flushLazyDPS() before using */
304 /* DPTR within a lazy DPS evaluation block. */
306 /* Note that aopPut and aopGet already contain the proper calls to */
307 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
308 /* DPS evaluation block. */
310 /* Also, _flushLazyDPS must be called before any flow control */
311 /* operations that could potentially branch out of the block. */
313 /* Lazy DPS evaluation is simply an optimization (though an */
314 /* important one), so if in doubt, leave it out. */
315 /*-----------------------------------------------------------------*/
316 static void _startLazyDPSEvaluation(void)
323 /*-----------------------------------------------------------------*/
324 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
325 /* desired one. Call before using DPTR within a lazy DPS evaluation*/
327 /*-----------------------------------------------------------------*/
328 static void _flushLazyDPS(void)
336 if (_desiredDPS != _currentDPS)
340 emitcode("inc", "dps");
344 emitcode("dec", "dps");
346 _currentDPS = _desiredDPS;
350 /*-----------------------------------------------------------------*/
351 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
353 /* Forces us back to the safe state (standard DPTR selected). */
354 /*-----------------------------------------------------------------*/
355 static void _endLazyDPSEvaluation(void)
369 /*-----------------------------------------------------------------*/
370 /* pointerCode - returns the code for a pointer type */
371 /*-----------------------------------------------------------------*/
372 static int pointerCode (sym_link *etype)
375 return PTR_TYPE(SPEC_OCLS(etype));
379 /*-----------------------------------------------------------------*/
380 /* aopForSym - for a true symbol */
381 /*-----------------------------------------------------------------*/
382 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
385 memmap *space= SPEC_OCLS(sym->etype);
387 /* if already has one */
391 /* assign depending on the storage class */
392 /* if it is on the stack or indirectly addressable */
393 /* space we need to assign either r0 or r1 to it */
394 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
395 sym->aop = aop = newAsmop(0);
396 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
397 aop->size = getSize(sym->type);
399 /* now assign the address of the variable to
400 the pointer register */
401 if (aop->type != AOP_STK) {
405 emitcode("push","acc");
407 emitcode("mov","a,_bp");
408 emitcode("add","a,#0x%02x",
410 ((char)(sym->stack - _G.nRegsSaved )) :
411 ((char)sym->stack)) & 0xff);
412 emitcode("mov","%s,a",
413 aop->aopu.aop_ptr->name);
416 emitcode("pop","acc");
418 emitcode("mov","%s,#%s",
419 aop->aopu.aop_ptr->name,
421 aop->paged = space->paged;
423 aop->aopu.aop_stk = sym->stack;
427 if (sym->onStack && options.stack10bit)
429 /* It's on the 10 bit stack, which is located in
434 emitcode("push","acc");
436 emitcode("mov","a,_bp");
437 emitcode("add","a,#0x%02x",
439 ((char)(sym->stack - _G.nRegsSaved )) :
440 ((char)sym->stack)) & 0xff);
445 emitcode ("mov","dpx1,#0x40");
446 emitcode ("mov","dph1,#0x00");
447 emitcode ("mov","dpl1, a");
452 emitcode ("mov","dpx,#0x40");
453 emitcode ("mov","dph,#0x00");
454 emitcode ("mov","dpl, a");
458 emitcode("pop","acc");
460 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
461 aop->size = getSize(sym->type);
465 /* if in bit space */
466 if (IN_BITSPACE(space)) {
467 sym->aop = aop = newAsmop (AOP_CRY);
468 aop->aopu.aop_dir = sym->rname ;
469 aop->size = getSize(sym->type);
472 /* if it is in direct space */
473 if (IN_DIRSPACE(space)) {
474 sym->aop = aop = newAsmop (AOP_DIR);
475 aop->aopu.aop_dir = sym->rname ;
476 aop->size = getSize(sym->type);
480 /* special case for a function */
481 if (IS_FUNC(sym->type)) {
482 sym->aop = aop = newAsmop(AOP_IMMD);
483 aop->aopu.aop_immd = Safe_calloc(strlen(sym->rname)+1);
484 strcpy(aop->aopu.aop_immd,sym->rname);
485 aop->size = FPTRSIZE;
489 /* only remaining is far space */
490 /* in which case DPTR gets the address */
491 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
496 emitcode ("mov","dptr,#%s", sym->rname);
501 emitcode ("mov","dptr,#%s", sym->rname);
503 aop->size = getSize(sym->type);
505 /* if it is in code space */
506 if (IN_CODESPACE(space))
512 /*-----------------------------------------------------------------*/
513 /* aopForRemat - rematerialzes an object */
514 /*-----------------------------------------------------------------*/
515 static asmop *aopForRemat (symbol *sym)
517 iCode *ic = sym->rematiCode;
518 asmop *aop = newAsmop(AOP_IMMD);
524 val += operandLitValue(IC_RIGHT(ic));
525 else if (ic->op == '-')
526 val -= operandLitValue(IC_RIGHT(ic));
530 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
534 sprintf(buffer,"(%s %c 0x%04x)",
535 OP_SYMBOL(IC_LEFT(ic))->rname,
536 val >= 0 ? '+' : '-',
539 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
541 aop->aopu.aop_immd = Safe_calloc(strlen(buffer)+1);
542 strcpy(aop->aopu.aop_immd,buffer);
546 /*-----------------------------------------------------------------*/
547 /* regsInCommon - two operands have some registers in common */
548 /*-----------------------------------------------------------------*/
549 static bool regsInCommon (operand *op1, operand *op2)
554 /* if they have registers in common */
555 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
558 sym1 = OP_SYMBOL(op1);
559 sym2 = OP_SYMBOL(op2);
561 if (sym1->nRegs == 0 || sym2->nRegs == 0)
564 for (i = 0 ; i < sym1->nRegs ; i++) {
569 for (j = 0 ; j < sym2->nRegs ;j++ ) {
573 if (sym2->regs[j] == sym1->regs[i])
581 /*-----------------------------------------------------------------*/
582 /* operandsEqu - equivalent */
583 /*-----------------------------------------------------------------*/
584 static bool operandsEqu ( operand *op1, operand *op2)
588 /* if they not symbols */
589 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
592 sym1 = OP_SYMBOL(op1);
593 sym2 = OP_SYMBOL(op2);
595 /* if both are itemps & one is spilt
596 and the other is not then false */
597 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
598 sym1->isspilt != sym2->isspilt )
601 /* if they are the same */
605 if (strcmp(sym1->rname,sym2->rname) == 0)
609 /* if left is a tmp & right is not */
613 (sym1->usl.spillLoc == sym2))
620 (sym2->usl.spillLoc == sym1))
626 /*-----------------------------------------------------------------*/
627 /* sameRegs - two asmops have the same registers */
628 /*-----------------------------------------------------------------*/
629 static bool sameRegs (asmop *aop1, asmop *aop2 )
635 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
642 if (aop1->type != AOP_REG ||
643 aop2->type != AOP_REG )
646 if (aop1->size != aop2->size )
649 for (i = 0 ; i < aop1->size ; i++ )
650 if (aop1->aopu.aop_reg[i] !=
651 aop2->aopu.aop_reg[i] )
657 /*-----------------------------------------------------------------*/
658 /* aopOp - allocates an asmop for an operand : */
659 /*-----------------------------------------------------------------*/
660 static void aopOp (operand *op, iCode *ic, bool result, bool useDP2)
669 /* if this a literal */
670 if (IS_OP_LITERAL(op)) {
671 op->aop = aop = newAsmop(AOP_LIT);
672 aop->aopu.aop_lit = op->operand.valOperand;
673 aop->size = getSize(operandType(op));
677 /* if already has a asmop then continue */
681 /* if the underlying symbol has a aop */
682 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
683 op->aop = OP_SYMBOL(op)->aop;
687 /* if this is a true symbol */
688 if (IS_TRUE_SYMOP(op)) {
689 op->aop = aopForSym(ic,OP_SYMBOL(op),result, useDP2);
693 /* this is a temporary : this has
699 e) can be a return use only */
704 /* if the type is a conditional */
705 if (sym->regType == REG_CND) {
706 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
711 /* if it is spilt then two situations
713 b) has a spill location */
714 if (sym->isspilt || sym->nRegs == 0) {
716 /* rematerialize it NOW */
718 sym->aop = op->aop = aop =
720 aop->size = getSize(sym->type);
726 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
727 aop->size = getSize(sym->type);
728 for ( i = 0 ; i < 2 ; i++ )
729 aop->aopu.aop_str[i] = accUse[i];
738 /* a AOP_STR uses DPTR, but DPTR is already in use;
741 fprintf(stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
744 aop = op->aop = sym->aop = newAsmop(AOP_STR);
745 aop->size = getSize(sym->type);
746 for ( i = 0 ; i < fReturnSize_390 ; i++ )
747 aop->aopu.aop_str[i] = fReturn[i];
751 /* else spill location */
752 sym->aop = op->aop = aop =
753 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
754 aop->size = getSize(sym->type);
758 /* must be in a register */
759 sym->aop = op->aop = aop = newAsmop(AOP_REG);
760 aop->size = sym->nRegs;
761 for ( i = 0 ; i < sym->nRegs ;i++)
762 aop->aopu.aop_reg[i] = sym->regs[i];
765 /*-----------------------------------------------------------------*/
766 /* freeAsmop - free up the asmop given to an operand */
767 /*----------------------------------------------------------------*/
768 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
785 /* depending on the asmop type only three cases need work AOP_RO
786 , AOP_R1 && AOP_STK */
791 emitcode ("pop","ar0");
795 bitVectUnSetBit(ic->rUsed,R0_IDX);
801 emitcode ("pop","ar1");
805 bitVectUnSetBit(ic->rUsed,R1_IDX);
811 int stk = aop->aopu.aop_stk + aop->size;
812 bitVectUnSetBit(ic->rUsed,R0_IDX);
813 bitVectUnSetBit(ic->rUsed,R1_IDX);
815 getFreePtr(ic,&aop,FALSE);
817 if (options.stack10bit)
819 /* I'm not sure what to do here yet... */
822 "*** Warning: probably generating bad code for "
823 "10 bit stack mode.\n");
827 emitcode ("mov","a,_bp");
828 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
829 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
831 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
835 emitcode("pop","acc");
836 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
838 emitcode("dec","%s",aop->aopu.aop_ptr->name);
841 freeAsmop(op,NULL,ic,TRUE);
843 emitcode("pop","ar0");
848 emitcode("pop","ar1");
855 /* all other cases just dealloc */
859 OP_SYMBOL(op)->aop = NULL;
860 /* if the symbol has a spill */
862 SPIL_LOC(op)->aop = NULL;
867 /*------------------------------------------------------------------*/
868 /* aopGet - for fetching value of the aop */
870 /* Set canClobberACC if you are aure it is OK to clobber the value */
871 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe,*/
872 /* just less efficient. */
873 /*------------------------------------------------------------------*/
875 static char *aopGet (asmop *aop,
884 /* offset is greater than
886 if (offset > (aop->size - 1) &&
887 aop->type != AOP_LIT)
890 /* depending on type */
895 /* if we need to increment it */
896 while (offset > aop->coff) {
897 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
901 while (offset < aop->coff) {
902 emitcode("dec","%s",aop->aopu.aop_ptr->name);
908 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
909 return (dname ? "acc" : "a");
911 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
912 rs = Safe_calloc(strlen(s)+1);
919 if (aop->type == AOP_DPTR2)
923 #ifndef KEVIN_BROKE_IT
927 emitcode("xch", "a, ap");
933 while (offset > aop->coff) {
934 emitcode ("inc","dptr");
938 while (offset < aop->coff) {
939 emitcode("lcall","__decdptr");
946 emitcode("movc","a,@a+dptr");
949 emitcode("movx","a,@dptr");
952 if (aop->type == AOP_DPTR2)
956 #ifndef KEVIN_BROKE_IT
960 emitcode("xch", "a, ap");
965 return (dname ? "acc" : "a");
969 sprintf (s,"#%s",aop->aopu.aop_immd);
972 sprintf(s,"#(%s >> %d)",
978 rs = Safe_calloc(strlen(s)+1);
984 sprintf(s,"(%s + %d)",
988 sprintf(s,"%s",aop->aopu.aop_dir);
989 rs = Safe_calloc(strlen(s)+1);
995 return aop->aopu.aop_reg[offset]->dname;
997 return aop->aopu.aop_reg[offset]->name;
1000 emitcode("clr","a");
1001 emitcode("mov","c,%s",aop->aopu.aop_dir);
1002 emitcode("rlc","a") ;
1003 return (dname ? "acc" : "a");
1006 if (!offset && dname)
1008 return aop->aopu.aop_str[offset];
1011 return aopLiteral (aop->aopu.aop_lit,offset);
1014 aop->coff = offset ;
1015 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1019 return aop->aopu.aop_str[offset];
1023 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1024 "aopget got unsupported aop->type");
1027 /*-----------------------------------------------------------------*/
1028 /* aopPut - puts a string for a aop */
1029 /*-----------------------------------------------------------------*/
1030 static void aopPut (asmop *aop, char *s, int offset)
1035 if (aop->size && offset > ( aop->size - 1)) {
1036 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1037 "aopPut got offset > aop->size");
1041 /* will assign value to value */
1042 /* depending on where it is ofcourse */
1043 switch (aop->type) {
1046 sprintf(d,"(%s + %d)",
1047 aop->aopu.aop_dir,offset);
1049 sprintf(d,"%s",aop->aopu.aop_dir);
1052 emitcode("mov","%s,%s",d,s);
1057 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1058 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1060 strcmp(s,"r0") == 0 ||
1061 strcmp(s,"r1") == 0 ||
1062 strcmp(s,"r2") == 0 ||
1063 strcmp(s,"r3") == 0 ||
1064 strcmp(s,"r4") == 0 ||
1065 strcmp(s,"r5") == 0 ||
1066 strcmp(s,"r6") == 0 ||
1067 strcmp(s,"r7") == 0 )
1068 emitcode("mov","%s,%s",
1069 aop->aopu.aop_reg[offset]->dname,s);
1071 emitcode("mov","%s,%s",
1072 aop->aopu.aop_reg[offset]->name,s);
1079 if (aop->type == AOP_DPTR2)
1086 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1087 "aopPut writting to code space");
1091 while (offset > aop->coff) {
1093 emitcode ("inc","dptr");
1096 while (offset < aop->coff) {
1098 emitcode("lcall","__decdptr");
1103 /* if not in accumulater */
1106 emitcode ("movx","@dptr,a");
1108 if (aop->type == AOP_DPTR2)
1116 while (offset > aop->coff) {
1118 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1120 while (offset < aop->coff) {
1122 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1128 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1133 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1135 if (strcmp(s,"r0") == 0 ||
1136 strcmp(s,"r1") == 0 ||
1137 strcmp(s,"r2") == 0 ||
1138 strcmp(s,"r3") == 0 ||
1139 strcmp(s,"r4") == 0 ||
1140 strcmp(s,"r5") == 0 ||
1141 strcmp(s,"r6") == 0 ||
1142 strcmp(s,"r7") == 0 ) {
1144 sprintf(buffer,"a%s",s);
1145 emitcode("mov","@%s,%s",
1146 aop->aopu.aop_ptr->name,buffer);
1148 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1153 if (strcmp(s,"a") == 0)
1154 emitcode("push","acc");
1156 emitcode("push","%s",s);
1161 /* if bit variable */
1162 if (!aop->aopu.aop_dir) {
1163 emitcode("clr","a");
1164 emitcode("rlc","a");
1167 emitcode("clr","%s",aop->aopu.aop_dir);
1170 emitcode("setb","%s",aop->aopu.aop_dir);
1173 emitcode("mov","%s,c",aop->aopu.aop_dir);
1175 lbl = newiTempLabel(NULL);
1177 if (strcmp(s,"a")) {
1180 emitcode("clr","c");
1181 emitcode("jz","%05d$",lbl->key+100);
1182 emitcode("cpl","c");
1183 emitcode("","%05d$:",lbl->key+100);
1184 emitcode("mov","%s,c",aop->aopu.aop_dir);
1191 if (strcmp(aop->aopu.aop_str[offset],s))
1192 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1197 if (!offset && (strcmp(s,"acc") == 0))
1200 if (strcmp(aop->aopu.aop_str[offset],s))
1201 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1205 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1206 "aopPut got unsupported aop->type");
1213 /*-----------------------------------------------------------------*/
1214 /* reAdjustPreg - points a register back to where it should */
1215 /*-----------------------------------------------------------------*/
1216 static void reAdjustPreg (asmop *aop)
1221 if ((size = aop->size) <= 1)
1224 switch (aop->type) {
1228 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1232 if (aop->type == AOP_DPTR2)
1239 emitcode("lcall","__decdptr");
1242 if (aop->type == AOP_DPTR2)
1252 #define AOP(op) op->aop
1253 #define AOP_TYPE(op) AOP(op)->type
1254 #define AOP_SIZE(op) AOP(op)->size
1255 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1256 AOP_TYPE(x) == AOP_R0))
1258 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1259 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1262 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1263 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1264 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1266 /* Workaround for DS80C390 bug: div ab may return bogus results
1267 * if A is accessed in instruction immediately before the div.
1269 * Will be fixed in B4 rev of processor, Dallas claims.
1272 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1273 if (!AOP_NEEDSACC(RIGHT)) \
1275 /* We can load A first, then B, since \
1276 * B (the RIGHT operand) won't clobber A, \
1277 * thus avoiding touching A right before the div. \
1279 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1280 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1282 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1286 /* Just stuff in a nop after loading A. */ \
1287 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1288 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1290 emitcode("nop", "; workaround for DS80C390 div bug."); \
1293 /*-----------------------------------------------------------------*/
1294 /* genNotFloat - generates not for float operations */
1295 /*-----------------------------------------------------------------*/
1296 static void genNotFloat (operand *op, operand *res)
1302 D(emitcode(";", "genNotFloat "););
1304 /* we will put 127 in the first byte of
1306 aopPut(AOP(res),"#127",0);
1307 size = AOP_SIZE(op) - 1;
1310 _startLazyDPSEvaluation();
1311 l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
1315 emitcode("orl","a,%s",
1317 offset++,FALSE,FALSE,FALSE));
1319 _endLazyDPSEvaluation();
1320 tlbl = newiTempLabel(NULL);
1322 tlbl = newiTempLabel(NULL);
1323 aopPut(res->aop,one,1);
1324 emitcode("jz","%05d$",(tlbl->key+100));
1325 aopPut(res->aop,zero,1);
1326 emitcode("","%05d$:",(tlbl->key+100));
1328 size = res->aop->size - 2;
1330 /* put zeros in the rest */
1332 aopPut(res->aop,zero,offset++);
1335 /*-----------------------------------------------------------------*/
1336 /* opIsGptr: returns non-zero if the passed operand is */
1337 /* a generic pointer type. */
1338 /*-----------------------------------------------------------------*/
1339 static int opIsGptr(operand *op)
1341 sym_link *type = operandType(op);
1343 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1350 /*-----------------------------------------------------------------*/
1351 /* getDataSize - get the operand data size */
1352 /*-----------------------------------------------------------------*/
1353 static int getDataSize(operand *op)
1356 size = AOP_SIZE(op);
1357 if (size == GPTRSIZE)
1359 sym_link *type = operandType(op);
1360 if (IS_GENPTR(type))
1362 /* generic pointer; arithmetic operations
1363 * should ignore the high byte (pointer type).
1371 /*-----------------------------------------------------------------*/
1372 /* outAcc - output Acc */
1373 /*-----------------------------------------------------------------*/
1374 static void outAcc(operand *result)
1377 size = getDataSize(result);
1380 aopPut(AOP(result),"a",0);
1383 /* unsigned or positive */
1385 aopPut(AOP(result),zero,offset++);
1390 /*-----------------------------------------------------------------*/
1391 /* outBitC - output a bit C */
1392 /*-----------------------------------------------------------------*/
1393 static void outBitC(operand *result)
1395 /* if the result is bit */
1396 if (AOP_TYPE(result) == AOP_CRY)
1398 aopPut(AOP(result),"c",0);
1402 emitcode("clr","a");
1403 emitcode("rlc","a");
1408 /*-----------------------------------------------------------------*/
1409 /* toBoolean - emit code for orl a,operator(sizeop) */
1410 /*-----------------------------------------------------------------*/
1411 static void toBoolean(operand *oper)
1413 int size = AOP_SIZE(oper) - 1;
1416 /* The generic part of a generic pointer should
1417 * not participate in it's truth value.
1419 * i.e. 0x10000000 is zero.
1423 D(emitcode(";", "toBoolean: generic ptr special case."););
1427 _startLazyDPSEvaluation();
1428 if (AOP_NEEDSACC(oper))
1430 emitcode("push", "b");
1431 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1435 MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1439 if (AOP_NEEDSACC(oper))
1441 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1445 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1448 _endLazyDPSEvaluation();
1450 if (AOP_NEEDSACC(oper))
1452 emitcode("mov", "a,b");
1453 emitcode("pop", "b");
1458 /*-----------------------------------------------------------------*/
1459 /* genNot - generate code for ! operation */
1460 /*-----------------------------------------------------------------*/
1461 static void genNot (iCode *ic)
1464 sym_link *optype = operandType(IC_LEFT(ic));
1466 D(emitcode(";", "genNot "););
1468 /* assign asmOps to operand & result */
1469 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1470 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1472 /* if in bit space then a special case */
1473 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1474 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1475 emitcode("cpl","c");
1476 outBitC(IC_RESULT(ic));
1480 /* if type float then do float */
1481 if (IS_FLOAT(optype)) {
1482 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1486 toBoolean(IC_LEFT(ic));
1488 tlbl = newiTempLabel(NULL);
1489 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1490 emitcode("","%05d$:",tlbl->key+100);
1491 outBitC(IC_RESULT(ic));
1494 /* release the aops */
1495 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1496 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1500 /*-----------------------------------------------------------------*/
1501 /* genCpl - generate code for complement */
1502 /*-----------------------------------------------------------------*/
1503 static void genCpl (iCode *ic)
1508 D(emitcode(";", "genCpl "););
1511 /* assign asmOps to operand & result */
1512 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1513 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1515 /* if both are in bit space then
1517 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1518 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1520 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1521 emitcode("cpl","c");
1522 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1526 size = AOP_SIZE(IC_RESULT(ic));
1527 _startLazyDPSEvaluation();
1529 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1531 emitcode("cpl","a");
1532 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1534 _endLazyDPSEvaluation();
1538 /* release the aops */
1539 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1540 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1543 /*-----------------------------------------------------------------*/
1544 /* genUminusFloat - unary minus for floating points */
1545 /*-----------------------------------------------------------------*/
1546 static void genUminusFloat(operand *op,operand *result)
1548 int size ,offset =0 ;
1550 /* for this we just need to flip the
1551 first it then copy the rest in place */
1552 D(emitcode(";", "genUminusFloat"););
1554 _startLazyDPSEvaluation();
1555 size = AOP_SIZE(op) - 1;
1556 l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1559 emitcode("cpl","acc.7");
1560 aopPut(AOP(result),"a",3);
1564 aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1568 _endLazyDPSEvaluation();
1571 /*-----------------------------------------------------------------*/
1572 /* genUminus - unary minus code generation */
1573 /*-----------------------------------------------------------------*/
1574 static void genUminus (iCode *ic)
1577 sym_link *optype, *rtype;
1579 D(emitcode(";", "genUminus "););
1583 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1584 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1586 /* if both in bit space then special
1588 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1589 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1591 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1592 emitcode("cpl","c");
1593 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1597 optype = operandType(IC_LEFT(ic));
1598 rtype = operandType(IC_RESULT(ic));
1600 /* if float then do float stuff */
1601 if (IS_FLOAT(optype)) {
1602 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1606 /* otherwise subtract from zero */
1607 size = AOP_SIZE(IC_LEFT(ic));
1609 _startLazyDPSEvaluation();
1611 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1612 if (!strcmp(l,"a")) {
1615 emitcode("cpl","a");
1616 emitcode("addc", "a,#0");
1620 emitcode("clr","a");
1621 emitcode("subb","a,%s",l);
1623 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1625 _endLazyDPSEvaluation();
1627 /* if any remaining bytes in the result */
1628 /* we just need to propagate the sign */
1629 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1630 emitcode("rlc","a");
1631 emitcode("subb","a,acc");
1633 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1637 /* release the aops */
1638 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1639 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1642 /*-----------------------------------------------------------------*/
1643 /* saveRegisters - will look for a call and save the registers */
1644 /*-----------------------------------------------------------------*/
1645 static void saveRegisters(iCode *lic)
1653 for (ic = lic ; ic ; ic = ic->next)
1654 if (ic->op == CALL || ic->op == PCALL)
1658 fprintf(stderr,"found parameter push with no function call\n");
1662 /* if the registers have been saved already then
1664 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1667 /* find the registers in use at this time
1668 and push them away to safety */
1669 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1673 if (options.useXstack) {
1674 if (bitVectBitValue(rsave,R0_IDX))
1675 emitcode("mov","b,r0");
1676 emitcode("mov","r0,%s",spname);
1677 for (i = 0 ; i < ds390_nRegs ; i++) {
1678 if (bitVectBitValue(rsave,i)) {
1680 emitcode("mov","a,b");
1682 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1683 emitcode("movx","@r0,a");
1684 emitcode("inc","r0");
1687 emitcode("mov","%s,r0",spname);
1688 if (bitVectBitValue(rsave,R0_IDX))
1689 emitcode("mov","r0,b");
1691 for (i = 0 ; i < ds390_nRegs ; i++) {
1692 if (bitVectBitValue(rsave,i))
1693 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1696 detype = getSpec(operandType(IC_LEFT(ic)));
1698 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1699 IS_ISR(currFunc->etype) &&
1702 saverbank(SPEC_BANK(detype),ic,TRUE);
1705 /*-----------------------------------------------------------------*/
1706 /* unsaveRegisters - pop the pushed registers */
1707 /*-----------------------------------------------------------------*/
1708 static void unsaveRegisters (iCode *ic)
1712 /* find the registers in use at this time
1713 and push them away to safety */
1714 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1717 if (options.useXstack) {
1718 emitcode("mov","r0,%s",spname);
1719 for (i = ds390_nRegs ; i >= 0 ; i--) {
1720 if (bitVectBitValue(rsave,i)) {
1721 emitcode("dec","r0");
1722 emitcode("movx","a,@r0");
1724 emitcode("mov","b,a");
1726 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1730 emitcode("mov","%s,r0",spname);
1731 if (bitVectBitValue(rsave,R0_IDX))
1732 emitcode("mov","r0,b");
1734 for (i = ds390_nRegs ; i >= 0 ; i--) {
1735 if (bitVectBitValue(rsave,i))
1736 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1742 /*-----------------------------------------------------------------*/
1744 /*-----------------------------------------------------------------*/
1745 static void pushSide(operand * oper, int size)
1748 _startLazyDPSEvaluation();
1750 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1751 if (AOP_TYPE(oper) != AOP_REG &&
1752 AOP_TYPE(oper) != AOP_DIR &&
1754 emitcode("mov","a,%s",l);
1755 emitcode("push","acc");
1757 emitcode("push","%s",l);
1759 _endLazyDPSEvaluation();
1762 /*-----------------------------------------------------------------*/
1763 /* assignResultValue - */
1764 /*-----------------------------------------------------------------*/
1765 static void assignResultValue(operand * oper)
1768 int size = AOP_SIZE(oper);
1770 _startLazyDPSEvaluation();
1772 aopPut(AOP(oper),fReturn[offset],offset);
1775 _endLazyDPSEvaluation();
1779 /*-----------------------------------------------------------------*/
1780 /* genXpush - pushes onto the external stack */
1781 /*-----------------------------------------------------------------*/
1782 static void genXpush (iCode *ic)
1784 asmop *aop = newAsmop(0);
1786 int size,offset = 0;
1788 D(emitcode(";", "genXpush "););
1790 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1791 r = getFreePtr(ic,&aop,FALSE);
1794 emitcode("mov","%s,_spx",r->name);
1796 size = AOP_SIZE(IC_LEFT(ic));
1797 _startLazyDPSEvaluation();
1800 char *l = aopGet(AOP(IC_LEFT(ic)),
1801 offset++,FALSE,FALSE,TRUE);
1803 emitcode("movx","@%s,a",r->name);
1804 emitcode("inc","%s",r->name);
1807 _endLazyDPSEvaluation();
1810 emitcode("mov","_spx,%s",r->name);
1812 freeAsmop(NULL,aop,ic,TRUE);
1813 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1816 /*-----------------------------------------------------------------*/
1817 /* genIpush - genrate code for pushing this gets a little complex */
1818 /*-----------------------------------------------------------------*/
1819 static void genIpush (iCode *ic)
1821 int size, offset = 0 ;
1824 D(emitcode(";", "genIpush "););
1827 /* if this is not a parm push : ie. it is spill push
1828 and spill push is always done on the local stack */
1829 if (!ic->parmPush) {
1831 /* and the item is spilt then do nothing */
1832 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1835 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1836 size = AOP_SIZE(IC_LEFT(ic));
1837 /* push it on the stack */
1838 _startLazyDPSEvaluation();
1840 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1845 emitcode("push","%s",l);
1847 _endLazyDPSEvaluation();
1851 /* this is a paramter push: in this case we call
1852 the routine to find the call and save those
1853 registers that need to be saved */
1856 /* if use external stack then call the external
1857 stack pushing routine */
1858 if (options.useXstack) {
1863 /* then do the push */
1864 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1866 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1867 size = AOP_SIZE(IC_LEFT(ic));
1869 _startLazyDPSEvaluation();
1871 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1872 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1873 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1875 emitcode("mov","a,%s",l);
1876 emitcode("push","acc");
1878 emitcode("push","%s",l);
1880 _endLazyDPSEvaluation();
1882 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1885 /*-----------------------------------------------------------------*/
1886 /* genIpop - recover the registers: can happen only for spilling */
1887 /*-----------------------------------------------------------------*/
1888 static void genIpop (iCode *ic)
1892 D(emitcode(";", "genIpop "););
1895 /* if the temp was not pushed then */
1896 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1899 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1900 size = AOP_SIZE(IC_LEFT(ic));
1902 _startLazyDPSEvaluation();
1905 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1908 _endLazyDPSEvaluation();
1910 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1913 /*-----------------------------------------------------------------*/
1914 /* unsaverbank - restores the resgister bank from stack */
1915 /*-----------------------------------------------------------------*/
1916 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1923 if (options.useXstack) {
1925 r = getFreePtr(ic,&aop,FALSE);
1928 emitcode("mov","%s,_spx",r->name);
1929 emitcode("movx","a,@%s",r->name);
1930 emitcode("mov","psw,a");
1931 emitcode("dec","%s",r->name);
1934 emitcode ("pop","psw");
1937 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1938 if (options.useXstack) {
1939 emitcode("movx","a,@%s",r->name);
1940 emitcode("mov","(%s+%d),a",
1941 regs390[i].base,8*bank+regs390[i].offset);
1942 emitcode("dec","%s",r->name);
1945 emitcode("pop","(%s+%d)",
1946 regs390[i].base,8*bank+regs390[i].offset);
1949 if (options.useXstack) {
1951 emitcode("mov","_spx,%s",r->name);
1952 freeAsmop(NULL,aop,ic,TRUE);
1957 /*-----------------------------------------------------------------*/
1958 /* saverbank - saves an entire register bank on the stack */
1959 /*-----------------------------------------------------------------*/
1960 static void saverbank (int bank, iCode *ic, bool pushPsw)
1966 if (options.useXstack) {
1969 r = getFreePtr(ic,&aop,FALSE);
1970 emitcode("mov","%s,_spx",r->name);
1974 for (i = 0 ; i < ds390_nRegs ;i++) {
1975 if (options.useXstack) {
1976 emitcode("inc","%s",r->name);
1977 emitcode("mov","a,(%s+%d)",
1978 regs390[i].base,8*bank+regs390[i].offset);
1979 emitcode("movx","@%s,a",r->name);
1981 emitcode("push","(%s+%d)",
1982 regs390[i].base,8*bank+regs390[i].offset);
1986 if (options.useXstack) {
1987 emitcode("mov","a,psw");
1988 emitcode("movx","@%s,a",r->name);
1989 emitcode("inc","%s",r->name);
1990 emitcode("mov","_spx,%s",r->name);
1991 freeAsmop (NULL,aop,ic,TRUE);
1994 emitcode("push","psw");
1996 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2002 /*-----------------------------------------------------------------*/
2003 /* genCall - generates a call statement */
2004 /*-----------------------------------------------------------------*/
2005 static void genCall (iCode *ic)
2009 D(emitcode(";", "genCall "););
2011 /* if caller saves & we have not saved then */
2015 /* if we are calling a function that is not using
2016 the same register bank then we need to save the
2017 destination registers on the stack */
2018 detype = getSpec(operandType(IC_LEFT(ic)));
2020 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2021 IS_ISR(currFunc->etype) &&
2024 saverbank(SPEC_BANK(detype),ic,TRUE);
2026 /* if send set is not empty the assign */
2030 for (sic = setFirstItem(_G.sendSet) ; sic ;
2031 sic = setNextItem(_G.sendSet))
2033 int size, offset = 0;
2035 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
2036 size = AOP_SIZE(IC_LEFT(sic));
2038 _startLazyDPSEvaluation();
2040 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2041 FALSE, FALSE, TRUE);
2042 if (strcmp(l,fReturn[offset]))
2043 emitcode("mov","%s,%s",
2048 _endLazyDPSEvaluation();
2049 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2054 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2055 OP_SYMBOL(IC_LEFT(ic))->rname :
2056 OP_SYMBOL(IC_LEFT(ic))->name));
2058 /* if we need assign a result value */
2059 if ((IS_ITEMP(IC_RESULT(ic)) &&
2060 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2061 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2062 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2065 /* Not really related to LAZY_DPS_OPT, but don't want
2066 * another testing flag right now...
2068 #define FAR_RETURN_OPT
2069 #ifdef FAR_RETURN_OPT
2070 if (isOperandInFarSpace(IC_RESULT(ic))
2071 && getSize(operandType(IC_RESULT(ic))) <= 2)
2073 int size = getSize(operandType(IC_RESULT(ic)));
2075 /* Special case for 1 or 2 byte return in far space. */
2076 emitcode(";", "Kevin function call abuse #1");
2081 emitcode("mov", "b,%s", fReturn[1]);
2084 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2085 aopPut(AOP(IC_RESULT(ic)),"a",0);
2089 aopPut(AOP(IC_RESULT(ic)),"b",1);
2091 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2097 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2100 assignResultValue(IC_RESULT(ic));
2102 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2105 if (!isOperandInFarSpace(IC_RESULT(ic)))
2108 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2111 assignResultValue(IC_RESULT(ic));
2113 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2117 /* Result is in far space, and requires DPTR to access
2118 * it. Push the result onto the stack and restore from
2121 int size = getSize(operandType(IC_RESULT(ic)));
2122 int offset = size - 1;
2125 emitcode(";", "Kevin function call abuse #1");
2127 /* first push the right side on to the stack */
2128 /* NB: this relies on the fact that "a" is the last
2129 * register in fReturn. If it were not, the MOVA
2130 * would potentially clobber a returned byte in A.
2133 l = fReturn[offset--];
2135 emitcode ("push","acc");
2138 /* now assign DPTR to result */
2139 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2140 size = AOP_SIZE(IC_RESULT(ic));
2141 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
2143 emitcode ("pop","acc");
2144 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
2146 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2151 /* adjust the stack for parameters if
2153 if (IC_LEFT(ic)->parmBytes) {
2155 if (IC_LEFT(ic)->parmBytes > 3) {
2156 emitcode("mov","a,%s",spname);
2157 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2158 emitcode("mov","%s,a",spname);
2160 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2161 emitcode("dec","%s",spname);
2165 /* if register bank was saved then pop them */
2167 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2169 /* if we hade saved some registers then unsave them */
2170 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2171 unsaveRegisters (ic);
2176 /*-----------------------------------------------------------------*/
2177 /* genPcall - generates a call by pointer statement */
2178 /*-----------------------------------------------------------------*/
2179 static void genPcall (iCode *ic)
2182 symbol *rlbl = newiTempLabel(NULL);
2184 D(emitcode(";", "genPcall "););
2187 /* if caller saves & we have not saved then */
2191 /* if we are calling a function that is not using
2192 the same register bank then we need to save the
2193 destination registers on the stack */
2194 detype = getSpec(operandType(IC_LEFT(ic)));
2196 IS_ISR(currFunc->etype) &&
2197 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2198 saverbank(SPEC_BANK(detype),ic,TRUE);
2201 /* push the return address on to the stack */
2202 emitcode("mov","a,#%05d$",(rlbl->key+100));
2203 emitcode("push","acc");
2204 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2205 emitcode("push","acc");
2207 if (options.model == MODEL_FLAT24)
2209 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2210 emitcode("push","acc");
2213 /* now push the calling address */
2214 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2216 pushSide(IC_LEFT(ic), FPTRSIZE);
2218 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2220 /* if send set is not empty the assign */
2224 for (sic = setFirstItem(_G.sendSet) ; sic ;
2225 sic = setNextItem(_G.sendSet))
2227 int size, offset = 0;
2229 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2230 size = AOP_SIZE(IC_LEFT(sic));
2231 _startLazyDPSEvaluation();
2234 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2236 if (strcmp(l,fReturn[offset]))
2238 emitcode("mov","%s,%s",
2244 _endLazyDPSEvaluation();
2245 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2251 emitcode("","%05d$:",(rlbl->key+100));
2254 /* if we need assign a result value */
2255 if ((IS_ITEMP(IC_RESULT(ic)) &&
2256 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2257 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2258 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2261 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2264 assignResultValue(IC_RESULT(ic));
2266 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2269 /* adjust the stack for parameters if
2271 if (IC_LEFT(ic)->parmBytes) {
2273 if (IC_LEFT(ic)->parmBytes > 3) {
2274 emitcode("mov","a,%s",spname);
2275 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2276 emitcode("mov","%s,a",spname);
2278 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2279 emitcode("dec","%s",spname);
2283 /* if register bank was saved then unsave them */
2285 (SPEC_BANK(currFunc->etype) !=
2287 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2289 /* if we hade saved some registers then
2292 unsaveRegisters (ic);
2296 /*-----------------------------------------------------------------*/
2297 /* resultRemat - result is rematerializable */
2298 /*-----------------------------------------------------------------*/
2299 static int resultRemat (iCode *ic)
2301 if (SKIP_IC(ic) || ic->op == IFX)
2304 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2305 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2306 if (sym->remat && !POINTER_SET(ic))
2313 #if defined(__BORLANDC__) || defined(_MSC_VER)
2314 #define STRCASECMP stricmp
2316 #define STRCASECMP strcasecmp
2319 /*-----------------------------------------------------------------*/
2320 /* inExcludeList - return 1 if the string is in exclude Reg list */
2321 /*-----------------------------------------------------------------*/
2322 static bool inExcludeList(char *s)
2326 if (options.excludeRegs[i] &&
2327 STRCASECMP(options.excludeRegs[i],"none") == 0)
2330 for ( i = 0 ; options.excludeRegs[i]; i++) {
2331 if (options.excludeRegs[i] &&
2332 STRCASECMP(s,options.excludeRegs[i]) == 0)
2338 /*-----------------------------------------------------------------*/
2339 /* genFunction - generated code for function entry */
2340 /*-----------------------------------------------------------------*/
2341 static void genFunction (iCode *ic)
2346 D(emitcode(";", "genFunction "););
2349 /* create the function header */
2350 emitcode(";","-----------------------------------------");
2351 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2352 emitcode(";","-----------------------------------------");
2354 emitcode("","%s:",sym->rname);
2355 fetype = getSpec(operandType(IC_LEFT(ic)));
2357 /* if critical function then turn interrupts off */
2358 if (SPEC_CRTCL(fetype))
2359 emitcode("clr","ea");
2361 /* here we need to generate the equates for the
2362 register bank if required */
2363 if (SPEC_BANK(fetype) != rbank) {
2366 rbank = SPEC_BANK(fetype);
2367 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2368 if (strcmp(regs390[i].base,"0") == 0)
2369 emitcode("","%s = 0x%02x",
2371 8*rbank+regs390[i].offset);
2373 emitcode ("","%s = %s + 0x%02x",
2376 8*rbank+regs390[i].offset);
2380 /* if this is an interrupt service routine then
2381 save acc, b, dpl, dph */
2382 if (IS_ISR(sym->etype)) {
2384 if (!inExcludeList("acc"))
2385 emitcode ("push","acc");
2386 if (!inExcludeList("b"))
2387 emitcode ("push","b");
2388 if (!inExcludeList("dpl"))
2389 emitcode ("push","dpl");
2390 if (!inExcludeList("dph"))
2391 emitcode ("push","dph");
2392 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2394 emitcode ("push", "dpx");
2395 /* Make sure we're using standard DPTR */
2396 emitcode ("push", "dps");
2397 emitcode ("mov", "dps, #0x00");
2398 if (options.stack10bit)
2400 /* This ISR could conceivably use DPTR2. Better save it. */
2401 emitcode ("push", "dpl1");
2402 emitcode ("push", "dph1");
2403 emitcode ("push", "dpx1");
2404 emitcode ("push", "ap");
2407 /* if this isr has no bank i.e. is going to
2408 run with bank 0 , then we need to save more
2410 if (!SPEC_BANK(sym->etype)) {
2412 /* if this function does not call any other
2413 function then we can be economical and
2414 save only those registers that are used */
2415 if (! sym->hasFcall) {
2418 /* if any registers used */
2419 if (sym->regsUsed) {
2420 /* save the registers used */
2421 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2422 if (bitVectBitValue(sym->regsUsed,i) ||
2423 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2424 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2429 /* this function has a function call cannot
2430 determines register usage so we will have the
2432 saverbank(0,ic,FALSE);
2436 /* if callee-save to be used for this function
2437 then save the registers being used in this function */
2438 if (sym->calleeSave) {
2441 /* if any registers used */
2442 if (sym->regsUsed) {
2443 /* save the registers used */
2444 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2445 if (bitVectBitValue(sym->regsUsed,i) ||
2446 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2447 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2455 /* set the register bank to the desired value */
2456 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2457 emitcode("push","psw");
2458 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2461 if (IS_RENT(sym->etype) || options.stackAuto) {
2463 if (options.useXstack) {
2464 emitcode("mov","r0,%s",spname);
2465 emitcode("mov","a,_bp");
2466 emitcode("movx","@r0,a");
2467 emitcode("inc","%s",spname);
2471 /* set up the stack */
2472 emitcode ("push","_bp"); /* save the callers stack */
2474 emitcode ("mov","_bp,%s",spname);
2477 /* adjust the stack for the function */
2482 werror(W_STACK_OVERFLOW,sym->name);
2484 if (i > 3 && sym->recvSize < 4) {
2486 emitcode ("mov","a,sp");
2487 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2488 emitcode ("mov","sp,a");
2493 emitcode("inc","sp");
2498 emitcode ("mov","a,_spx");
2499 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2500 emitcode ("mov","_spx,a");
2505 /*-----------------------------------------------------------------*/
2506 /* genEndFunction - generates epilogue for functions */
2507 /*-----------------------------------------------------------------*/
2508 static void genEndFunction (iCode *ic)
2510 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2512 D(emitcode(";", "genEndFunction "););
2514 if (IS_RENT(sym->etype) || options.stackAuto)
2516 emitcode ("mov","%s,_bp",spname);
2519 /* if use external stack but some variables were
2520 added to the local stack then decrement the
2522 if (options.useXstack && sym->stack) {
2523 emitcode("mov","a,sp");
2524 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2525 emitcode("mov","sp,a");
2529 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2530 if (options.useXstack) {
2531 emitcode("mov","r0,%s",spname);
2532 emitcode("movx","a,@r0");
2533 emitcode("mov","_bp,a");
2534 emitcode("dec","%s",spname);
2538 emitcode ("pop","_bp");
2542 /* restore the register bank */
2543 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2544 emitcode ("pop","psw");
2546 if (IS_ISR(sym->etype)) {
2548 /* now we need to restore the registers */
2549 /* if this isr has no bank i.e. is going to
2550 run with bank 0 , then we need to save more
2552 if (!SPEC_BANK(sym->etype)) {
2554 /* if this function does not call any other
2555 function then we can be economical and
2556 save only those registers that are used */
2557 if (! sym->hasFcall) {
2560 /* if any registers used */
2561 if (sym->regsUsed) {
2562 /* save the registers used */
2563 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2564 if (bitVectBitValue(sym->regsUsed,i) ||
2565 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2566 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2571 /* this function has a function call cannot
2572 determines register usage so we will have the
2574 unsaverbank(0,ic,FALSE);
2578 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2580 if (options.stack10bit)
2582 emitcode ("pop", "ap");
2583 emitcode ("pop", "dpx1");
2584 emitcode ("pop", "dph1");
2585 emitcode ("pop", "dpl1");
2587 emitcode ("pop", "dps");
2588 emitcode ("pop", "dpx");
2590 if (!inExcludeList("dph"))
2591 emitcode ("pop","dph");
2592 if (!inExcludeList("dpl"))
2593 emitcode ("pop","dpl");
2594 if (!inExcludeList("b"))
2595 emitcode ("pop","b");
2596 if (!inExcludeList("acc"))
2597 emitcode ("pop","acc");
2599 if (SPEC_CRTCL(sym->etype))
2600 emitcode("setb","ea");
2602 /* if debug then send end of function */
2603 /* if (options.debug && currFunc) { */
2606 emitcode("","C$%s$%d$%d$%d ==.",
2607 ic->filename,currFunc->lastLine,
2608 ic->level,ic->block);
2609 if (IS_STATIC(currFunc->etype))
2610 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2612 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2616 emitcode ("reti","");
2619 if (SPEC_CRTCL(sym->etype))
2620 emitcode("setb","ea");
2622 if (sym->calleeSave) {
2625 /* if any registers used */
2626 if (sym->regsUsed) {
2627 /* save the registers used */
2628 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2629 if (bitVectBitValue(sym->regsUsed,i) ||
2630 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2631 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2637 /* if debug then send end of function */
2640 emitcode("","C$%s$%d$%d$%d ==.",
2641 ic->filename,currFunc->lastLine,
2642 ic->level,ic->block);
2643 if (IS_STATIC(currFunc->etype))
2644 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2646 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2650 emitcode ("ret","");
2655 /*-----------------------------------------------------------------*/
2656 /* genRet - generate code for return statement */
2657 /*-----------------------------------------------------------------*/
2658 static void genRet (iCode *ic)
2660 int size,offset = 0 , pushed = 0;
2662 D(emitcode(";", "genRet "););
2664 /* if we have no return value then
2665 just generate the "ret" */
2669 /* we have something to return then
2670 move the return value into place */
2671 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2672 size = AOP_SIZE(IC_LEFT(ic));
2674 _startLazyDPSEvaluation();
2677 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2678 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2680 emitcode("push","%s",l);
2683 l = aopGet(AOP(IC_LEFT(ic)),offset,
2685 if (strcmp(fReturn[offset],l))
2686 emitcode("mov","%s,%s",fReturn[offset++],l);
2689 _endLazyDPSEvaluation();
2694 if (strcmp(fReturn[pushed],"a"))
2695 emitcode("pop",fReturn[pushed]);
2697 emitcode("pop","acc");
2700 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2703 /* generate a jump to the return label
2704 if the next is not the return statement */
2705 if (!(ic->next && ic->next->op == LABEL &&
2706 IC_LABEL(ic->next) == returnLabel))
2708 emitcode("ljmp","%05d$",(returnLabel->key+100));
2712 /*-----------------------------------------------------------------*/
2713 /* genLabel - generates a label */
2714 /*-----------------------------------------------------------------*/
2715 static void genLabel (iCode *ic)
2717 /* special case never generate */
2718 if (IC_LABEL(ic) == entryLabel)
2721 D(emitcode(";", "genLabel "););
2723 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2726 /*-----------------------------------------------------------------*/
2727 /* genGoto - generates a ljmp */
2728 /*-----------------------------------------------------------------*/
2729 static void genGoto (iCode *ic)
2731 D(emitcode(";", "genGoto "););
2732 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2735 /*-----------------------------------------------------------------*/
2736 /* findLabelBackwards: walks back through the iCode chain looking */
2737 /* for the given label. Returns number of iCode instructions */
2738 /* between that label and given ic. */
2739 /* Returns zero if label not found. */
2740 /*-----------------------------------------------------------------*/
2741 static int findLabelBackwards(iCode *ic, int key)
2750 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2752 /* printf("findLabelBackwards = %d\n", count); */
2760 /*-----------------------------------------------------------------*/
2761 /* genPlusIncr :- does addition with increment if possible */
2762 /*-----------------------------------------------------------------*/
2763 static bool genPlusIncr (iCode *ic)
2765 unsigned int icount ;
2766 unsigned int size = getDataSize(IC_RESULT(ic));
2768 /* will try to generate an increment */
2769 /* if the right side is not a literal
2771 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2774 /* if the literal value of the right hand side
2775 is greater than 4 then it is not worth it */
2776 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2779 /* if increment 16 bits in register */
2781 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2782 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2783 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2790 /* If the next instruction is a goto and the goto target
2791 * is <= 5 instructions previous to this, we can generate
2792 * jumps straight to that target.
2794 if (ic->next && ic->next->op == GOTO
2795 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2796 && labelRange <= 5 )
2798 emitcode(";", "tail increment optimized (range %d)", labelRange);
2799 tlbl = IC_LABEL(ic->next);
2804 tlbl = newiTempLabel(NULL);
2807 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2808 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2809 IS_AOP_PREG(IC_RESULT(ic)))
2810 emitcode("cjne","%s,#0x00,%05d$"
2811 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2814 emitcode("clr","a");
2815 emitcode("cjne","a,%s,%05d$"
2816 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2820 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2823 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2824 IS_AOP_PREG(IC_RESULT(ic)))
2825 emitcode("cjne","%s,#0x00,%05d$"
2826 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2829 emitcode("cjne","a,%s,%05d$"
2830 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2833 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2837 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2838 IS_AOP_PREG(IC_RESULT(ic)))
2839 emitcode("cjne","%s,#0x00,%05d$"
2840 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2843 emitcode("cjne","a,%s,%05d$"
2844 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2847 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2852 emitcode("","%05d$:",tlbl->key+100);
2857 /* if the sizes are greater than 1 then we cannot */
2858 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2859 AOP_SIZE(IC_LEFT(ic)) > 1 )
2862 /* we can if the aops of the left & result match or
2863 if they are in registers and the registers are the
2866 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2867 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2868 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2871 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2872 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2873 aopPut(AOP(IC_RESULT(ic)),"a",0);
2876 _startLazyDPSEvaluation();
2879 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2881 _endLazyDPSEvaluation();
2890 /*-----------------------------------------------------------------*/
2891 /* outBitAcc - output a bit in acc */
2892 /*-----------------------------------------------------------------*/
2893 static void outBitAcc(operand *result)
2895 symbol *tlbl = newiTempLabel(NULL);
2896 /* if the result is a bit */
2897 if (AOP_TYPE(result) == AOP_CRY){
2898 aopPut(AOP(result),"a",0);
2901 emitcode("jz","%05d$",tlbl->key+100);
2902 emitcode("mov","a,%s",one);
2903 emitcode("","%05d$:",tlbl->key+100);
2908 /*-----------------------------------------------------------------*/
2909 /* genPlusBits - generates code for addition of two bits */
2910 /*-----------------------------------------------------------------*/
2911 static void genPlusBits (iCode *ic)
2913 D(emitcode(";", "genPlusBits "););
2914 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2915 symbol *lbl = newiTempLabel(NULL);
2916 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2917 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2918 emitcode("cpl","c");
2919 emitcode("","%05d$:",(lbl->key+100));
2920 outBitC(IC_RESULT(ic));
2923 emitcode("clr","a");
2924 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2925 emitcode("rlc","a");
2926 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2927 emitcode("addc","a,#0x00");
2928 outAcc(IC_RESULT(ic));
2932 static void adjustArithmeticResult(iCode *ic)
2934 if (opIsGptr(IC_RESULT(ic)) &&
2935 opIsGptr(IC_LEFT(ic)) &&
2936 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2938 aopPut(AOP(IC_RESULT(ic)),
2939 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2943 if (opIsGptr(IC_RESULT(ic)) &&
2944 opIsGptr(IC_RIGHT(ic)) &&
2945 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2947 aopPut(AOP(IC_RESULT(ic)),
2948 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2952 if (opIsGptr(IC_RESULT(ic)) &&
2953 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2954 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2955 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2956 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2958 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2959 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2964 #define AOP_OP_3(ic) \
2965 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2966 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2967 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2968 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2969 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2971 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2973 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2976 #define AOP_OP_3(ic) \
2977 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2978 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2979 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
2980 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2981 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2982 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2984 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2986 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2989 #define AOP_OP_3_NOFATAL(ic, rc) \
2990 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2991 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2992 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2993 isOperandInFarSpace(IC_RESULT(ic))) \
2995 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3000 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3001 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3003 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3004 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3006 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3008 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
3012 #define AOP_OP_2(ic) \
3013 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3014 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3019 #define AOP_SET_LOCALS(ic) \
3020 left = IC_LEFT(ic); \
3021 right = IC_RIGHT(ic); \
3022 result = IC_RESULT(ic);
3024 /*-----------------------------------------------------------------*/
3025 /* genPlus - generates code for addition */
3026 /*-----------------------------------------------------------------*/
3027 static void genPlus (iCode *ic)
3029 int size, offset = 0;
3030 bool pushResult = FALSE;
3033 D(emitcode(";", "genPlus "););
3035 /* special cases :- */
3038 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
3039 aopOp (IC_LEFT(ic),ic,FALSE,
3040 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3041 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
3042 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
3048 aopOp (IC_RESULT(ic),ic,TRUE,
3049 ((AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)
3050 || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR)));
3053 AOP_OP_3_NOFATAL(ic, pushResult);
3056 D(emitcode(";", "genPlus: must push result: 3 ops in far space"););
3062 /* if literal, literal on the right or
3063 if left requires ACC or right is already
3065 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)
3066 || ((AOP_NEEDSACC(IC_LEFT(ic))) && !(AOP_NEEDSACC(IC_RIGHT(ic))))
3067 || AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC )
3069 operand *t = IC_RIGHT(ic);
3070 IC_RIGHT(ic) = IC_LEFT(ic);
3072 emitcode(";", "Swapped plus args.");
3075 /* if both left & right are in bit
3077 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3078 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3083 /* if left in bit space & right literal */
3084 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3085 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3086 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3087 /* if result in bit space */
3088 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3089 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
3090 emitcode("cpl","c");
3091 outBitC(IC_RESULT(ic));
3093 size = getDataSize(IC_RESULT(ic));
3094 _startLazyDPSEvaluation();
3096 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3097 emitcode("addc","a,#00");
3098 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3100 _endLazyDPSEvaluation();
3105 /* if I can do an increment instead
3106 of add then GOOD for ME */
3107 if (genPlusIncr (ic) == TRUE)
3109 emitcode(";", "did genPlusIncr");
3114 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3116 _startLazyDPSEvaluation();
3119 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3121 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3123 emitcode("add","a,%s",
3124 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3126 emitcode("addc","a,%s",
3127 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3129 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3131 emitcode("add","a,%s",
3132 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3134 emitcode("addc","a,%s",
3135 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3139 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3143 emitcode("push", "acc");
3147 _endLazyDPSEvaluation();
3151 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3153 size = getDataSize(IC_LEFT(ic));
3154 rSize = getDataSize(IC_RESULT(ic));
3156 /* If the pushed data is bigger than the result,
3157 * simply discard unused bytes. Icky, but works.
3159 * Should we throw a warning here? We're losing data...
3161 while (size > rSize)
3163 D(emitcode(";", "discarding unused result byte."););
3164 emitcode("pop", "acc");
3170 emitcode("clr", "a");
3171 /* Conversly, we haven't pushed enough here.
3172 * just zero-pad, and all is well.
3174 while (size < rSize)
3176 emitcode("push", "acc");
3182 _startLazyDPSEvaluation();
3185 emitcode("pop", "acc");
3186 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3188 _endLazyDPSEvaluation();
3191 adjustArithmeticResult(ic);
3194 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3195 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3196 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3199 /*-----------------------------------------------------------------*/
3200 /* genMinusDec :- does subtraction with deccrement if possible */
3201 /*-----------------------------------------------------------------*/
3202 static bool genMinusDec (iCode *ic)
3204 unsigned int icount ;
3205 unsigned int size = getDataSize(IC_RESULT(ic));
3207 /* will try to generate an increment */
3208 /* if the right side is not a literal
3210 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3213 /* if the literal value of the right hand side
3214 is greater than 4 then it is not worth it */
3215 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3218 /* if decrement 16 bits in register */
3219 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3220 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3221 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3228 /* If the next instruction is a goto and the goto target
3229 * is <= 5 instructions previous to this, we can generate
3230 * jumps straight to that target.
3232 if (ic->next && ic->next->op == GOTO
3233 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3234 && labelRange <= 5 )
3236 emitcode(";", "tail decrement optimized (range %d)", labelRange);
3237 tlbl = IC_LABEL(ic->next);
3242 tlbl = newiTempLabel(NULL);
3246 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3247 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3248 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3249 IS_AOP_PREG(IC_RESULT(ic)))
3250 emitcode("cjne","%s,#0xff,%05d$"
3251 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3254 emitcode("mov","a,#0xff");
3255 emitcode("cjne","a,%s,%05d$"
3256 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3259 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3262 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3263 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3264 IS_AOP_PREG(IC_RESULT(ic)))
3265 emitcode("cjne","%s,#0xff,%05d$"
3266 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3269 emitcode("cjne","a,%s,%05d$"
3270 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3273 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3277 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3278 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3279 IS_AOP_PREG(IC_RESULT(ic)))
3280 emitcode("cjne","%s,#0xff,%05d$"
3281 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3284 emitcode("cjne","a,%s,%05d$"
3285 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3288 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3292 emitcode("","%05d$:",tlbl->key+100);
3297 /* if the sizes are greater than 1 then we cannot */
3298 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3299 AOP_SIZE(IC_LEFT(ic)) > 1 )
3302 /* we can if the aops of the left & result match or
3303 if they are in registers and the registers are the
3306 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3307 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3308 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3310 _startLazyDPSEvaluation();
3313 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3315 _endLazyDPSEvaluation();
3323 /*-----------------------------------------------------------------*/
3324 /* addSign - complete with sign */
3325 /*-----------------------------------------------------------------*/
3326 static void addSign(operand *result, int offset, int sign)
3328 int size = (getDataSize(result) - offset);
3331 emitcode("rlc","a");
3332 emitcode("subb","a,acc");
3334 aopPut(AOP(result),"a",offset++);
3337 aopPut(AOP(result),zero,offset++);
3341 /*-----------------------------------------------------------------*/
3342 /* genMinusBits - generates code for subtraction of two bits */
3343 /*-----------------------------------------------------------------*/
3344 static void genMinusBits (iCode *ic)
3346 symbol *lbl = newiTempLabel(NULL);
3348 D(emitcode(";", "genMinusBits "););
3350 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3351 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3352 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3353 emitcode("cpl","c");
3354 emitcode("","%05d$:",(lbl->key+100));
3355 outBitC(IC_RESULT(ic));
3358 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3359 emitcode("subb","a,acc");
3360 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3361 emitcode("inc","a");
3362 emitcode("","%05d$:",(lbl->key+100));
3363 aopPut(AOP(IC_RESULT(ic)),"a",0);
3364 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3368 /*-----------------------------------------------------------------*/
3369 /* genMinus - generates code for subtraction */
3370 /*-----------------------------------------------------------------*/
3371 static void genMinus (iCode *ic)
3373 int size, offset = 0;
3375 unsigned long lit = 0L;
3376 bool pushResult = FALSE;
3378 D(emitcode(";", "genMinus "););
3380 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3381 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3382 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3383 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3389 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3391 /* special cases :- */
3392 /* if both left & right are in bit space */
3393 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3394 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3399 /* if I can do an decrement instead
3400 of subtract then GOOD for ME */
3401 if (genMinusDec (ic) == TRUE)
3406 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3408 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3412 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3417 /* if literal, add a,#-lit, else normal subb */
3418 _startLazyDPSEvaluation();
3420 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3421 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3422 emitcode("subb","a,%s",
3423 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3425 /* first add without previous c */
3427 emitcode("add","a,#0x%02x",
3428 (unsigned int)(lit & 0x0FFL));
3430 emitcode("addc","a,#0x%02x",
3431 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3436 emitcode("push", "acc");
3440 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3444 _endLazyDPSEvaluation();
3448 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3450 size = getDataSize(IC_LEFT(ic));
3451 rSize = getDataSize(IC_RESULT(ic));
3453 /* If the pushed data is bigger than the result,
3454 * simply discard unused bytes. Icky, but works.
3456 * Should we throw a warning here? We're losing data...
3458 while (size > getDataSize(IC_RESULT(ic)))
3460 emitcode(";", "discarding unused result byte.");
3461 emitcode("pop", "acc");
3467 emitcode("clr", "a");
3468 /* Conversly, we haven't pushed enough here.
3469 * just zero-pad, and all is well.
3471 while (size < rSize)
3473 emitcode("push", "acc");
3481 emitcode("pop", "acc");
3482 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3486 adjustArithmeticResult(ic);
3489 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3490 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3491 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3495 /*-----------------------------------------------------------------*/
3496 /* genMultbits :- multiplication of bits */
3497 /*-----------------------------------------------------------------*/
3498 static void genMultbits (operand *left,
3502 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3503 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3508 /*-----------------------------------------------------------------*/
3509 /* genMultOneByte : 8 bit multiplication & division */
3510 /*-----------------------------------------------------------------*/
3511 static void genMultOneByte (operand *left,
3515 sym_link *opetype = operandType(result);
3520 /* (if two literals, the value is computed before) */
3521 /* if one literal, literal on the right */
3522 if (AOP_TYPE(left) == AOP_LIT){
3528 size = AOP_SIZE(result);
3529 /* signed or unsigned */
3530 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3531 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3533 emitcode("mul","ab");
3534 /* if result size = 1, mul signed = mul unsigned */
3535 aopPut(AOP(result),"a",0);
3537 if (SPEC_USIGN(opetype)){
3538 aopPut(AOP(result),"b",1);
3540 /* for filling the MSBs */
3541 emitcode("clr","a");
3544 emitcode("mov","a,b");
3546 /* adjust the MSB if left or right neg */
3548 /* if one literal */
3549 if (AOP_TYPE(right) == AOP_LIT){
3550 /* AND literal negative */
3551 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3552 /* adjust MSB (c==0 after mul) */
3553 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3557 lbl = newiTempLabel(NULL);
3558 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3559 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3560 emitcode("","%05d$:",(lbl->key+100));
3561 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3562 lbl = newiTempLabel(NULL);
3563 emitcode("jc","%05d$",(lbl->key+100));
3564 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3565 emitcode("","%05d$:",(lbl->key+100));
3568 lbl = newiTempLabel(NULL);
3569 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3570 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3571 emitcode("","%05d$:",(lbl->key+100));
3572 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3573 lbl = newiTempLabel(NULL);
3574 emitcode("jc","%05d$",(lbl->key+100));
3575 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3576 emitcode("","%05d$:",(lbl->key+100));
3578 aopPut(AOP(result),"a",1);
3581 emitcode("rlc","a");
3582 emitcode("subb","a,acc");
3589 aopPut(AOP(result),"a",offset++);
3593 /*-----------------------------------------------------------------*/
3594 /* genMult - generates code for multiplication */
3595 /*-----------------------------------------------------------------*/
3596 static void genMult (iCode *ic)
3598 operand *left = IC_LEFT(ic);
3599 operand *right = IC_RIGHT(ic);
3600 operand *result= IC_RESULT(ic);
3602 D(emitcode(";", "genMult "););
3604 /* assign the amsops */
3607 aopOp (left,ic,FALSE, FALSE);
3608 aopOp (right,ic,FALSE, TRUE);
3609 aopOp (result,ic,TRUE, FALSE);
3612 /* special cases first */
3614 if (AOP_TYPE(left) == AOP_CRY &&
3615 AOP_TYPE(right)== AOP_CRY) {
3616 genMultbits(left,right,result);
3620 /* if both are of size == 1 */
3621 if (AOP_SIZE(left) == 1 &&
3622 AOP_SIZE(right) == 1 ) {
3623 genMultOneByte(left,right,result);
3627 /* should have been converted to function call */
3631 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3632 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3633 freeAsmop(result,NULL,ic,TRUE);
3636 /*-----------------------------------------------------------------*/
3637 /* genDivbits :- division of bits */
3638 /*-----------------------------------------------------------------*/
3639 static void genDivbits (operand *left,
3646 /* the result must be bit */
3647 LOAD_AB_FOR_DIV(left, right, l);
3648 emitcode("div","ab");
3649 emitcode("rrc","a");
3650 aopPut(AOP(result),"c",0);
3653 /*-----------------------------------------------------------------*/
3654 /* genDivOneByte : 8 bit division */
3655 /*-----------------------------------------------------------------*/
3656 static void genDivOneByte (operand *left,
3660 sym_link *opetype = operandType(result);
3665 size = AOP_SIZE(result) - 1;
3667 /* signed or unsigned */
3668 if (SPEC_USIGN(opetype)) {
3669 /* unsigned is easy */
3670 LOAD_AB_FOR_DIV(left, right, l);
3671 emitcode("div","ab");
3672 aopPut(AOP(result),"a",0);
3674 aopPut(AOP(result),zero,offset++);
3678 /* signed is a little bit more difficult */
3680 /* save the signs of the operands */
3681 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3683 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3684 emitcode("push","acc"); /* save it on the stack */
3686 /* now sign adjust for both left & right */
3687 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3689 lbl = newiTempLabel(NULL);
3690 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3691 emitcode("cpl","a");
3692 emitcode("inc","a");
3693 emitcode("","%05d$:",(lbl->key+100));
3694 emitcode("mov","b,a");
3696 /* sign adjust left side */
3697 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3700 lbl = newiTempLabel(NULL);
3701 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3702 emitcode("cpl","a");
3703 emitcode("inc","a");
3704 emitcode("","%05d$:",(lbl->key+100));
3706 /* now the division */
3707 emitcode("nop", "; workaround for DS80C390 div bug.");
3708 emitcode("div","ab");
3709 /* we are interested in the lower order
3711 emitcode("mov","b,a");
3712 lbl = newiTempLabel(NULL);
3713 emitcode("pop","acc");
3714 /* if there was an over flow we don't
3715 adjust the sign of the result */
3716 emitcode("jb","ov,%05d$",(lbl->key+100));
3717 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3719 emitcode("clr","a");
3720 emitcode("subb","a,b");
3721 emitcode("mov","b,a");
3722 emitcode("","%05d$:",(lbl->key+100));
3724 /* now we are done */
3725 aopPut(AOP(result),"b",0);
3727 emitcode("mov","c,b.7");
3728 emitcode("subb","a,acc");
3731 aopPut(AOP(result),"a",offset++);
3735 /*-----------------------------------------------------------------*/
3736 /* genDiv - generates code for division */
3737 /*-----------------------------------------------------------------*/
3738 static void genDiv (iCode *ic)
3740 operand *left = IC_LEFT(ic);
3741 operand *right = IC_RIGHT(ic);
3742 operand *result= IC_RESULT(ic);
3744 D(emitcode(";", "genDiv "););
3746 /* assign the amsops */
3749 aopOp (left,ic,FALSE, FALSE);
3750 aopOp (right,ic,FALSE, TRUE);
3751 aopOp (result,ic,TRUE, FALSE);
3754 /* special cases first */
3756 if (AOP_TYPE(left) == AOP_CRY &&
3757 AOP_TYPE(right)== AOP_CRY) {
3758 genDivbits(left,right,result);
3762 /* if both are of size == 1 */
3763 if (AOP_SIZE(left) == 1 &&
3764 AOP_SIZE(right) == 1 ) {
3765 genDivOneByte(left,right,result);
3769 /* should have been converted to function call */
3772 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3773 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3774 freeAsmop(result,NULL,ic,TRUE);
3777 /*-----------------------------------------------------------------*/
3778 /* genModbits :- modulus of bits */
3779 /*-----------------------------------------------------------------*/
3780 static void genModbits (operand *left,
3787 /* the result must be bit */
3788 LOAD_AB_FOR_DIV(left, right, l);
3789 emitcode("div","ab");
3790 emitcode("mov","a,b");
3791 emitcode("rrc","a");
3792 aopPut(AOP(result),"c",0);
3795 /*-----------------------------------------------------------------*/
3796 /* genModOneByte : 8 bit modulus */
3797 /*-----------------------------------------------------------------*/
3798 static void genModOneByte (operand *left,
3802 sym_link *opetype = operandType(result);
3806 /* signed or unsigned */
3807 if (SPEC_USIGN(opetype)) {
3808 /* unsigned is easy */
3809 LOAD_AB_FOR_DIV(left, right, l);
3810 emitcode("div","ab");
3811 aopPut(AOP(result),"b",0);
3815 /* signed is a little bit more difficult */
3817 /* save the signs of the operands */
3818 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3821 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3822 emitcode("push","acc"); /* save it on the stack */
3824 /* now sign adjust for both left & right */
3825 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3828 lbl = newiTempLabel(NULL);
3829 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3830 emitcode("cpl","a");
3831 emitcode("inc","a");
3832 emitcode("","%05d$:",(lbl->key+100));
3833 emitcode("mov","b,a");
3835 /* sign adjust left side */
3836 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3839 lbl = newiTempLabel(NULL);
3840 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3841 emitcode("cpl","a");
3842 emitcode("inc","a");
3843 emitcode("","%05d$:",(lbl->key+100));
3845 /* now the multiplication */
3846 emitcode("nop", "; workaround for DS80C390 div bug.");
3847 emitcode("div","ab");
3848 /* we are interested in the lower order
3850 lbl = newiTempLabel(NULL);
3851 emitcode("pop","acc");
3852 /* if there was an over flow we don't
3853 adjust the sign of the result */
3854 emitcode("jb","ov,%05d$",(lbl->key+100));
3855 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3857 emitcode("clr","a");
3858 emitcode("subb","a,b");
3859 emitcode("mov","b,a");
3860 emitcode("","%05d$:",(lbl->key+100));
3862 /* now we are done */
3863 aopPut(AOP(result),"b",0);
3867 /*-----------------------------------------------------------------*/
3868 /* genMod - generates code for division */
3869 /*-----------------------------------------------------------------*/
3870 static void genMod (iCode *ic)
3872 operand *left = IC_LEFT(ic);
3873 operand *right = IC_RIGHT(ic);
3874 operand *result= IC_RESULT(ic);
3876 D(emitcode(";", "genMod "););
3878 /* assign the amsops */
3881 aopOp (left,ic,FALSE, FALSE);
3882 aopOp (right,ic,FALSE, TRUE);
3883 aopOp (result,ic,TRUE, FALSE);
3886 /* special cases first */
3888 if (AOP_TYPE(left) == AOP_CRY &&
3889 AOP_TYPE(right)== AOP_CRY) {
3890 genModbits(left,right,result);
3894 /* if both are of size == 1 */
3895 if (AOP_SIZE(left) == 1 &&
3896 AOP_SIZE(right) == 1 ) {
3897 genModOneByte(left,right,result);
3901 /* should have been converted to function call */
3905 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3906 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3907 freeAsmop(result,NULL,ic,TRUE);
3910 /*-----------------------------------------------------------------*/
3911 /* genIfxJump :- will create a jump depending on the ifx */
3912 /*-----------------------------------------------------------------*/
3913 static void genIfxJump (iCode *ic, char *jval)
3916 symbol *tlbl = newiTempLabel(NULL);
3919 D(emitcode(";", "genIfxJump "););
3921 /* if true label then we jump if condition
3923 if ( IC_TRUE(ic) ) {
3925 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3926 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3929 /* false label is present */
3930 jlbl = IC_FALSE(ic) ;
3931 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3932 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3934 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3935 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3937 emitcode(inst,"%05d$",tlbl->key+100);
3938 emitcode("ljmp","%05d$",jlbl->key+100);
3939 emitcode("","%05d$:",tlbl->key+100);
3941 /* mark the icode as generated */
3945 /*-----------------------------------------------------------------*/
3946 /* genCmp :- greater or less than comparison */
3947 /*-----------------------------------------------------------------*/
3948 static void genCmp (operand *left,operand *right,
3949 iCode *ic, iCode *ifx, int sign)
3951 int size, offset = 0 ;
3952 unsigned long lit = 0L;
3955 D(emitcode(";", "genCmp"););
3957 result = IC_RESULT(ic);
3959 /* if left & right are bit variables */
3960 if (AOP_TYPE(left) == AOP_CRY &&
3961 AOP_TYPE(right) == AOP_CRY ) {
3962 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3963 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3965 /* subtract right from left if at the
3966 end the carry flag is set then we know that
3967 left is greater than right */
3968 size = max(AOP_SIZE(left),AOP_SIZE(right));
3970 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3971 if((size == 1) && !sign &&
3972 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3973 symbol *lbl = newiTempLabel(NULL);
3974 emitcode("cjne","%s,%s,%05d$",
3975 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3976 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3978 emitcode("","%05d$:",lbl->key+100);
3980 if (AOP_TYPE(right) == AOP_LIT)
3982 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3983 /* optimize if(x < 0) or if(x >= 0) */
3992 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3994 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3995 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3997 aopOp(result,ic,FALSE, FALSE);
3999 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx)
4001 freeAsmop(result,NULL,ic,TRUE);
4002 genIfxJump (ifx,"acc.7");
4007 emitcode("rlc","a");
4009 goto release_freedLR;
4017 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
4018 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4019 emitcode(";", "genCmp #2");
4020 if (sign && (size == 0))
4022 emitcode(";", "genCmp #3");
4023 emitcode("xrl","a,#0x80");
4024 if (AOP_TYPE(right) == AOP_LIT)
4026 unsigned long lit = (unsigned long)
4027 floatFromVal(AOP(right)->aopu.aop_lit);
4028 emitcode(";", "genCmp #3.1");
4029 emitcode("subb","a,#0x%02x",
4030 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
4034 emitcode(";", "genCmp #3.2");
4035 if (AOP_NEEDSACC(right))
4037 emitcode("push", "acc");
4039 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
4040 FALSE,FALSE,FALSE));
4041 emitcode("xrl","b,#0x80");
4042 if (AOP_NEEDSACC(right))
4044 emitcode("pop", "acc");
4046 emitcode("subb","a,b");
4053 emitcode(";", "genCmp #4");
4054 if (AOP_NEEDSACC(right))
4057 emitcode(";", "genCmp #4.1");
4058 emitcode("xch", "a, b");
4059 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
4060 emitcode("xch", "a, b");
4065 emitcode(";", "genCmp #4.2");
4066 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
4069 emitcode("subb","a,%s",s);
4076 /* Don't need the left & right operands any more; do need the result. */
4077 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4078 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4080 aopOp(result,ic,FALSE, FALSE);
4084 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result))
4090 /* if the result is used in the next
4091 ifx conditional branch then generate
4092 code a little differently */
4095 genIfxJump (ifx,"c");
4101 /* leave the result in acc */
4103 freeAsmop(result,NULL,ic,TRUE);
4106 /*-----------------------------------------------------------------*/
4107 /* genCmpGt :- greater than comparison */
4108 /*-----------------------------------------------------------------*/
4109 static void genCmpGt (iCode *ic, iCode *ifx)
4111 operand *left, *right;
4112 sym_link *letype , *retype;
4115 D(emitcode(";", "genCmpGt "););
4118 right= IC_RIGHT(ic);
4120 letype = getSpec(operandType(left));
4121 retype =getSpec(operandType(right));
4122 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4124 /* assign the left & right amsops */
4127 genCmp(right, left, ic, ifx, sign);
4130 /*-----------------------------------------------------------------*/
4131 /* genCmpLt - less than comparisons */
4132 /*-----------------------------------------------------------------*/
4133 static void genCmpLt (iCode *ic, iCode *ifx)
4135 operand *left, *right;
4136 sym_link *letype , *retype;
4139 D(emitcode(";", "genCmpLt "););
4142 right= IC_RIGHT(ic);
4144 letype = getSpec(operandType(left));
4145 retype =getSpec(operandType(right));
4146 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4148 /* assign the left & right amsops */
4151 genCmp(left, right, ic, ifx, sign);
4154 /*-----------------------------------------------------------------*/
4155 /* gencjneshort - compare and jump if not equal */
4156 /*-----------------------------------------------------------------*/
4157 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4159 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4161 unsigned long lit = 0L;
4163 D(emitcode(";", "gencjneshort"););
4165 /* if the left side is a literal or
4166 if the right is in a pointer register and left
4168 if ((AOP_TYPE(left) == AOP_LIT) ||
4169 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4175 if(AOP_TYPE(right) == AOP_LIT)
4176 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4178 if (opIsGptr(left) || opIsGptr(right))
4180 /* We are comparing a generic pointer to something.
4181 * Exclude the generic type byte from the comparison.
4184 D(emitcode(";", "cjneshort: generic ptr special case.");)
4188 /* if the right side is a literal then anything goes */
4189 if (AOP_TYPE(right) == AOP_LIT &&
4190 AOP_TYPE(left) != AOP_DIR ) {
4192 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4194 emitcode("cjne","a,%s,%05d$",
4195 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4201 /* if the right side is in a register or in direct space or
4202 if the left is a pointer register & right is not */
4203 else if (AOP_TYPE(right) == AOP_REG ||
4204 AOP_TYPE(right) == AOP_DIR ||
4205 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4206 (IS_AOP_PREG(left) && !IS_AOP_PREG(right)))
4210 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4211 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4212 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4213 emitcode("jnz","%05d$",lbl->key+100);
4215 emitcode("cjne","a,%s,%05d$",
4216 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4221 /* right is a pointer reg need both a & b */
4223 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4225 emitcode("mov","b,%s",l);
4226 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4227 emitcode("cjne","a,b,%05d$",lbl->key+100);
4233 /*-----------------------------------------------------------------*/
4234 /* gencjne - compare and jump if not equal */
4235 /*-----------------------------------------------------------------*/
4236 static void gencjne(operand *left, operand *right, symbol *lbl)
4238 symbol *tlbl = newiTempLabel(NULL);
4240 D(emitcode(";", "gencjne"););
4242 gencjneshort(left, right, lbl);
4244 emitcode("mov","a,%s",one);
4245 emitcode("sjmp","%05d$",tlbl->key+100);
4246 emitcode("","%05d$:",lbl->key+100);
4247 emitcode("clr","a");
4248 emitcode("","%05d$:",tlbl->key+100);
4251 /*-----------------------------------------------------------------*/
4252 /* genCmpEq - generates code for equal to */
4253 /*-----------------------------------------------------------------*/
4254 static void genCmpEq (iCode *ic, iCode *ifx)
4256 operand *left, *right, *result;
4258 D(emitcode(";", "genCmpEq "););
4263 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4264 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4265 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4268 /* if literal, literal on the right or
4269 if the right is in a pointer register and left
4271 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4272 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4273 operand *t = IC_RIGHT(ic);
4274 IC_RIGHT(ic) = IC_LEFT(ic);
4278 if (ifx && /* !AOP_SIZE(result) */
4279 OP_SYMBOL(result) &&
4280 OP_SYMBOL(result)->regType == REG_CND)
4283 /* if they are both bit variables */
4284 if (AOP_TYPE(left) == AOP_CRY &&
4285 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4286 if(AOP_TYPE(right) == AOP_LIT){
4287 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4289 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4290 emitcode("cpl","c");
4291 } else if(lit == 1L) {
4292 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4294 emitcode("clr","c");
4296 /* AOP_TYPE(right) == AOP_CRY */
4298 symbol *lbl = newiTempLabel(NULL);
4299 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4300 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4301 emitcode("cpl","c");
4302 emitcode("","%05d$:",(lbl->key+100));
4304 /* if true label then we jump if condition
4306 tlbl = newiTempLabel(NULL);
4307 if ( IC_TRUE(ifx) ) {
4308 emitcode("jnc","%05d$",tlbl->key+100);
4309 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4311 emitcode("jc","%05d$",tlbl->key+100);
4312 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4314 emitcode("","%05d$:",tlbl->key+100);
4316 tlbl = newiTempLabel(NULL);
4317 gencjneshort(left, right, tlbl);
4318 if ( IC_TRUE(ifx) ) {
4319 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4320 emitcode("","%05d$:",tlbl->key+100);
4322 symbol *lbl = newiTempLabel(NULL);
4323 emitcode("sjmp","%05d$",lbl->key+100);
4324 emitcode("","%05d$:",tlbl->key+100);
4325 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4326 emitcode("","%05d$:",lbl->key+100);
4329 /* mark the icode as generated */
4332 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4333 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4337 /* if they are both bit variables */
4338 if (AOP_TYPE(left) == AOP_CRY &&
4339 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4340 if(AOP_TYPE(right) == AOP_LIT){
4341 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4343 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4344 emitcode("cpl","c");
4345 } else if(lit == 1L) {
4346 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4348 emitcode("clr","c");
4350 /* AOP_TYPE(right) == AOP_CRY */
4352 symbol *lbl = newiTempLabel(NULL);
4353 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4354 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4355 emitcode("cpl","c");
4356 emitcode("","%05d$:",(lbl->key+100));
4359 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4360 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4362 aopOp(result,ic,TRUE, FALSE);
4365 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4370 genIfxJump (ifx,"c");
4373 /* if the result is used in an arithmetic operation
4374 then put the result in place */
4377 gencjne(left,right,newiTempLabel(NULL));
4379 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4380 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4382 aopOp(result,ic,TRUE, FALSE);
4384 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4385 aopPut(AOP(result),"a",0);
4389 genIfxJump (ifx,"a");
4392 /* if the result is used in an arithmetic operation
4393 then put the result in place */
4394 if (AOP_TYPE(result) != AOP_CRY)
4396 /* leave the result in acc */
4400 freeAsmop(result,NULL,ic,TRUE);
4403 /*-----------------------------------------------------------------*/
4404 /* ifxForOp - returns the icode containing the ifx for operand */
4405 /*-----------------------------------------------------------------*/
4406 static iCode *ifxForOp ( operand *op, iCode *ic )
4408 /* if true symbol then needs to be assigned */
4409 if (IS_TRUE_SYMOP(op))
4412 /* if this has register type condition and
4413 the next instruction is ifx with the same operand
4414 and live to of the operand is upto the ifx only then */
4416 ic->next->op == IFX &&
4417 IC_COND(ic->next)->key == op->key &&
4418 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4423 /*-----------------------------------------------------------------*/
4424 /* genAndOp - for && operation */
4425 /*-----------------------------------------------------------------*/
4426 static void genAndOp (iCode *ic)
4428 operand *left,*right, *result;
4431 D(emitcode(";", "genAndOp "););
4433 /* note here that && operations that are in an
4434 if statement are taken away by backPatchLabels
4435 only those used in arthmetic operations remain */
4439 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4440 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4441 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4444 /* if both are bit variables */
4445 if (AOP_TYPE(left) == AOP_CRY &&
4446 AOP_TYPE(right) == AOP_CRY ) {
4447 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4448 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4451 tlbl = newiTempLabel(NULL);
4453 emitcode("jz","%05d$",tlbl->key+100);
4455 emitcode("","%05d$:",tlbl->key+100);
4459 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4460 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4461 freeAsmop(result,NULL,ic,TRUE);
4465 /*-----------------------------------------------------------------*/
4466 /* genOrOp - for || operation */
4467 /*-----------------------------------------------------------------*/
4468 static void genOrOp (iCode *ic)
4470 operand *left,*right, *result;
4473 D(emitcode(";", "genOrOp "););
4475 /* note here that || operations that are in an
4476 if statement are taken away by backPatchLabels
4477 only those used in arthmetic operations remain */
4481 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4482 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4483 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4486 /* if both are bit variables */
4487 if (AOP_TYPE(left) == AOP_CRY &&
4488 AOP_TYPE(right) == AOP_CRY ) {
4489 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4490 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4493 tlbl = newiTempLabel(NULL);
4495 emitcode("jnz","%05d$",tlbl->key+100);
4497 emitcode("","%05d$:",tlbl->key+100);
4501 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4502 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4503 freeAsmop(result,NULL,ic,TRUE);
4506 /*-----------------------------------------------------------------*/
4507 /* isLiteralBit - test if lit == 2^n */
4508 /*-----------------------------------------------------------------*/
4509 static int isLiteralBit(unsigned long lit)
4511 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4512 0x100L,0x200L,0x400L,0x800L,
4513 0x1000L,0x2000L,0x4000L,0x8000L,
4514 0x10000L,0x20000L,0x40000L,0x80000L,
4515 0x100000L,0x200000L,0x400000L,0x800000L,
4516 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4517 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4520 for(idx = 0; idx < 32; idx++)
4526 /*-----------------------------------------------------------------*/
4527 /* continueIfTrue - */
4528 /*-----------------------------------------------------------------*/
4529 static void continueIfTrue (iCode *ic)
4532 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4536 /*-----------------------------------------------------------------*/
4538 /*-----------------------------------------------------------------*/
4539 static void jumpIfTrue (iCode *ic)
4542 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4546 /*-----------------------------------------------------------------*/
4547 /* jmpTrueOrFalse - */
4548 /*-----------------------------------------------------------------*/
4549 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4551 // ugly but optimized by peephole
4553 symbol *nlbl = newiTempLabel(NULL);
4554 emitcode("sjmp","%05d$",nlbl->key+100);
4555 emitcode("","%05d$:",tlbl->key+100);
4556 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4557 emitcode("","%05d$:",nlbl->key+100);
4560 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4561 emitcode("","%05d$:",tlbl->key+100);
4566 /*-----------------------------------------------------------------*/
4567 /* genAnd - code for and */
4568 /*-----------------------------------------------------------------*/
4569 static void genAnd (iCode *ic, iCode *ifx)
4571 operand *left, *right, *result;
4573 unsigned long lit = 0L;
4577 D(emitcode(";", "genAnd "););
4582 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4583 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4584 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4588 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4590 AOP_TYPE(left), AOP_TYPE(right));
4591 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4593 AOP_SIZE(left), AOP_SIZE(right));
4596 /* if left is a literal & right is not then exchange them */
4597 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4598 AOP_NEEDSACC(left)) {
4599 operand *tmp = right ;
4604 /* if result = right then exchange them */
4605 if(sameRegs(AOP(result),AOP(right))){
4606 operand *tmp = right ;
4611 /* if right is bit then exchange them */
4612 if (AOP_TYPE(right) == AOP_CRY &&
4613 AOP_TYPE(left) != AOP_CRY){
4614 operand *tmp = right ;
4618 if(AOP_TYPE(right) == AOP_LIT)
4619 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4621 size = AOP_SIZE(result);
4624 // result = bit & yy;
4625 if (AOP_TYPE(left) == AOP_CRY){
4626 // c = bit & literal;
4627 if(AOP_TYPE(right) == AOP_LIT){
4629 if(size && sameRegs(AOP(result),AOP(left)))
4632 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4635 if(size && (AOP_TYPE(result) == AOP_CRY)){
4636 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4639 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4643 emitcode("clr","c");
4646 if (AOP_TYPE(right) == AOP_CRY){
4648 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4649 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4652 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4654 emitcode("rrc","a");
4655 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4663 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4664 genIfxJump(ifx, "c");
4668 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4669 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4670 if((AOP_TYPE(right) == AOP_LIT) &&
4671 (AOP_TYPE(result) == AOP_CRY) &&
4672 (AOP_TYPE(left) != AOP_CRY)){
4673 int posbit = isLiteralBit(lit);
4677 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4680 emitcode("mov","c,acc.%d",posbit&0x07);
4684 sprintf(buffer,"acc.%d",posbit&0x07);
4685 genIfxJump(ifx, buffer);
4690 symbol *tlbl = newiTempLabel(NULL);
4691 int sizel = AOP_SIZE(left);
4693 emitcode("setb","c");
4695 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4696 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4698 if((posbit = isLiteralBit(bytelit)) != 0)
4699 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4701 if(bytelit != 0x0FFL)
4702 emitcode("anl","a,%s",
4703 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4704 emitcode("jnz","%05d$",tlbl->key+100);
4709 // bit = left & literal
4711 emitcode("clr","c");
4712 emitcode("","%05d$:",tlbl->key+100);
4714 // if(left & literal)
4717 jmpTrueOrFalse(ifx, tlbl);
4725 /* if left is same as result */
4726 if(sameRegs(AOP(result),AOP(left))){
4727 for(;size--; offset++) {
4728 if(AOP_TYPE(right) == AOP_LIT){
4729 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4733 aopPut(AOP(result),zero,offset);
4735 if (IS_AOP_PREG(result)) {
4736 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4737 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4738 aopPut(AOP(result),"a",offset);
4740 emitcode("anl","%s,%s",
4741 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4742 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4744 if (AOP_TYPE(left) == AOP_ACC)
4745 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4747 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4748 if (IS_AOP_PREG(result)) {
4749 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4750 aopPut(AOP(result),"a",offset);
4753 emitcode("anl","%s,a",
4754 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4759 // left & result in different registers
4760 if(AOP_TYPE(result) == AOP_CRY){
4762 // if(size), result in bit
4763 // if(!size && ifx), conditional oper: if(left & right)
4764 symbol *tlbl = newiTempLabel(NULL);
4765 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4767 emitcode("setb","c");
4769 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4770 emitcode("anl","a,%s",
4771 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4772 emitcode("jnz","%05d$",tlbl->key+100);
4777 emitcode("","%05d$:",tlbl->key+100);
4780 jmpTrueOrFalse(ifx, tlbl);
4783 for(;(size--);offset++)
4786 // result = left & right
4787 if(AOP_TYPE(right) == AOP_LIT)
4789 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4792 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4796 else if (bytelit == 0)
4798 aopPut(AOP(result),zero,offset);
4801 D(emitcode(";", "better literal AND."););
4802 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4803 emitcode("anl", "a, %s", aopGet(AOP(right),offset,
4804 FALSE,FALSE,FALSE));
4809 // faster than result <- left, anl result,right
4810 // and better if result is SFR
4811 if (AOP_TYPE(left) == AOP_ACC)
4813 emitcode("anl","a,%s",aopGet(AOP(right),offset,
4814 FALSE,FALSE,FALSE));
4818 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4819 emitcode("anl","a,%s",
4820 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4823 aopPut(AOP(result),"a",offset);
4829 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4830 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4831 freeAsmop(result,NULL,ic,TRUE);
4834 /*-----------------------------------------------------------------*/
4835 /* genOr - code for or */
4836 /*-----------------------------------------------------------------*/
4837 static void genOr (iCode *ic, iCode *ifx)
4839 operand *left, *right, *result;
4841 unsigned long lit = 0L;
4843 D(emitcode(";", "genOr "););
4848 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4849 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4850 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4854 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4856 AOP_TYPE(left), AOP_TYPE(right));
4857 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4859 AOP_SIZE(left), AOP_SIZE(right));
4862 /* if left is a literal & right is not then exchange them */
4863 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4864 AOP_NEEDSACC(left)) {
4865 operand *tmp = right ;
4870 /* if result = right then exchange them */
4871 if(sameRegs(AOP(result),AOP(right))){
4872 operand *tmp = right ;
4877 /* if right is bit then exchange them */
4878 if (AOP_TYPE(right) == AOP_CRY &&
4879 AOP_TYPE(left) != AOP_CRY){
4880 operand *tmp = right ;
4884 if(AOP_TYPE(right) == AOP_LIT)
4885 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4887 size = AOP_SIZE(result);
4891 if (AOP_TYPE(left) == AOP_CRY){
4892 if(AOP_TYPE(right) == AOP_LIT){
4893 // c = bit & literal;
4895 // lit != 0 => result = 1
4896 if(AOP_TYPE(result) == AOP_CRY){
4898 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4900 continueIfTrue(ifx);
4903 emitcode("setb","c");
4905 // lit == 0 => result = left
4906 if(size && sameRegs(AOP(result),AOP(left)))
4908 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4911 if (AOP_TYPE(right) == AOP_CRY){
4913 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4914 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4918 symbol *tlbl = newiTempLabel(NULL);
4919 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4920 emitcode("setb","c");
4921 emitcode("jb","%s,%05d$",
4922 AOP(left)->aopu.aop_dir,tlbl->key+100);
4924 emitcode("jnz","%05d$",tlbl->key+100);
4925 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4926 jmpTrueOrFalse(ifx, tlbl);
4930 emitcode("","%05d$:",tlbl->key+100);
4939 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4940 genIfxJump(ifx, "c");
4944 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4945 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4946 if((AOP_TYPE(right) == AOP_LIT) &&
4947 (AOP_TYPE(result) == AOP_CRY) &&
4948 (AOP_TYPE(left) != AOP_CRY)){
4952 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4954 continueIfTrue(ifx);
4957 // lit = 0, result = boolean(left)
4959 emitcode("setb","c");
4962 symbol *tlbl = newiTempLabel(NULL);
4963 emitcode("jnz","%05d$",tlbl->key+100);
4965 emitcode("","%05d$:",tlbl->key+100);
4967 genIfxJump (ifx,"a");
4975 /* if left is same as result */
4976 if(sameRegs(AOP(result),AOP(left)))
4978 for(;size--; offset++)
4980 if(AOP_TYPE(right) == AOP_LIT){
4981 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4987 if (IS_AOP_PREG(left))
4989 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4990 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4991 aopPut(AOP(result),"a",offset);
4995 emitcode("orl","%s,%s",
4996 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4997 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5003 if (AOP_TYPE(left) == AOP_ACC)
5005 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5009 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5010 if (IS_AOP_PREG(left))
5012 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5013 aopPut(AOP(result),"a",offset);
5017 emitcode("orl","%s,a",
5018 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5026 // left & result in different registers
5027 if(AOP_TYPE(result) == AOP_CRY)
5030 // if(size), result in bit
5031 // if(!size && ifx), conditional oper: if(left | right)
5032 symbol *tlbl = newiTempLabel(NULL);
5033 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5035 emitcode("setb","c");
5037 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5038 emitcode("orl","a,%s",
5039 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5040 emitcode("jnz","%05d$",tlbl->key+100);
5045 emitcode("","%05d$:",tlbl->key+100);
5048 jmpTrueOrFalse(ifx, tlbl);
5052 for(;(size--);offset++)
5055 // result = left & right
5056 if(AOP_TYPE(right) == AOP_LIT)
5058 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5061 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5065 D(emitcode(";", "better literal OR."););
5066 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5067 emitcode("orl", "a, %s", aopGet(AOP(right),offset,
5068 FALSE,FALSE,FALSE));
5073 // faster than result <- left, anl result,right
5074 // and better if result is SFR
5075 if (AOP_TYPE(left) == AOP_ACC)
5077 emitcode("orl","a,%s",aopGet(AOP(right),offset,
5078 FALSE,FALSE,FALSE));
5082 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5083 emitcode("orl","a,%s",
5084 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5087 aopPut(AOP(result),"a",offset);
5093 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5094 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5095 freeAsmop(result,NULL,ic,TRUE);
5098 /*-----------------------------------------------------------------*/
5099 /* genXor - code for xclusive or */
5100 /*-----------------------------------------------------------------*/
5101 static void genXor (iCode *ic, iCode *ifx)
5103 operand *left, *right, *result;
5105 unsigned long lit = 0L;
5107 D(emitcode(";", "genXor "););
5112 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
5113 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
5114 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
5118 emitcode("","; Type res[%d] = l[%d]&r[%d]",
5120 AOP_TYPE(left), AOP_TYPE(right));
5121 emitcode("","; Size res[%d] = l[%d]&r[%d]",
5123 AOP_SIZE(left), AOP_SIZE(right));
5126 /* if left is a literal & right is not ||
5127 if left needs acc & right does not */
5128 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5129 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5130 operand *tmp = right ;
5135 /* if result = right then exchange them */
5136 if(sameRegs(AOP(result),AOP(right))){
5137 operand *tmp = right ;
5142 /* if right is bit then exchange them */
5143 if (AOP_TYPE(right) == AOP_CRY &&
5144 AOP_TYPE(left) != AOP_CRY){
5145 operand *tmp = right ;
5149 if(AOP_TYPE(right) == AOP_LIT)
5150 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5152 size = AOP_SIZE(result);
5156 if (AOP_TYPE(left) == AOP_CRY){
5157 if(AOP_TYPE(right) == AOP_LIT){
5158 // c = bit & literal;
5160 // lit>>1 != 0 => result = 1
5161 if(AOP_TYPE(result) == AOP_CRY){
5163 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5165 continueIfTrue(ifx);
5168 emitcode("setb","c");
5172 // lit == 0, result = left
5173 if(size && sameRegs(AOP(result),AOP(left)))
5175 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5177 // lit == 1, result = not(left)
5178 if(size && sameRegs(AOP(result),AOP(left))){
5179 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5182 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5183 emitcode("cpl","c");
5190 symbol *tlbl = newiTempLabel(NULL);
5191 if (AOP_TYPE(right) == AOP_CRY){
5193 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5196 int sizer = AOP_SIZE(right);
5198 // if val>>1 != 0, result = 1
5199 emitcode("setb","c");
5201 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5203 // test the msb of the lsb
5204 emitcode("anl","a,#0xfe");
5205 emitcode("jnz","%05d$",tlbl->key+100);
5209 emitcode("rrc","a");
5211 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5212 emitcode("cpl","c");
5213 emitcode("","%05d$:",(tlbl->key+100));
5220 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5221 genIfxJump(ifx, "c");
5225 if(sameRegs(AOP(result),AOP(left))){
5226 /* if left is same as result */
5227 for(;size--; offset++) {
5228 if(AOP_TYPE(right) == AOP_LIT){
5229 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5232 if (IS_AOP_PREG(left)) {
5233 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5234 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5235 aopPut(AOP(result),"a",offset);
5237 emitcode("xrl","%s,%s",
5238 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5239 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5241 if (AOP_TYPE(left) == AOP_ACC)
5242 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5244 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5245 if (IS_AOP_PREG(left)) {
5246 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5247 aopPut(AOP(result),"a",offset);
5249 emitcode("xrl","%s,a",
5250 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5255 // left & result in different registers
5256 if(AOP_TYPE(result) == AOP_CRY){
5258 // if(size), result in bit
5259 // if(!size && ifx), conditional oper: if(left ^ right)
5260 symbol *tlbl = newiTempLabel(NULL);
5261 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5263 emitcode("setb","c");
5265 if((AOP_TYPE(right) == AOP_LIT) &&
5266 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5267 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5269 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5270 emitcode("xrl","a,%s",
5271 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5273 emitcode("jnz","%05d$",tlbl->key+100);
5278 emitcode("","%05d$:",tlbl->key+100);
5281 jmpTrueOrFalse(ifx, tlbl);
5282 } else for(;(size--);offset++)
5285 // result = left & right
5286 if(AOP_TYPE(right) == AOP_LIT)
5288 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5291 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5295 D(emitcode(";", "better literal XOR."););
5296 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5297 emitcode("xrl", "a, %s", aopGet(AOP(right),offset,
5298 FALSE,FALSE,FALSE));
5302 // faster than result <- left, anl result,right
5303 // and better if result is SFR
5304 if (AOP_TYPE(left) == AOP_ACC)
5306 emitcode("xrl","a,%s",aopGet(AOP(right),offset,
5307 FALSE,FALSE,FALSE));
5311 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5312 emitcode("xrl","a,%s",
5313 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5316 aopPut(AOP(result),"a",offset);
5321 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5322 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5323 freeAsmop(result,NULL,ic,TRUE);
5326 /*-----------------------------------------------------------------*/
5327 /* genInline - write the inline code out */
5328 /*-----------------------------------------------------------------*/
5329 static void genInline (iCode *ic)
5331 char buffer[MAX_INLINEASM];
5335 D(emitcode(";", "genInline "););
5337 _G.inLine += (!options.asmpeep);
5338 strcpy(buffer,IC_INLINE(ic));
5340 /* emit each line as a code */
5359 /* emitcode("",buffer); */
5360 _G.inLine -= (!options.asmpeep);
5363 /*-----------------------------------------------------------------*/
5364 /* genRRC - rotate right with carry */
5365 /*-----------------------------------------------------------------*/
5366 static void genRRC (iCode *ic)
5368 operand *left , *result ;
5369 int size, offset = 0;
5372 D(emitcode(";", "genRRC "););
5374 /* rotate right with carry */
5376 result=IC_RESULT(ic);
5377 aopOp (left,ic,FALSE, FALSE);
5378 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5380 /* move it to the result */
5381 size = AOP_SIZE(result);
5385 _startLazyDPSEvaluation();
5387 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5389 emitcode("rrc","a");
5390 if (AOP_SIZE(result) > 1)
5391 aopPut(AOP(result),"a",offset--);
5393 _endLazyDPSEvaluation();
5395 /* now we need to put the carry into the
5396 highest order byte of the result */
5397 if (AOP_SIZE(result) > 1) {
5398 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5401 emitcode("mov","acc.7,c");
5402 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5403 freeAsmop(left,NULL,ic,TRUE);
5404 freeAsmop(result,NULL,ic,TRUE);
5407 /*-----------------------------------------------------------------*/
5408 /* genRLC - generate code for rotate left with carry */
5409 /*-----------------------------------------------------------------*/
5410 static void genRLC (iCode *ic)
5412 operand *left , *result ;
5413 int size, offset = 0;
5416 D(emitcode(";", "genRLC "););
5418 /* rotate right with carry */
5420 result=IC_RESULT(ic);
5421 aopOp (left,ic,FALSE, FALSE);
5422 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5424 /* move it to the result */
5425 size = AOP_SIZE(result);
5428 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5430 emitcode("add","a,acc");
5431 if (AOP_SIZE(result) > 1)
5433 aopPut(AOP(result),"a",offset++);
5436 _startLazyDPSEvaluation();
5438 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5440 emitcode("rlc","a");
5441 if (AOP_SIZE(result) > 1)
5442 aopPut(AOP(result),"a",offset++);
5444 _endLazyDPSEvaluation();
5446 /* now we need to put the carry into the
5447 highest order byte of the result */
5448 if (AOP_SIZE(result) > 1) {
5449 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5452 emitcode("mov","acc.0,c");
5453 aopPut(AOP(result),"a",0);
5454 freeAsmop(left,NULL,ic,TRUE);
5455 freeAsmop(result,NULL,ic,TRUE);
5458 /*-----------------------------------------------------------------*/
5459 /* genGetHbit - generates code get highest order bit */
5460 /*-----------------------------------------------------------------*/
5461 static void genGetHbit (iCode *ic)
5463 operand *left, *result;
5465 result=IC_RESULT(ic);
5466 aopOp (left,ic,FALSE, FALSE);
5467 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5469 D(emitcode(";", "genGetHbit "););
5471 /* get the highest order byte into a */
5472 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5473 if(AOP_TYPE(result) == AOP_CRY){
5474 emitcode("rlc","a");
5479 emitcode("anl","a,#0x01");
5484 freeAsmop(left,NULL,ic,TRUE);
5485 freeAsmop(result,NULL,ic,TRUE);
5488 /*-----------------------------------------------------------------*/
5489 /* AccRol - rotate left accumulator by known count */
5490 /*-----------------------------------------------------------------*/
5491 static void AccRol (int shCount)
5493 shCount &= 0x0007; // shCount : 0..7
5505 emitcode("swap","a");
5509 emitcode("swap","a");
5512 emitcode("swap","a");
5525 /*-----------------------------------------------------------------*/
5526 /* AccLsh - left shift accumulator by known count */
5527 /*-----------------------------------------------------------------*/
5528 static void AccLsh (int shCount)
5532 emitcode("add","a,acc");
5535 emitcode("add","a,acc");
5536 emitcode("add","a,acc");
5538 /* rotate left accumulator */
5540 /* and kill the lower order bits */
5541 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5546 /*-----------------------------------------------------------------*/
5547 /* AccRsh - right shift accumulator by known count */
5548 /*-----------------------------------------------------------------*/
5549 static void AccRsh (int shCount)
5554 emitcode("rrc","a");
5556 /* rotate right accumulator */
5557 AccRol(8 - shCount);
5558 /* and kill the higher order bits */
5559 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5566 /*-----------------------------------------------------------------*/
5567 /* AccSRsh - signed right shift accumulator by known count */
5568 /*-----------------------------------------------------------------*/
5569 static void AccSRsh (int shCount)
5574 emitcode("mov","c,acc.7");
5575 emitcode("rrc","a");
5576 } else if(shCount == 2){
5577 emitcode("mov","c,acc.7");
5578 emitcode("rrc","a");
5579 emitcode("mov","c,acc.7");
5580 emitcode("rrc","a");
5582 tlbl = newiTempLabel(NULL);
5583 /* rotate right accumulator */
5584 AccRol(8 - shCount);
5585 /* and kill the higher order bits */
5586 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5587 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5588 emitcode("orl","a,#0x%02x",
5589 (unsigned char)~SRMask[shCount]);
5590 emitcode("","%05d$:",tlbl->key+100);
5598 /*-----------------------------------------------------------------*/
5599 /* shiftR1Left2Result - shift right one byte from left to result */
5600 /*-----------------------------------------------------------------*/
5601 static void shiftR1Left2Result (operand *left, int offl,
5602 operand *result, int offr,
5603 int shCount, int sign)
5605 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5606 /* shift right accumulator */
5611 aopPut(AOP(result),"a",offr);
5617 /*-----------------------------------------------------------------*/
5618 /* shiftL1Left2Result - shift left one byte from left to result */
5619 /*-----------------------------------------------------------------*/
5620 static void shiftL1Left2Result (operand *left, int offl,
5621 operand *result, int offr, int shCount)
5624 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5626 /* shift left accumulator */
5628 aopPut(AOP(result),"a",offr);
5634 /*-----------------------------------------------------------------*/
5635 /* movLeft2Result - move byte from left to result */
5636 /*-----------------------------------------------------------------*/
5637 static void movLeft2Result (operand *left, int offl,
5638 operand *result, int offr, int sign)
5641 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5642 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5644 if (*l == '@' && (IS_AOP_PREG(result))) {
5645 emitcode("mov","a,%s",l);
5646 aopPut(AOP(result),"a",offr);
5649 aopPut(AOP(result),l,offr);
5651 /* MSB sign in acc.7 ! */
5652 if(getDataSize(left) == offl+1){
5653 emitcode("mov","a,%s",l);
5654 aopPut(AOP(result),"a",offr);
5664 /*-----------------------------------------------------------------*/
5665 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5666 /*-----------------------------------------------------------------*/
5667 static void AccAXRrl1 (char *x)
5669 emitcode("rrc","a");
5670 emitcode("xch","a,%s", x);
5671 emitcode("rrc","a");
5672 emitcode("xch","a,%s", x);
5678 /*-----------------------------------------------------------------*/
5679 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5680 /*-----------------------------------------------------------------*/
5681 static void AccAXLrl1 (char *x)
5683 emitcode("xch","a,%s",x);
5684 emitcode("rlc","a");
5685 emitcode("xch","a,%s",x);
5686 emitcode("rlc","a");
5692 /*-----------------------------------------------------------------*/
5693 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5694 /*-----------------------------------------------------------------*/
5695 static void AccAXLsh1 (char *x)
5697 emitcode("xch","a,%s",x);
5698 emitcode("add","a,acc");
5699 emitcode("xch","a,%s",x);
5700 emitcode("rlc","a");
5706 /*-----------------------------------------------------------------*/
5707 /* AccAXLsh - left shift a:x by known count (0..7) */
5708 /*-----------------------------------------------------------------*/
5709 static void AccAXLsh (char *x, int shCount)
5723 case 5 : // AAAAABBB:CCCCCDDD
5724 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5725 emitcode("anl","a,#0x%02x",
5726 SLMask[shCount]); // BBB00000:CCCCCDDD
5727 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5728 AccRol(shCount); // DDDCCCCC:BBB00000
5729 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5730 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5731 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5732 emitcode("anl","a,#0x%02x",
5733 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5734 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5735 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5737 case 6 : // AAAAAABB:CCCCCCDD
5738 emitcode("anl","a,#0x%02x",
5739 SRMask[shCount]); // 000000BB:CCCCCCDD
5740 emitcode("mov","c,acc.0"); // c = B
5741 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5742 AccAXRrl1(x); // BCCCCCCD:D000000B
5743 AccAXRrl1(x); // BBCCCCCC:DD000000
5745 case 7 : // a:x <<= 7
5746 emitcode("anl","a,#0x%02x",
5747 SRMask[shCount]); // 0000000B:CCCCCCCD
5748 emitcode("mov","c,acc.0"); // c = B
5749 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5750 AccAXRrl1(x); // BCCCCCCC:D0000000
5760 /*-----------------------------------------------------------------*/
5761 /* AccAXRsh - right shift a:x known count (0..7) */
5762 /*-----------------------------------------------------------------*/
5763 static void AccAXRsh (char *x, int shCount)
5770 AccAXRrl1(x); // 0->a:x
5774 AccAXRrl1(x); // 0->a:x
5776 AccAXRrl1(x); // 0->a:x
5780 case 5 : // AAAAABBB:CCCCCDDD = a:x
5781 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5782 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5783 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5784 emitcode("anl","a,#0x%02x",
5785 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5786 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5787 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5788 emitcode("anl","a,#0x%02x",
5789 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5790 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5791 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5792 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5794 case 6 : // AABBBBBB:CCDDDDDD
5795 emitcode("mov","c,acc.7");
5796 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5797 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5798 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5799 emitcode("anl","a,#0x%02x",
5800 SRMask[shCount]); // 000000AA:BBBBBBCC
5802 case 7 : // ABBBBBBB:CDDDDDDD
5803 emitcode("mov","c,acc.7"); // c = A
5804 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5805 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5806 emitcode("anl","a,#0x%02x",
5807 SRMask[shCount]); // 0000000A:BBBBBBBC
5817 /*-----------------------------------------------------------------*/
5818 /* AccAXRshS - right shift signed a:x known count (0..7) */
5819 /*-----------------------------------------------------------------*/
5820 static void AccAXRshS (char *x, int shCount)
5827 emitcode("mov","c,acc.7");
5828 AccAXRrl1(x); // s->a:x
5831 emitcode("mov","c,acc.7");
5832 AccAXRrl1(x); // s->a:x
5833 emitcode("mov","c,acc.7");
5834 AccAXRrl1(x); // s->a:x
5838 case 5 : // AAAAABBB:CCCCCDDD = a:x
5839 tlbl = newiTempLabel(NULL);
5840 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5841 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5842 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5843 emitcode("anl","a,#0x%02x",
5844 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5845 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5846 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5847 emitcode("anl","a,#0x%02x",
5848 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5849 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5850 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5851 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5852 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5853 emitcode("orl","a,#0x%02x",
5854 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5855 emitcode("","%05d$:",tlbl->key+100);
5856 break; // SSSSAAAA:BBBCCCCC
5857 case 6 : // AABBBBBB:CCDDDDDD
5858 tlbl = newiTempLabel(NULL);
5859 emitcode("mov","c,acc.7");
5860 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5861 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5862 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5863 emitcode("anl","a,#0x%02x",
5864 SRMask[shCount]); // 000000AA:BBBBBBCC
5865 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5866 emitcode("orl","a,#0x%02x",
5867 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5868 emitcode("","%05d$:",tlbl->key+100);
5870 case 7 : // ABBBBBBB:CDDDDDDD
5871 tlbl = newiTempLabel(NULL);
5872 emitcode("mov","c,acc.7"); // c = A
5873 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5874 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5875 emitcode("anl","a,#0x%02x",
5876 SRMask[shCount]); // 0000000A:BBBBBBBC
5877 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5878 emitcode("orl","a,#0x%02x",
5879 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5880 emitcode("","%05d$:",tlbl->key+100);
5890 /*-----------------------------------------------------------------*/
5891 /* shiftL2Left2Result - shift left two bytes from left to result */
5892 /*-----------------------------------------------------------------*/
5893 static void shiftL2Left2Result (operand *left, int offl,
5894 operand *result, int offr, int shCount)
5896 if(sameRegs(AOP(result), AOP(left)) &&
5897 ((offl + MSB16) == offr)){
5898 /* don't crash result[offr] */
5899 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5900 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5902 movLeft2Result(left,offl, result, offr, 0);
5903 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5905 /* ax << shCount (x = lsb(result))*/
5906 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5907 aopPut(AOP(result),"a",offr+MSB16);
5913 /*-----------------------------------------------------------------*/
5914 /* shiftR2Left2Result - shift right two bytes from left to result */
5915 /*-----------------------------------------------------------------*/
5916 static void shiftR2Left2Result (operand *left, int offl,
5917 operand *result, int offr,
5918 int shCount, int sign)
5920 if(sameRegs(AOP(result), AOP(left)) &&
5921 ((offl + MSB16) == offr)){
5922 /* don't crash result[offr] */
5923 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5924 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5926 movLeft2Result(left,offl, result, offr, 0);
5927 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5929 /* a:x >> shCount (x = lsb(result))*/
5931 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5933 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5934 if(getDataSize(result) > 1)
5935 aopPut(AOP(result),"a",offr+MSB16);
5941 /*-----------------------------------------------------------------*/
5942 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5943 /*-----------------------------------------------------------------*/
5944 static void shiftLLeftOrResult (operand *left, int offl,
5945 operand *result, int offr, int shCount)
5947 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5948 /* shift left accumulator */
5950 /* or with result */
5951 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5952 /* back to result */
5953 aopPut(AOP(result),"a",offr);
5959 /*-----------------------------------------------------------------*/
5960 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5961 /*-----------------------------------------------------------------*/
5962 static void shiftRLeftOrResult (operand *left, int offl,
5963 operand *result, int offr, int shCount)
5965 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5966 /* shift right accumulator */
5968 /* or with result */
5969 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5970 /* back to result */
5971 aopPut(AOP(result),"a",offr);
5977 /*-----------------------------------------------------------------*/
5978 /* genlshOne - left shift a one byte quantity by known count */
5979 /*-----------------------------------------------------------------*/
5980 static void genlshOne (operand *result, operand *left, int shCount)
5982 D(emitcode(";", "genlshOne "););
5983 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5989 /*-----------------------------------------------------------------*/
5990 /* genlshTwo - left shift two bytes by known amount != 0 */
5991 /*-----------------------------------------------------------------*/
5992 static void genlshTwo (operand *result,operand *left, int shCount)
5996 D(emitcode(";", "genlshTwo "););
5998 size = getDataSize(result);
6000 /* if shCount >= 8 */
6006 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6008 movLeft2Result(left, LSB, result, MSB16, 0);
6010 aopPut(AOP(result),zero,LSB);
6013 /* 1 <= shCount <= 7 */
6016 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6018 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6025 /*-----------------------------------------------------------------*/
6026 /* shiftLLong - shift left one long from left to result */
6027 /* offl = LSB or MSB16 */
6028 /*-----------------------------------------------------------------*/
6029 static void shiftLLong (operand *left, operand *result, int offr )
6032 int size = AOP_SIZE(result);
6034 if(size >= LSB+offr){
6035 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
6037 emitcode("add","a,acc");
6038 if (sameRegs(AOP(left),AOP(result)) &&
6039 size >= MSB16+offr && offr != LSB )
6040 emitcode("xch","a,%s",
6041 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
6043 aopPut(AOP(result),"a",LSB+offr);
6046 if(size >= MSB16+offr){
6047 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6048 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
6051 emitcode("rlc","a");
6052 if (sameRegs(AOP(left),AOP(result)) &&
6053 size >= MSB24+offr && offr != LSB)
6054 emitcode("xch","a,%s",
6055 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
6057 aopPut(AOP(result),"a",MSB16+offr);
6060 if(size >= MSB24+offr){
6061 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6062 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
6065 emitcode("rlc","a");
6066 if (sameRegs(AOP(left),AOP(result)) &&
6067 size >= MSB32+offr && offr != LSB )
6068 emitcode("xch","a,%s",
6069 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
6071 aopPut(AOP(result),"a",MSB24+offr);
6074 if(size > MSB32+offr){
6075 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6076 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
6079 emitcode("rlc","a");
6080 aopPut(AOP(result),"a",MSB32+offr);
6083 aopPut(AOP(result),zero,LSB);
6089 /*-----------------------------------------------------------------*/
6090 /* genlshFour - shift four byte by a known amount != 0 */
6091 /*-----------------------------------------------------------------*/
6092 static void genlshFour (operand *result, operand *left, int shCount)
6096 D(emitcode(";", "genlshFour "););
6098 size = AOP_SIZE(result);
6100 /* if shifting more that 3 bytes */
6101 if (shCount >= 24 ) {
6104 /* lowest order of left goes to the highest
6105 order of the destination */
6106 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6108 movLeft2Result(left, LSB, result, MSB32, 0);
6109 aopPut(AOP(result),zero,LSB);
6110 aopPut(AOP(result),zero,MSB16);
6111 aopPut(AOP(result),zero,MSB32);
6115 /* more than two bytes */
6116 else if ( shCount >= 16 ) {
6117 /* lower order two bytes goes to higher order two bytes */
6119 /* if some more remaining */
6121 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6123 movLeft2Result(left, MSB16, result, MSB32, 0);
6124 movLeft2Result(left, LSB, result, MSB24, 0);
6126 aopPut(AOP(result),zero,MSB16);
6127 aopPut(AOP(result),zero,LSB);
6131 /* if more than 1 byte */
6132 else if ( shCount >= 8 ) {
6133 /* lower order three bytes goes to higher order three bytes */
6137 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6139 movLeft2Result(left, LSB, result, MSB16, 0);
6141 else{ /* size = 4 */
6143 movLeft2Result(left, MSB24, result, MSB32, 0);
6144 movLeft2Result(left, MSB16, result, MSB24, 0);
6145 movLeft2Result(left, LSB, result, MSB16, 0);
6146 aopPut(AOP(result),zero,LSB);
6148 else if(shCount == 1)
6149 shiftLLong(left, result, MSB16);
6151 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6152 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6153 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6154 aopPut(AOP(result),zero,LSB);
6159 /* 1 <= shCount <= 7 */
6160 else if(shCount <= 2){
6161 shiftLLong(left, result, LSB);
6163 shiftLLong(result, result, LSB);
6165 /* 3 <= shCount <= 7, optimize */
6167 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6168 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6169 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6176 /*-----------------------------------------------------------------*/
6177 /* genLeftShiftLiteral - left shifting by known count */
6178 /*-----------------------------------------------------------------*/
6179 static void genLeftShiftLiteral (operand *left,
6184 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6187 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
6189 freeAsmop(right,NULL,ic,TRUE);
6191 aopOp(left,ic,FALSE, FALSE);
6192 aopOp(result,ic,FALSE, TRUE);
6194 size = getSize(operandType(result));
6197 emitcode("; shift left ","result %d, left %d",size,
6201 /* I suppose that the left size >= result size */
6204 movLeft2Result(left, size, result, size, 0);
6208 else if(shCount >= (size * 8))
6210 aopPut(AOP(result),zero,size);
6214 genlshOne (result,left,shCount);
6218 case 3: /* bug: this is for generic pointers, I bet. */
6219 genlshTwo (result,left,shCount);
6223 genlshFour (result,left,shCount);
6227 freeAsmop(left,NULL,ic,TRUE);
6228 freeAsmop(result,NULL,ic,TRUE);
6232 /*-----------------------------------------------------------------*/
6233 /* genLeftShift - generates code for left shifting */
6234 /*-----------------------------------------------------------------*/
6235 static void genLeftShift (iCode *ic)
6237 operand *left,*right, *result;
6240 symbol *tlbl , *tlbl1;
6242 D(emitcode(";", "genLeftShift "););
6244 right = IC_RIGHT(ic);
6246 result = IC_RESULT(ic);
6248 aopOp(right,ic,FALSE, FALSE);
6251 /* if the shift count is known then do it
6252 as efficiently as possible */
6253 if (AOP_TYPE(right) == AOP_LIT) {
6254 genLeftShiftLiteral (left,right,result,ic);
6259 /* shift count is unknown then we have to form
6260 a loop get the loop count in B : Note: we take
6261 only the lower order byte since shifting
6262 more that 32 bits make no sense anyway, ( the
6263 largest size of an object can be only 32 bits ) */
6265 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6266 emitcode("inc","b");
6267 freeAsmop (right,NULL,ic,TRUE);
6268 aopOp(left,ic,FALSE, FALSE);
6269 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6271 /* now move the left to the result if they are not the
6273 if (!sameRegs(AOP(left),AOP(result)) &&
6274 AOP_SIZE(result) > 1) {
6276 size = AOP_SIZE(result);
6278 _startLazyDPSEvaluation();
6280 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6281 if (*l == '@' && (IS_AOP_PREG(result))) {
6283 emitcode("mov","a,%s",l);
6284 aopPut(AOP(result),"a",offset);
6286 aopPut(AOP(result),l,offset);
6289 _endLazyDPSEvaluation();
6292 tlbl = newiTempLabel(NULL);
6293 size = AOP_SIZE(result);
6295 tlbl1 = newiTempLabel(NULL);
6297 /* if it is only one byte then */
6299 symbol *tlbl1 = newiTempLabel(NULL);
6301 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6303 emitcode("sjmp","%05d$",tlbl1->key+100);
6304 emitcode("","%05d$:",tlbl->key+100);
6305 emitcode("add","a,acc");
6306 emitcode("","%05d$:",tlbl1->key+100);
6307 emitcode("djnz","b,%05d$",tlbl->key+100);
6308 aopPut(AOP(result),"a",0);
6312 reAdjustPreg(AOP(result));
6314 emitcode("sjmp","%05d$",tlbl1->key+100);
6315 emitcode("","%05d$:",tlbl->key+100);
6316 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6318 emitcode("add","a,acc");
6319 aopPut(AOP(result),"a",offset++);
6320 _startLazyDPSEvaluation();
6322 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6324 emitcode("rlc","a");
6325 aopPut(AOP(result),"a",offset++);
6327 _endLazyDPSEvaluation();
6328 reAdjustPreg(AOP(result));
6330 emitcode("","%05d$:",tlbl1->key+100);
6331 emitcode("djnz","b,%05d$",tlbl->key+100);
6333 freeAsmop(left,NULL,ic,TRUE);
6334 freeAsmop(result,NULL,ic,TRUE);
6339 /*-----------------------------------------------------------------*/
6340 /* genrshOne - right shift a one byte quantity by known count */
6341 /*-----------------------------------------------------------------*/
6342 static void genrshOne (operand *result, operand *left,
6343 int shCount, int sign)
6345 D(emitcode(";", "genrshOne"););
6346 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6352 /*-----------------------------------------------------------------*/
6353 /* genrshTwo - right shift two bytes by known amount != 0 */
6354 /*-----------------------------------------------------------------*/
6355 static void genrshTwo (operand *result,operand *left,
6356 int shCount, int sign)
6358 D(emitcode(";", "genrshTwo"););
6360 /* if shCount >= 8 */
6364 shiftR1Left2Result(left, MSB16, result, LSB,
6367 movLeft2Result(left, MSB16, result, LSB, sign);
6368 addSign(result, MSB16, sign);
6371 /* 1 <= shCount <= 7 */
6373 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6379 /*-----------------------------------------------------------------*/
6380 /* shiftRLong - shift right one long from left to result */
6381 /* offl = LSB or MSB16 */
6382 /*-----------------------------------------------------------------*/
6383 static void shiftRLong (operand *left, int offl,
6384 operand *result, int sign)
6387 emitcode("clr","c");
6388 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6390 emitcode("mov","c,acc.7");
6391 emitcode("rrc","a");
6392 aopPut(AOP(result),"a",MSB32-offl);
6394 /* add sign of "a" */
6395 addSign(result, MSB32, sign);
6397 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6398 emitcode("rrc","a");
6399 aopPut(AOP(result),"a",MSB24-offl);
6401 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6402 emitcode("rrc","a");
6403 aopPut(AOP(result),"a",MSB16-offl);
6406 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6407 emitcode("rrc","a");
6408 aopPut(AOP(result),"a",LSB);
6415 /*-----------------------------------------------------------------*/
6416 /* genrshFour - shift four byte by a known amount != 0 */
6417 /*-----------------------------------------------------------------*/
6418 static void genrshFour (operand *result, operand *left,
6419 int shCount, int sign)
6421 D(emitcode(";", "genrshFour"););
6423 /* if shifting more that 3 bytes */
6424 if(shCount >= 24 ) {
6427 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6429 movLeft2Result(left, MSB32, result, LSB, sign);
6430 addSign(result, MSB16, sign);
6432 else if(shCount >= 16){
6435 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6437 movLeft2Result(left, MSB24, result, LSB, 0);
6438 movLeft2Result(left, MSB32, result, MSB16, sign);
6440 addSign(result, MSB24, sign);
6442 else if(shCount >= 8){
6445 shiftRLong(left, MSB16, result, sign);
6446 else if(shCount == 0){
6447 movLeft2Result(left, MSB16, result, LSB, 0);
6448 movLeft2Result(left, MSB24, result, MSB16, 0);
6449 movLeft2Result(left, MSB32, result, MSB24, sign);
6450 addSign(result, MSB32, sign);
6453 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6454 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6455 /* the last shift is signed */
6456 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6457 addSign(result, MSB32, sign);
6460 else{ /* 1 <= shCount <= 7 */
6462 shiftRLong(left, LSB, result, sign);
6464 shiftRLong(result, LSB, result, sign);
6467 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6468 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6469 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6477 /*-----------------------------------------------------------------*/
6478 /* genRightShiftLiteral - right shifting by known count */
6479 /*-----------------------------------------------------------------*/
6480 static void genRightShiftLiteral (operand *left,
6486 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6489 D(emitcode(";", "genRightShiftLiteral"););
6491 freeAsmop(right,NULL,ic,TRUE);
6493 aopOp(left,ic,FALSE, FALSE);
6494 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6497 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6501 size = getDataSize(left);
6502 /* test the LEFT size !!! */
6504 /* I suppose that the left size >= result size */
6506 size = getDataSize(result);
6508 movLeft2Result(left, size, result, size, 0);
6511 else if(shCount >= (size * 8)){
6513 /* get sign in acc.7 */
6514 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6515 addSign(result, LSB, sign);
6519 genrshOne (result,left,shCount,sign);
6523 genrshTwo (result,left,shCount,sign);
6527 genrshFour (result,left,shCount,sign);
6533 freeAsmop(left,NULL,ic,TRUE);
6534 freeAsmop(result,NULL,ic,TRUE);
6539 /*-----------------------------------------------------------------*/
6540 /* genSignedRightShift - right shift of signed number */
6541 /*-----------------------------------------------------------------*/
6542 static void genSignedRightShift (iCode *ic)
6544 operand *right, *left, *result;
6547 symbol *tlbl, *tlbl1 ;
6549 D(emitcode(";", "genSignedRightShift "););
6551 /* we do it the hard way put the shift count in b
6552 and loop thru preserving the sign */
6554 right = IC_RIGHT(ic);
6556 result = IC_RESULT(ic);
6558 aopOp(right,ic,FALSE, FALSE);
6561 if ( AOP_TYPE(right) == AOP_LIT) {
6562 genRightShiftLiteral (left,right,result,ic,1);
6566 /* shift count is unknown then we have to form
6567 a loop get the loop count in B : Note: we take
6568 only the lower order byte since shifting
6569 more that 32 bits make no sense anyway, ( the
6570 largest size of an object can be only 32 bits ) */
6572 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6573 emitcode("inc","b");
6574 freeAsmop (right,NULL,ic,TRUE);
6575 aopOp(left,ic,FALSE, FALSE);
6576 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6578 /* now move the left to the result if they are not the
6580 if (!sameRegs(AOP(left),AOP(result)) &&
6581 AOP_SIZE(result) > 1) {
6583 size = AOP_SIZE(result);
6585 _startLazyDPSEvaluation();
6587 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6588 if (*l == '@' && IS_AOP_PREG(result)) {
6590 emitcode("mov","a,%s",l);
6591 aopPut(AOP(result),"a",offset);
6593 aopPut(AOP(result),l,offset);
6596 _endLazyDPSEvaluation();
6599 /* mov the highest order bit to OVR */
6600 tlbl = newiTempLabel(NULL);
6601 tlbl1= newiTempLabel(NULL);
6603 size = AOP_SIZE(result);
6605 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6606 emitcode("rlc","a");
6607 emitcode("mov","ov,c");
6608 /* if it is only one byte then */
6610 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6612 emitcode("sjmp","%05d$",tlbl1->key+100);
6613 emitcode("","%05d$:",tlbl->key+100);
6614 emitcode("mov","c,ov");
6615 emitcode("rrc","a");
6616 emitcode("","%05d$:",tlbl1->key+100);
6617 emitcode("djnz","b,%05d$",tlbl->key+100);
6618 aopPut(AOP(result),"a",0);
6622 reAdjustPreg(AOP(result));
6623 emitcode("sjmp","%05d$",tlbl1->key+100);
6624 emitcode("","%05d$:",tlbl->key+100);
6625 emitcode("mov","c,ov");
6626 _startLazyDPSEvaluation();
6628 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6630 emitcode("rrc","a");
6631 aopPut(AOP(result),"a",offset--);
6633 _endLazyDPSEvaluation();
6634 reAdjustPreg(AOP(result));
6635 emitcode("","%05d$:",tlbl1->key+100);
6636 emitcode("djnz","b,%05d$",tlbl->key+100);
6639 freeAsmop(left,NULL,ic,TRUE);
6640 freeAsmop(result,NULL,ic,TRUE);
6643 /*-----------------------------------------------------------------*/
6644 /* genRightShift - generate code for right shifting */
6645 /*-----------------------------------------------------------------*/
6646 static void genRightShift (iCode *ic)
6648 operand *right, *left, *result;
6652 symbol *tlbl, *tlbl1 ;
6654 D(emitcode(";", "genRightShift "););
6656 /* if signed then we do it the hard way preserve the
6657 sign bit moving it inwards */
6658 retype = getSpec(operandType(IC_RESULT(ic)));
6660 if (!SPEC_USIGN(retype)) {
6661 genSignedRightShift (ic);
6665 /* signed & unsigned types are treated the same : i.e. the
6666 signed is NOT propagated inwards : quoting from the
6667 ANSI - standard : "for E1 >> E2, is equivalent to division
6668 by 2**E2 if unsigned or if it has a non-negative value,
6669 otherwise the result is implementation defined ", MY definition
6670 is that the sign does not get propagated */
6672 right = IC_RIGHT(ic);
6674 result = IC_RESULT(ic);
6676 aopOp(right,ic,FALSE, FALSE);
6679 /* if the shift count is known then do it
6680 as efficiently as possible */
6681 if (AOP_TYPE(right) == AOP_LIT) {
6682 genRightShiftLiteral (left,right,result,ic, 0);
6687 /* shift count is unknown then we have to form
6688 a loop get the loop count in B : Note: we take
6689 only the lower order byte since shifting
6690 more that 32 bits make no sense anyway, ( the
6691 largest size of an object can be only 32 bits ) */
6693 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6694 emitcode("inc","b");
6695 freeAsmop (right,NULL,ic,TRUE);
6696 aopOp(left,ic,FALSE, FALSE);
6697 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6699 /* now move the left to the result if they are not the
6701 if (!sameRegs(AOP(left),AOP(result)) &&
6702 AOP_SIZE(result) > 1) {
6704 size = AOP_SIZE(result);
6706 _startLazyDPSEvaluation();
6708 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6709 if (*l == '@' && IS_AOP_PREG(result)) {
6711 emitcode("mov","a,%s",l);
6712 aopPut(AOP(result),"a",offset);
6714 aopPut(AOP(result),l,offset);
6717 _endLazyDPSEvaluation();
6720 tlbl = newiTempLabel(NULL);
6721 tlbl1= newiTempLabel(NULL);
6722 size = AOP_SIZE(result);
6725 /* if it is only one byte then */
6727 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6729 emitcode("sjmp","%05d$",tlbl1->key+100);
6730 emitcode("","%05d$:",tlbl->key+100);
6732 emitcode("rrc","a");
6733 emitcode("","%05d$:",tlbl1->key+100);
6734 emitcode("djnz","b,%05d$",tlbl->key+100);
6735 aopPut(AOP(result),"a",0);
6739 reAdjustPreg(AOP(result));
6740 emitcode("sjmp","%05d$",tlbl1->key+100);
6741 emitcode("","%05d$:",tlbl->key+100);
6743 _startLazyDPSEvaluation();
6745 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6747 emitcode("rrc","a");
6748 aopPut(AOP(result),"a",offset--);
6750 _endLazyDPSEvaluation();
6751 reAdjustPreg(AOP(result));
6753 emitcode("","%05d$:",tlbl1->key+100);
6754 emitcode("djnz","b,%05d$",tlbl->key+100);
6757 freeAsmop(left,NULL,ic,TRUE);
6758 freeAsmop(result,NULL,ic,TRUE);
6761 /*-----------------------------------------------------------------*/
6762 /* genUnpackBits - generates code for unpacking bits */
6763 /*-----------------------------------------------------------------*/
6764 static void genUnpackBits (operand *result, char *rname, int ptype)
6771 D(emitcode(";", "genUnpackBits "););
6773 etype = getSpec(operandType(result));
6775 /* read the first byte */
6780 emitcode("mov","a,@%s",rname);
6784 emitcode("movx","a,@%s",rname);
6788 emitcode("movx","a,@dptr");
6792 emitcode("clr","a");
6793 emitcode("movc","a","@a+dptr");
6797 emitcode("lcall","__gptrget");
6801 /* if we have bitdisplacement then it fits */
6802 /* into this byte completely or if length is */
6803 /* less than a byte */
6804 if ((shCnt = SPEC_BSTR(etype)) ||
6805 (SPEC_BLEN(etype) <= 8)) {
6807 /* shift right acc */
6810 emitcode("anl","a,#0x%02x",
6811 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6812 aopPut(AOP(result),"a",offset);
6816 /* bit field did not fit in a byte */
6817 rlen = SPEC_BLEN(etype) - 8;
6818 aopPut(AOP(result),"a",offset++);
6825 emitcode("inc","%s",rname);
6826 emitcode("mov","a,@%s",rname);
6830 emitcode("inc","%s",rname);
6831 emitcode("movx","a,@%s",rname);
6835 emitcode("inc","dptr");
6836 emitcode("movx","a,@dptr");
6840 emitcode("clr","a");
6841 emitcode("inc","dptr");
6842 emitcode("movc","a","@a+dptr");
6846 emitcode("inc","dptr");
6847 emitcode("lcall","__gptrget");
6852 /* if we are done */
6856 aopPut(AOP(result),"a",offset++);
6861 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6862 aopPut(AOP(result),"a",offset);
6869 /*-----------------------------------------------------------------*/
6870 /* genDataPointerGet - generates code when ptr offset is known */
6871 /*-----------------------------------------------------------------*/
6872 static void genDataPointerGet (operand *left,
6878 int size , offset = 0;
6879 aopOp(result,ic,TRUE, FALSE);
6881 /* get the string representation of the name */
6882 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6883 size = AOP_SIZE(result);
6884 _startLazyDPSEvaluation();
6887 sprintf(buffer,"(%s + %d)",l+1,offset);
6889 sprintf(buffer,"%s",l+1);
6890 aopPut(AOP(result),buffer,offset++);
6892 _endLazyDPSEvaluation();
6894 freeAsmop(left,NULL,ic,TRUE);
6895 freeAsmop(result,NULL,ic,TRUE);
6898 /*-----------------------------------------------------------------*/
6899 /* genNearPointerGet - emitcode for near pointer fetch */
6900 /*-----------------------------------------------------------------*/
6901 static void genNearPointerGet (operand *left,
6908 sym_link *rtype, *retype, *letype;
6909 sym_link *ltype = operandType(left);
6912 rtype = operandType(result);
6913 retype= getSpec(rtype);
6914 letype= getSpec(ltype);
6916 aopOp(left,ic,FALSE, FALSE);
6918 /* if left is rematerialisable and
6919 result is not bit variable type and
6920 the left is pointer to data space i.e
6921 lower 128 bytes of space */
6922 if (AOP_TYPE(left) == AOP_IMMD &&
6923 !IS_BITVAR(retype) &&
6924 !IS_BITVAR(letype) &&
6925 DCL_TYPE(ltype) == POINTER) {
6926 genDataPointerGet (left,result,ic);
6930 /* if the value is already in a pointer register
6931 then don't need anything more */
6932 if (!AOP_INPREG(AOP(left))) {
6933 /* otherwise get a free pointer register */
6935 preg = getFreePtr(ic,&aop,FALSE);
6936 emitcode("mov","%s,%s",
6938 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6939 rname = preg->name ;
6941 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6943 freeAsmop(left,NULL,ic,TRUE);
6944 aopOp (result,ic,FALSE, FALSE);
6946 /* if bitfield then unpack the bits */
6947 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6948 genUnpackBits (result,rname,POINTER);
6950 /* we have can just get the values */
6951 int size = AOP_SIZE(result);
6955 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6957 emitcode("mov","a,@%s",rname);
6958 aopPut(AOP(result),"a",offset);
6960 sprintf(buffer,"@%s",rname);
6961 aopPut(AOP(result),buffer,offset);
6965 emitcode("inc","%s",rname);
6969 /* now some housekeeping stuff */
6971 /* we had to allocate for this iCode */
6972 freeAsmop(NULL,aop,ic,TRUE);
6974 /* we did not allocate which means left
6975 already in a pointer register, then
6976 if size > 0 && this could be used again
6977 we have to point it back to where it
6979 if (AOP_SIZE(result) > 1 &&
6980 !OP_SYMBOL(left)->remat &&
6981 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6983 int size = AOP_SIZE(result) - 1;
6985 emitcode("dec","%s",rname);
6990 freeAsmop(result,NULL,ic,TRUE);
6994 /*-----------------------------------------------------------------*/
6995 /* genPagedPointerGet - emitcode for paged pointer fetch */
6996 /*-----------------------------------------------------------------*/
6997 static void genPagedPointerGet (operand *left,
7004 sym_link *rtype, *retype, *letype;
7006 rtype = operandType(result);
7007 retype= getSpec(rtype);
7008 letype= getSpec(operandType(left));
7009 aopOp(left,ic,FALSE, FALSE);
7011 /* if the value is already in a pointer register
7012 then don't need anything more */
7013 if (!AOP_INPREG(AOP(left))) {
7014 /* otherwise get a free pointer register */
7016 preg = getFreePtr(ic,&aop,FALSE);
7017 emitcode("mov","%s,%s",
7019 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
7020 rname = preg->name ;
7022 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
7024 freeAsmop(left,NULL,ic,TRUE);
7025 aopOp (result,ic,FALSE, FALSE);
7027 /* if bitfield then unpack the bits */
7028 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7029 genUnpackBits (result,rname,PPOINTER);
7031 /* we have can just get the values */
7032 int size = AOP_SIZE(result);
7037 emitcode("movx","a,@%s",rname);
7038 aopPut(AOP(result),"a",offset);
7043 emitcode("inc","%s",rname);
7047 /* now some housekeeping stuff */
7049 /* we had to allocate for this iCode */
7050 freeAsmop(NULL,aop,ic,TRUE);
7052 /* we did not allocate which means left
7053 already in a pointer register, then
7054 if size > 0 && this could be used again
7055 we have to point it back to where it
7057 if (AOP_SIZE(result) > 1 &&
7058 !OP_SYMBOL(left)->remat &&
7059 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7061 int size = AOP_SIZE(result) - 1;
7063 emitcode("dec","%s",rname);
7068 freeAsmop(result,NULL,ic,TRUE);
7073 /*-----------------------------------------------------------------*/
7074 /* genFarPointerGet - gget value from far space */
7075 /*-----------------------------------------------------------------*/
7076 static void genFarPointerGet (operand *left,
7077 operand *result, iCode *ic)
7080 sym_link *retype = getSpec(operandType(result));
7081 sym_link *letype = getSpec(operandType(left));
7082 D(emitcode(";", "genFarPointerGet"););
7084 aopOp(left,ic,FALSE, FALSE);
7086 /* if the operand is already in dptr
7087 then we do nothing else we move the value to dptr */
7088 if (AOP_TYPE(left) != AOP_STR) {
7089 /* if this is remateriazable */
7090 if (AOP_TYPE(left) == AOP_IMMD)
7092 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7096 /* we need to get it byte by byte */
7097 _startLazyDPSEvaluation();
7098 if (AOP_TYPE(left) != AOP_DPTR)
7100 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7101 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7102 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7106 /* We need to generate a load to DPTR indirect through DPTR. */
7107 D(emitcode(";", "genFarPointerGet -- indirection special case."););
7108 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7109 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7110 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7111 emitcode("pop", "dph");
7112 emitcode("pop", "dpl");
7114 _endLazyDPSEvaluation();
7117 /* so dptr know contains the address */
7118 freeAsmop(left,NULL,ic,TRUE);
7119 aopOp(result,ic,FALSE, TRUE);
7121 /* if bit then unpack */
7122 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7123 genUnpackBits(result,"dptr",FPOINTER);
7125 size = AOP_SIZE(result);
7128 _startLazyDPSEvaluation();
7134 emitcode("movx","a,@dptr");
7136 emitcode("inc","dptr");
7138 aopPut(AOP(result),"a",offset++);
7140 _endLazyDPSEvaluation();
7143 freeAsmop(result,NULL,ic,TRUE);
7146 /*-----------------------------------------------------------------*/
7147 /* emitcodePointerGet - gget value from code space */
7148 /*-----------------------------------------------------------------*/
7149 static void emitcodePointerGet (operand *left,
7150 operand *result, iCode *ic)
7153 sym_link *retype = getSpec(operandType(result));
7155 aopOp(left,ic,FALSE, FALSE);
7157 /* if the operand is already in dptr
7158 then we do nothing else we move the value to dptr */
7159 if (AOP_TYPE(left) != AOP_STR) {
7160 /* if this is remateriazable */
7161 if (AOP_TYPE(left) == AOP_IMMD)
7163 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7166 { /* we need to get it byte by byte */
7167 _startLazyDPSEvaluation();
7168 if (AOP_TYPE(left) != AOP_DPTR)
7170 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7171 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7172 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7176 /* We need to generate a load to DPTR indirect through DPTR. */
7177 D(emitcode(";", "gencodePointerGet -- indirection special case."););
7178 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7179 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7180 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7181 emitcode("pop", "dph");
7182 emitcode("pop", "dpl");
7184 _endLazyDPSEvaluation();
7187 /* so dptr know contains the address */
7188 freeAsmop(left,NULL,ic,TRUE);
7189 aopOp(result,ic,FALSE, TRUE);
7191 /* if bit then unpack */
7192 if (IS_BITVAR(retype))
7193 genUnpackBits(result,"dptr",CPOINTER);
7195 size = AOP_SIZE(result);
7198 _startLazyDPSEvaluation();
7204 emitcode("clr","a");
7205 emitcode("movc","a,@a+dptr");
7207 emitcode("inc","dptr");
7208 aopPut(AOP(result),"a",offset++);
7210 _endLazyDPSEvaluation();
7213 freeAsmop(result,NULL,ic,TRUE);
7216 /*-----------------------------------------------------------------*/
7217 /* genGenPointerGet - gget value from generic pointer space */
7218 /*-----------------------------------------------------------------*/
7219 static void genGenPointerGet (operand *left,
7220 operand *result, iCode *ic)
7223 sym_link *retype = getSpec(operandType(result));
7224 sym_link *letype = getSpec(operandType(left));
7226 aopOp(left,ic,FALSE, TRUE);
7228 /* if the operand is already in dptr
7229 then we do nothing else we move the value to dptr */
7230 if (AOP_TYPE(left) != AOP_STR) {
7231 /* if this is remateriazable */
7232 if (AOP_TYPE(left) == AOP_IMMD) {
7233 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7234 emitcode("mov","b,#%d",pointerCode(retype));
7236 else { /* we need to get it byte by byte */
7237 _startLazyDPSEvaluation();
7238 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7239 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7240 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7241 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7242 _endLazyDPSEvaluation();
7245 /* so dptr know contains the address */
7246 freeAsmop(left,NULL,ic,TRUE);
7247 aopOp(result,ic,FALSE, TRUE);
7249 /* if bit then unpack */
7250 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7251 genUnpackBits(result,"dptr",GPOINTER);
7253 size = AOP_SIZE(result);
7257 emitcode("lcall","__gptrget");
7258 aopPut(AOP(result),"a",offset++);
7260 emitcode("inc","dptr");
7264 freeAsmop(result,NULL,ic,TRUE);
7267 /*-----------------------------------------------------------------*/
7268 /* genPointerGet - generate code for pointer get */
7269 /*-----------------------------------------------------------------*/
7270 static void genPointerGet (iCode *ic)
7272 operand *left, *result ;
7273 sym_link *type, *etype;
7276 D(emitcode(";", "genPointerGet "););
7279 result = IC_RESULT(ic) ;
7281 /* depending on the type of pointer we need to
7282 move it to the correct pointer register */
7283 type = operandType(left);
7284 etype = getSpec(type);
7285 /* if left is of type of pointer then it is simple */
7286 if (IS_PTR(type) && !IS_FUNC(type->next))
7287 p_type = DCL_TYPE(type);
7289 /* we have to go by the storage class */
7290 p_type = PTR_TYPE(SPEC_OCLS(etype));
7293 /* now that we have the pointer type we assign
7294 the pointer values */
7299 genNearPointerGet (left,result,ic);
7303 genPagedPointerGet(left,result,ic);
7307 genFarPointerGet (left,result,ic);
7311 emitcodePointerGet (left,result,ic);
7315 genGenPointerGet (left,result,ic);
7321 /*-----------------------------------------------------------------*/
7322 /* genPackBits - generates code for packed bit storage */
7323 /*-----------------------------------------------------------------*/
7324 static void genPackBits (sym_link *etype ,
7326 char *rname, int p_type)
7334 blen = SPEC_BLEN(etype);
7335 bstr = SPEC_BSTR(etype);
7337 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7340 /* if the bit lenth is less than or */
7341 /* it exactly fits a byte then */
7342 if (SPEC_BLEN(etype) <= 8 ) {
7343 shCount = SPEC_BSTR(etype) ;
7345 /* shift left acc */
7348 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7353 emitcode ("mov","b,a");
7354 emitcode("mov","a,@%s",rname);
7358 emitcode ("mov","b,a");
7359 emitcode("movx","a,@dptr");
7363 emitcode ("push","b");
7364 emitcode ("push","acc");
7365 emitcode ("lcall","__gptrget");
7366 emitcode ("pop","b");
7370 emitcode ("anl","a,#0x%02x",(unsigned char)
7371 ((unsigned char)(0xFF << (blen+bstr)) |
7372 (unsigned char)(0xFF >> (8-bstr)) ) );
7373 emitcode ("orl","a,b");
7374 if (p_type == GPOINTER)
7375 emitcode("pop","b");
7381 emitcode("mov","@%s,a",rname);
7385 emitcode("movx","@dptr,a");
7389 emitcode("lcall","__gptrput");
7394 if ( SPEC_BLEN(etype) <= 8 )
7397 emitcode("inc","%s",rname);
7398 rLen = SPEC_BLEN(etype) ;
7400 /* now generate for lengths greater than one byte */
7403 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7413 emitcode("mov","@%s,a",rname);
7415 emitcode("mov","@%s,%s",rname,l);
7420 emitcode("movx","@dptr,a");
7425 emitcode("lcall","__gptrput");
7428 emitcode ("inc","%s",rname);
7433 /* last last was not complete */
7435 /* save the byte & read byte */
7438 emitcode ("mov","b,a");
7439 emitcode("mov","a,@%s",rname);
7443 emitcode ("mov","b,a");
7444 emitcode("movx","a,@dptr");
7448 emitcode ("push","b");
7449 emitcode ("push","acc");
7450 emitcode ("lcall","__gptrget");
7451 emitcode ("pop","b");
7455 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << rLen) );
7456 emitcode ("orl","a,b");
7459 if (p_type == GPOINTER)
7460 emitcode("pop","b");
7465 emitcode("mov","@%s,a",rname);
7469 emitcode("movx","@dptr,a");
7473 emitcode("lcall","__gptrput");
7477 /*-----------------------------------------------------------------*/
7478 /* genDataPointerSet - remat pointer to data space */
7479 /*-----------------------------------------------------------------*/
7480 static void genDataPointerSet(operand *right,
7484 int size, offset = 0 ;
7485 char *l, buffer[256];
7487 aopOp(right,ic,FALSE, FALSE);
7489 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7490 size = AOP_SIZE(right);
7493 sprintf(buffer,"(%s + %d)",l+1,offset);
7495 sprintf(buffer,"%s",l+1);
7496 emitcode("mov","%s,%s",buffer,
7497 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7500 freeAsmop(right,NULL,ic,TRUE);
7501 freeAsmop(result,NULL,ic,TRUE);
7504 /*-----------------------------------------------------------------*/
7505 /* genNearPointerSet - emitcode for near pointer put */
7506 /*-----------------------------------------------------------------*/
7507 static void genNearPointerSet (operand *right,
7514 sym_link *retype, *letype;
7515 sym_link *ptype = operandType(result);
7517 retype= getSpec(operandType(right));
7518 letype= getSpec(ptype);
7520 aopOp(result,ic,FALSE, FALSE);
7522 /* if the result is rematerializable &
7523 in data space & not a bit variable */
7524 if (AOP_TYPE(result) == AOP_IMMD &&
7525 DCL_TYPE(ptype) == POINTER &&
7526 !IS_BITVAR(retype) &&
7527 !IS_BITVAR(letype)) {
7528 genDataPointerSet (right,result,ic);
7532 /* if the value is already in a pointer register
7533 then don't need anything more */
7534 if (!AOP_INPREG(AOP(result))) {
7535 /* otherwise get a free pointer register */
7537 preg = getFreePtr(ic,&aop,FALSE);
7538 emitcode("mov","%s,%s",
7540 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7541 rname = preg->name ;
7543 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7545 freeAsmop(result,NULL,ic,TRUE);
7546 aopOp (right,ic,FALSE, FALSE);
7548 /* if bitfield then unpack the bits */
7549 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7550 genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
7552 /* we have can just get the values */
7553 int size = AOP_SIZE(right);
7557 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7560 emitcode("mov","@%s,a",rname);
7562 emitcode("mov","@%s,%s",rname,l);
7564 emitcode("inc","%s",rname);
7569 /* now some housekeeping stuff */
7571 /* we had to allocate for this iCode */
7572 freeAsmop(NULL,aop,ic,TRUE);
7574 /* we did not allocate which means left
7575 already in a pointer register, then
7576 if size > 0 && this could be used again
7577 we have to point it back to where it
7579 if (AOP_SIZE(right) > 1 &&
7580 !OP_SYMBOL(result)->remat &&
7581 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7583 int size = AOP_SIZE(right) - 1;
7585 emitcode("dec","%s",rname);
7590 freeAsmop(right,NULL,ic,TRUE);
7595 /*-----------------------------------------------------------------*/
7596 /* genPagedPointerSet - emitcode for Paged pointer put */
7597 /*-----------------------------------------------------------------*/
7598 static void genPagedPointerSet (operand *right,
7605 sym_link *retype, *letype;
7607 retype= getSpec(operandType(right));
7608 letype= getSpec(operandType(result));
7610 aopOp(result,ic,FALSE, FALSE);
7612 /* if the value is already in a pointer register
7613 then don't need anything more */
7614 if (!AOP_INPREG(AOP(result))) {
7615 /* otherwise get a free pointer register */
7617 preg = getFreePtr(ic,&aop,FALSE);
7618 emitcode("mov","%s,%s",
7620 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7621 rname = preg->name ;
7623 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7625 freeAsmop(result,NULL,ic,TRUE);
7626 aopOp (right,ic,FALSE, FALSE);
7628 /* if bitfield then unpack the bits */
7629 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7630 genPackBits ((IS_BITVAR(retype) ? retype : letype) ,right,rname,PPOINTER);
7632 /* we have can just get the values */
7633 int size = AOP_SIZE(right);
7637 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7640 emitcode("movx","@%s,a",rname);
7643 emitcode("inc","%s",rname);
7649 /* now some housekeeping stuff */
7651 /* we had to allocate for this iCode */
7652 freeAsmop(NULL,aop,ic,TRUE);
7654 /* we did not allocate which means left
7655 already in a pointer register, then
7656 if size > 0 && this could be used again
7657 we have to point it back to where it
7659 if (AOP_SIZE(right) > 1 &&
7660 !OP_SYMBOL(result)->remat &&
7661 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7663 int size = AOP_SIZE(right) - 1;
7665 emitcode("dec","%s",rname);
7670 freeAsmop(right,NULL,ic,TRUE);
7675 /*-----------------------------------------------------------------*/
7676 /* genFarPointerSet - set value from far space */
7677 /*-----------------------------------------------------------------*/
7678 static void genFarPointerSet (operand *right,
7679 operand *result, iCode *ic)
7682 sym_link *retype = getSpec(operandType(right));
7683 sym_link *letype = getSpec(operandType(result));
7685 aopOp(result,ic,FALSE, FALSE);
7687 /* if the operand is already in dptr
7688 then we do nothing else we move the value to dptr */
7689 if (AOP_TYPE(result) != AOP_STR) {
7690 /* if this is remateriazable */
7691 if (AOP_TYPE(result) == AOP_IMMD)
7692 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7695 /* we need to get it byte by byte */
7696 _startLazyDPSEvaluation();
7697 if (AOP_TYPE(result) != AOP_DPTR)
7699 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7700 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7701 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7705 /* We need to generate a load to DPTR indirect through DPTR. */
7706 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7707 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7708 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7709 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7710 emitcode("pop", "dph");
7711 emitcode("pop", "dpl");
7713 _endLazyDPSEvaluation();
7716 /* so dptr know contains the address */
7717 freeAsmop(result,NULL,ic,TRUE);
7718 aopOp(right,ic,FALSE, TRUE);
7720 /* if bit then unpack */
7721 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7722 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",FPOINTER);
7724 size = AOP_SIZE(right);
7727 _startLazyDPSEvaluation();
7729 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7735 emitcode("movx","@dptr,a");
7737 emitcode("inc","dptr");
7739 _endLazyDPSEvaluation();
7742 freeAsmop(right,NULL,ic,TRUE);
7745 /*-----------------------------------------------------------------*/
7746 /* genGenPointerSet - set value from generic pointer space */
7747 /*-----------------------------------------------------------------*/
7748 static void genGenPointerSet (operand *right,
7749 operand *result, iCode *ic)
7752 sym_link *retype = getSpec(operandType(right));
7753 sym_link *letype = getSpec(operandType(result));
7755 aopOp(result,ic,FALSE, TRUE);
7757 /* if the operand is already in dptr
7758 then we do nothing else we move the value to dptr */
7759 if (AOP_TYPE(result) != AOP_STR) {
7760 _startLazyDPSEvaluation();
7761 /* if this is remateriazable */
7762 if (AOP_TYPE(result) == AOP_IMMD) {
7763 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7764 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7766 else { /* we need to get it byte by byte */
7767 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7768 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7769 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7770 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7772 _endLazyDPSEvaluation();
7774 /* so dptr know contains the address */
7775 freeAsmop(result,NULL,ic,TRUE);
7776 aopOp(right,ic,FALSE, TRUE);
7778 /* if bit then unpack */
7779 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7780 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",GPOINTER);
7782 size = AOP_SIZE(right);
7785 _startLazyDPSEvaluation();
7787 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7793 emitcode("lcall","__gptrput");
7795 emitcode("inc","dptr");
7797 _endLazyDPSEvaluation();
7800 freeAsmop(right,NULL,ic,TRUE);
7803 /*-----------------------------------------------------------------*/
7804 /* genPointerSet - stores the value into a pointer location */
7805 /*-----------------------------------------------------------------*/
7806 static void genPointerSet (iCode *ic)
7808 operand *right, *result ;
7809 sym_link *type, *etype;
7812 D(emitcode(";", "genPointerSet "););
7814 right = IC_RIGHT(ic);
7815 result = IC_RESULT(ic) ;
7817 /* depending on the type of pointer we need to
7818 move it to the correct pointer register */
7819 type = operandType(result);
7820 etype = getSpec(type);
7821 /* if left is of type of pointer then it is simple */
7822 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7823 p_type = DCL_TYPE(type);
7826 /* we have to go by the storage class */
7827 p_type = PTR_TYPE(SPEC_OCLS(etype));
7830 /* now that we have the pointer type we assign
7831 the pointer values */
7836 genNearPointerSet (right,result,ic);
7840 genPagedPointerSet (right,result,ic);
7844 genFarPointerSet (right,result,ic);
7848 genGenPointerSet (right,result,ic);
7854 /*-----------------------------------------------------------------*/
7855 /* genIfx - generate code for Ifx statement */
7856 /*-----------------------------------------------------------------*/
7857 static void genIfx (iCode *ic, iCode *popIc)
7859 operand *cond = IC_COND(ic);
7862 D(emitcode(";", "genIfx "););
7864 aopOp(cond,ic,FALSE, FALSE);
7866 /* get the value into acc */
7867 if (AOP_TYPE(cond) != AOP_CRY)
7871 /* the result is now in the accumulator */
7872 freeAsmop(cond,NULL,ic,TRUE);
7874 /* if there was something to be popped then do it */
7878 /* if the condition is a bit variable */
7879 if (isbit && IS_ITEMP(cond) &&
7881 genIfxJump(ic,SPIL_LOC(cond)->rname);
7883 if (isbit && !IS_ITEMP(cond))
7884 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7891 /*-----------------------------------------------------------------*/
7892 /* genAddrOf - generates code for address of */
7893 /*-----------------------------------------------------------------*/
7894 static void genAddrOf (iCode *ic)
7896 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7899 D(emitcode(";", "genAddrOf "););
7901 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7903 /* if the operand is on the stack then we
7904 need to get the stack offset of this
7907 /* if it has an offset then we need to compute
7910 emitcode("mov","a,_bp");
7911 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7912 aopPut(AOP(IC_RESULT(ic)),"a",0);
7914 /* we can just move _bp */
7915 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7917 /* fill the result with zero */
7918 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7921 if (options.stack10bit && size < (FPTRSIZE - 1))
7924 "*** warning: pointer to stack var truncated.\n");
7931 if (options.stack10bit && offset == 2)
7933 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7937 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7944 /* object not on stack then we need the name */
7945 size = AOP_SIZE(IC_RESULT(ic));
7949 char s[SDCC_NAME_MAX];
7951 sprintf(s,"#(%s >> %d)",
7955 sprintf(s,"#%s",sym->rname);
7956 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7960 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7964 /*-----------------------------------------------------------------*/
7965 /* genFarFarAssign - assignment when both are in far space */
7966 /*-----------------------------------------------------------------*/
7967 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7969 int size = AOP_SIZE(right);
7976 /* This is a net loss for size == 1, but a big gain
7979 D(emitcode(";", "genFarFarAssign (improved)"););
7981 aopOp(result,ic,TRUE, TRUE);
7983 _startLazyDPSEvaluation();
7987 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7991 _endLazyDPSEvaluation();
7992 freeAsmop(result,NULL,ic,FALSE);
7993 freeAsmop(right,NULL,ic,FALSE);
7998 D(emitcode(";", "genFarFarAssign "););
8000 /* first push the right side on to the stack */
8001 _startLazyDPSEvaluation();
8003 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
8005 emitcode ("push","acc");
8008 freeAsmop(right,NULL,ic,FALSE);
8009 /* now assign DPTR to result */
8010 aopOp(result,ic,FALSE, FALSE);
8011 size = AOP_SIZE(result);
8013 emitcode ("pop","acc");
8014 aopPut(AOP(result),"a",--offset);
8016 freeAsmop(result,NULL,ic,FALSE);
8017 _endLazyDPSEvaluation();
8021 /*-----------------------------------------------------------------*/
8022 /* genAssign - generate code for assignment */
8023 /*-----------------------------------------------------------------*/
8024 static void genAssign (iCode *ic)
8026 operand *result, *right;
8028 unsigned long lit = 0L;
8030 D(emitcode(";", "genAssign "););
8032 result = IC_RESULT(ic);
8033 right = IC_RIGHT(ic) ;
8035 /* if they are the same */
8036 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8039 aopOp(right,ic,FALSE, FALSE);
8041 emitcode(";", "genAssign: resultIsFar = %s",
8042 isOperandInFarSpace(result) ?
8045 /* special case both in far space */
8046 if ((AOP_TYPE(right) == AOP_DPTR ||
8047 AOP_TYPE(right) == AOP_DPTR2) &&
8048 /* IS_TRUE_SYMOP(result) && */
8049 isOperandInFarSpace(result)) {
8051 genFarFarAssign (result,right,ic);
8055 aopOp(result,ic,TRUE, FALSE);
8057 /* if they are the same registers */
8058 if (sameRegs(AOP(right),AOP(result)))
8061 /* if the result is a bit */
8062 if (AOP_TYPE(result) == AOP_CRY) {
8064 /* if the right size is a literal then
8065 we know what the value is */
8066 if (AOP_TYPE(right) == AOP_LIT) {
8067 if (((int) operandLitValue(right)))
8068 aopPut(AOP(result),one,0);
8070 aopPut(AOP(result),zero,0);
8074 /* the right is also a bit variable */
8075 if (AOP_TYPE(right) == AOP_CRY) {
8076 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8077 aopPut(AOP(result),"c",0);
8083 aopPut(AOP(result),"a",0);
8087 /* bit variables done */
8089 size = AOP_SIZE(result);
8091 if(AOP_TYPE(right) == AOP_LIT)
8092 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8095 (AOP_TYPE(result) != AOP_REG) &&
8096 (AOP_TYPE(right) == AOP_LIT) &&
8097 !IS_FLOAT(operandType(right))
8098 #ifndef LAZY_DPS_OPT
8104 D(emitcode(";", "Kevin's better literal load code"););
8105 _startLazyDPSEvaluation();
8106 while (size && ((unsigned int)(lit >> (offset*8)) != 0))
8109 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
8114 /* And now fill the rest with zeros. */
8117 emitcode("clr","a");
8121 aopPut(AOP(result), "a", offset++);
8123 _endLazyDPSEvaluation();
8125 emitcode("clr","a");
8127 _startLazyDPSEvaluation();
8130 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
8131 aopPut(AOP(result),"a",size);
8134 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
8137 _endLazyDPSEvaluation();
8142 _startLazyDPSEvaluation();
8146 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8150 _endLazyDPSEvaluation();
8154 freeAsmop (right,NULL,ic,FALSE);
8155 freeAsmop (result,NULL,ic,TRUE);
8158 /*-----------------------------------------------------------------*/
8159 /* genJumpTab - generates code for jump table */
8160 /*-----------------------------------------------------------------*/
8161 static void genJumpTab (iCode *ic)
8166 D(emitcode(";", "genJumpTab "););
8168 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
8169 /* get the condition into accumulator */
8170 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
8172 /* multiply by four! */
8173 emitcode("add","a,acc");
8174 emitcode("add","a,acc");
8175 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8177 jtab = newiTempLabel(NULL);
8178 emitcode("mov","dptr,#%05d$",jtab->key+100);
8179 emitcode("jmp","@a+dptr");
8180 emitcode("","%05d$:",jtab->key+100);
8181 /* now generate the jump labels */
8182 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8183 jtab = setNextItem(IC_JTLABELS(ic)))
8184 emitcode("ljmp","%05d$",jtab->key+100);
8188 /*-----------------------------------------------------------------*/
8189 /* genCast - gen code for casting */
8190 /*-----------------------------------------------------------------*/
8191 static void genCast (iCode *ic)
8193 operand *result = IC_RESULT(ic);
8194 sym_link *ctype = operandType(IC_LEFT(ic));
8195 sym_link *rtype = operandType(IC_RIGHT(ic));
8196 operand *right = IC_RIGHT(ic);
8199 D(emitcode(";", "genCast "););
8201 /* if they are equivalent then do nothing */
8202 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8205 aopOp(right,ic,FALSE, FALSE) ;
8206 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
8208 /* if the result is a bit */
8209 if (AOP_TYPE(result) == AOP_CRY) {
8210 /* if the right size is a literal then
8211 we know what the value is */
8212 if (AOP_TYPE(right) == AOP_LIT) {
8213 if (((int) operandLitValue(right)))
8214 aopPut(AOP(result),one,0);
8216 aopPut(AOP(result),zero,0);
8221 /* the right is also a bit variable */
8222 if (AOP_TYPE(right) == AOP_CRY) {
8223 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8224 aopPut(AOP(result),"c",0);
8230 aopPut(AOP(result),"a",0);
8234 /* if they are the same size : or less */
8235 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8237 /* if they are in the same place */
8238 if (sameRegs(AOP(right),AOP(result)))
8241 /* if they in different places then copy */
8242 size = AOP_SIZE(result);
8244 _startLazyDPSEvaluation();
8247 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8251 _endLazyDPSEvaluation();
8256 /* if the result is of type pointer */
8257 if (IS_PTR(ctype)) {
8260 sym_link *type = operandType(right);
8262 /* pointer to generic pointer */
8263 if (IS_GENPTR(ctype)) {
8268 p_type = DCL_TYPE(type);
8272 #if OLD_CAST_BEHAVIOR
8273 /* KV: we are converting a non-pointer type to
8274 * a generic pointer. This (ifdef'd out) code
8275 * says that the resulting generic pointer
8276 * should have the same class as the storage
8277 * location of the non-pointer variable.
8279 * For example, converting an int (which happens
8280 * to be stored in DATA space) to a pointer results
8281 * in a DATA generic pointer; if the original int
8282 * in XDATA space, so will be the resulting pointer.
8284 * I don't like that behavior, and thus this change:
8285 * all such conversions will be forced to XDATA and
8286 * throw a warning. If you want some non-XDATA
8287 * type, or you want to suppress the warning, you
8288 * must go through an intermediate cast, like so:
8290 * char _generic *gp = (char _xdata *)(intVar);
8292 sym_link *etype = getSpec(type);
8294 /* we have to go by the storage class */
8295 if (SPEC_OCLS(etype) != generic)
8297 p_type = PTR_TYPE(SPEC_OCLS(etype));
8302 /* Converting unknown class (i.e. register variable)
8303 * to generic pointer. This is not good, but
8304 * we'll make a guess (and throw a warning).
8307 werror(W_INT_TO_GEN_PTR_CAST);
8311 /* the first two bytes are known */
8312 size = GPTRSIZE - 1;
8314 _startLazyDPSEvaluation();
8317 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8321 _endLazyDPSEvaluation();
8323 /* the last byte depending on type */
8340 /* this should never happen */
8341 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8342 "got unknown pointer type");
8345 aopPut(AOP(result),l, GPTRSIZE - 1);
8349 /* just copy the pointers */
8350 size = AOP_SIZE(result);
8352 _startLazyDPSEvaluation();
8355 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8359 _endLazyDPSEvaluation();
8363 /* so we now know that the size of destination is greater
8364 than the size of the source */
8365 /* we move to result for the size of source */
8366 size = AOP_SIZE(right);
8368 _startLazyDPSEvaluation();
8371 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8375 _endLazyDPSEvaluation();
8377 /* now depending on the sign of the source && destination */
8378 size = AOP_SIZE(result) - AOP_SIZE(right);
8379 /* if unsigned or not an integral type */
8380 /* also, if the source is a bit, we don't need to sign extend, because
8381 * it can't possibly have set the sign bit.
8383 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype) || AOP_TYPE(right) == AOP_CRY)
8387 aopPut(AOP(result),zero,offset++);
8392 /* we need to extend the sign :{ */
8393 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8396 emitcode("rlc","a");
8397 emitcode("subb","a,acc");
8399 aopPut(AOP(result),"a",offset++);
8402 /* we are done hurray !!!! */
8405 freeAsmop(right,NULL,ic,TRUE);
8406 freeAsmop(result,NULL,ic,TRUE);
8410 /*-----------------------------------------------------------------*/
8411 /* genDjnz - generate decrement & jump if not zero instrucion */
8412 /*-----------------------------------------------------------------*/
8413 static int genDjnz (iCode *ic, iCode *ifx)
8419 /* if the if condition has a false label
8420 then we cannot save */
8424 /* if the minus is not of the form
8426 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8427 !IS_OP_LITERAL(IC_RIGHT(ic)))
8430 if (operandLitValue(IC_RIGHT(ic)) != 1)
8433 /* if the size of this greater than one then no
8435 if (getSize(operandType(IC_RESULT(ic))) > 1)
8438 /* otherwise we can save BIG */
8439 lbl = newiTempLabel(NULL);
8440 lbl1= newiTempLabel(NULL);
8442 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8444 if (IS_AOP_PREG(IC_RESULT(ic))) {
8445 emitcode("dec","%s",
8446 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8447 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8448 emitcode("jnz","%05d$",lbl->key+100);
8450 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8453 emitcode ("sjmp","%05d$",lbl1->key+100);
8454 emitcode ("","%05d$:",lbl->key+100);
8455 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8456 emitcode ("","%05d$:",lbl1->key+100);
8458 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8463 /*-----------------------------------------------------------------*/
8464 /* genReceive - generate code for a receive iCode */
8465 /*-----------------------------------------------------------------*/
8466 static void genReceive (iCode *ic)
8469 D(emitcode(";", "genReceive "););
8471 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8472 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8473 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8474 int size = getSize(operandType(IC_RESULT(ic)));
8475 int offset = fReturnSize_390 - size;
8477 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8478 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8481 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8482 size = AOP_SIZE(IC_RESULT(ic));
8485 emitcode ("pop","acc");
8486 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8491 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8493 assignResultValue(IC_RESULT(ic));
8496 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8499 /*-----------------------------------------------------------------*/
8500 /* gen390Code - generate code for Dallas 390 based controllers */
8501 /*-----------------------------------------------------------------*/
8502 void gen390Code (iCode *lic)
8507 lineHead = lineCurr = NULL;
8511 /* print the allocation information */
8513 printAllocInfo( currFunc, codeOutFile);
8515 /* if debug information required */
8516 if (options.debug && currFunc) {
8517 //jwk if (currFunc) {
8518 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8520 if (IS_STATIC(currFunc->etype))
8521 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8523 emitcode("","G$%s$0$0 ==.",currFunc->name);
8526 /* stack pointer name */
8527 if (options.useXstack)
8533 for (ic = lic ; ic ; ic = ic->next ) {
8535 if ( cln != ic->lineno ) {
8536 if ( options.debug ) {
8538 emitcode("","C$%s$%d$%d$%d ==.",
8539 ic->filename,ic->lineno,
8540 ic->level,ic->block);
8543 emitcode(";","%s %d",ic->filename,ic->lineno);
8546 /* if the result is marked as
8547 spilt and rematerializable or code for
8548 this has already been generated then
8550 if (resultRemat(ic) || ic->generated )
8553 /* depending on the operation */
8572 /* IPOP happens only when trying to restore a
8573 spilt live range, if there is an ifx statement
8574 following this pop then the if statement might
8575 be using some of the registers being popped which
8576 would destory the contents of the register so
8577 we need to check for this condition and handle it */
8579 ic->next->op == IFX &&
8580 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8581 genIfx (ic->next,ic);
8599 genEndFunction (ic);
8619 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8636 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8640 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8647 /* note these two are xlated by algebraic equivalence
8648 during parsing SDCC.y */
8649 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8650 "got '>=' or '<=' shouldn't have come here");
8654 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8666 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8670 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8674 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8701 case GET_VALUE_AT_ADDRESS:
8706 if (POINTER_SET(ic))
8733 addSet(&_G.sendSet,ic);
8738 /* piCode(ic,stdout); */
8744 /* now we are ready to call the
8745 peep hole optimizer */
8746 if (!options.nopeep)
8747 peepHole (&lineHead);
8749 /* now do the actual printing */
8750 printLine (lineHead,codeOutFile);