1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
54 char *aopLiteral (value *val, int offset);
60 /* this is the down and dirty file with all kinds of
61 kludgy & hacky stuff. This is what it is all about
62 CODE GENERATION for a specific MCU . some of the
63 routines may be reusable, will have to see */
65 static char *zero = "#0x00";
66 static char *one = "#0x01";
71 unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
72 static char *fReturn[] = {"dpl","dph","dpx", "b","a" };
73 static char *accUse[] = {"a","b"};
75 static short rbank = -1;
87 static void saverbank (int, iCode *,bool);
89 #define RESULTONSTACK(x) \
90 (IC_RESULT(x) && IC_RESULT(x)->aop && \
91 IC_RESULT(x)->aop->type == AOP_STK )
93 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
94 #define MOVA(x) { char *_mova_tmp = strdup(x); \
95 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
97 emitcode("mov","a,%s",_mova_tmp); \
101 #define CLRC emitcode("clr","c")
102 #define SETC emitcode("setb","c")
104 static lineNode *lineHead = NULL;
105 static lineNode *lineCurr = NULL;
107 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
108 0xE0, 0xC0, 0x80, 0x00};
109 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
110 0x07, 0x03, 0x01, 0x00};
117 /*-----------------------------------------------------------------*/
118 /* emitcode - writes the code into a file : for now it is simple */
119 /*-----------------------------------------------------------------*/
120 static void emitcode (char *inst,char *fmt, ...)
123 char lb[MAX_INLINEASM];
130 sprintf(lb,"%s\t",inst);
132 sprintf(lb,"%s",inst);
133 vsprintf(lb+(strlen(lb)),fmt,ap);
137 while (isspace(*lbp)) lbp++;
140 lineCurr = (lineCurr ?
141 connectLine(lineCurr,newLineNode(lb)) :
142 (lineHead = newLineNode(lb)));
143 lineCurr->isInline = _G.inLine;
144 lineCurr->isDebug = _G.debugLine;
148 /*-----------------------------------------------------------------*/
149 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
150 /*-----------------------------------------------------------------*/
151 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
153 bool r0iu = FALSE , r1iu = FALSE;
154 bool r0ou = FALSE , r1ou = FALSE;
156 /* the logic: if r0 & r1 used in the instruction
157 then we are in trouble otherwise */
159 /* first check if r0 & r1 are used by this
160 instruction, in which case we are in trouble */
161 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
162 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
167 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
168 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
170 /* if no usage of r0 then return it */
171 if (!r0iu && !r0ou) {
172 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
173 (*aopp)->type = AOP_R0;
175 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
178 /* if no usage of r1 then return it */
179 if (!r1iu && !r1ou) {
180 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
181 (*aopp)->type = AOP_R1;
183 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R1_IDX);
186 /* now we know they both have usage */
187 /* if r0 not used in this instruction */
189 /* push it if not already pushed */
191 emitcode ("push","%s",
192 ds390_regWithIdx(R0_IDX)->dname);
196 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
197 (*aopp)->type = AOP_R0;
199 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
202 /* if r1 not used then */
205 /* push it if not already pushed */
207 emitcode ("push","%s",
208 ds390_regWithIdx(R1_IDX)->dname);
212 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
213 (*aopp)->type = AOP_R1;
214 return ds390_regWithIdx(R1_IDX);
218 /* I said end of world but not quite end of world yet */
219 /* if this is a result then we can push it on the stack*/
221 (*aopp)->type = AOP_STK;
226 /* other wise this is true end of the world */
227 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
228 "getFreePtr should never reach here");
232 /*-----------------------------------------------------------------*/
233 /* newAsmop - creates a new asmOp */
234 /*-----------------------------------------------------------------*/
235 static asmop *newAsmop (short type)
239 ALLOC(aop,sizeof(asmop));
244 /* Turn this off if the world goes to hell. */
247 static int _currentDPS; /* Current processor DPS. */
248 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
249 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
251 /*-----------------------------------------------------------------*/
252 /* genSetDPTR: generate code to select which DPTR is in use (zero */
253 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
254 /* alternate DPTR (DPL1/DPH1/DPX1). */
255 /*-----------------------------------------------------------------*/
256 static void genSetDPTR(int n)
260 /* If we are doing lazy evaluation, simply note the desired
261 * change, but don't emit any code yet.
272 emitcode("mov", "dps, #0x00");
276 emitcode("mov", "dps, #0x01");
280 /*-----------------------------------------------------------------*/
281 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation*/
283 /* Any code that operates on DPTR (NB: not on the individual */
284 /* components, like DPH) *must* call _flushLazyDPS() before using */
285 /* DPTR within a lazy DPS evaluation block. */
287 /* Note that aopPut and aopGet already contain the proper calls to */
288 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
289 /* DPS evaluation block. */
291 /* Also, _flushLazyDPS must be called before any flow control */
292 /* operations that could potentially branch out of the block. */
294 /* Lazy DPS evaluation is simply an optimization (though an */
295 /* important one), so if in doubt, leave it out. */
296 /*-----------------------------------------------------------------*/
297 static void _startLazyDPSEvaluation(void)
304 /*-----------------------------------------------------------------*/
305 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
306 /* desired one. Call before using DPTR within a lazy DPS evaluation*/
308 /*-----------------------------------------------------------------*/
309 static void _flushLazyDPS(void)
317 if (_desiredDPS != _currentDPS)
321 emitcode("inc", "dps");
325 emitcode("dec", "dps");
327 _currentDPS = _desiredDPS;
331 /*-----------------------------------------------------------------*/
332 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
334 /* Forces us back to the safe state (standard DPTR selected). */
335 /*-----------------------------------------------------------------*/
336 static void _endLazyDPSEvaluation(void)
350 /*-----------------------------------------------------------------*/
351 /* pointerCode - returns the code for a pointer type */
352 /*-----------------------------------------------------------------*/
353 static int pointerCode (sym_link *etype)
356 return PTR_TYPE(SPEC_OCLS(etype));
360 /*-----------------------------------------------------------------*/
361 /* aopForSym - for a true symbol */
362 /*-----------------------------------------------------------------*/
363 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
366 memmap *space= SPEC_OCLS(sym->etype);
368 /* if already has one */
372 /* assign depending on the storage class */
373 /* if it is on the stack or indirectly addressable */
374 /* space we need to assign either r0 or r1 to it */
375 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
376 sym->aop = aop = newAsmop(0);
377 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
378 aop->size = getSize(sym->type);
380 /* now assign the address of the variable to
381 the pointer register */
382 if (aop->type != AOP_STK) {
386 emitcode("push","acc");
388 emitcode("mov","a,_bp");
389 emitcode("add","a,#0x%02x",
391 ((char)(sym->stack - _G.nRegsSaved )) :
392 ((char)sym->stack)) & 0xff);
393 emitcode("mov","%s,a",
394 aop->aopu.aop_ptr->name);
397 emitcode("pop","acc");
399 emitcode("mov","%s,#%s",
400 aop->aopu.aop_ptr->name,
402 aop->paged = space->paged;
404 aop->aopu.aop_stk = sym->stack;
408 if (sym->onStack && options.stack10bit)
410 /* It's on the 10 bit stack, which is located in
415 emitcode("push","acc");
417 emitcode("mov","a,_bp");
418 emitcode("add","a,#0x%02x",
420 ((char)(sym->stack - _G.nRegsSaved )) :
421 ((char)sym->stack)) & 0xff);
426 emitcode ("mov","dpx1,#0x40");
427 emitcode ("mov","dph1,#0x00");
428 emitcode ("mov","dpl1, a");
433 emitcode ("mov","dpx,#0x40");
434 emitcode ("mov","dph,#0x00");
435 emitcode ("mov","dpl, a");
439 emitcode("pop","acc");
441 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
442 aop->size = getSize(sym->type);
446 /* if in bit space */
447 if (IN_BITSPACE(space)) {
448 sym->aop = aop = newAsmop (AOP_CRY);
449 aop->aopu.aop_dir = sym->rname ;
450 aop->size = getSize(sym->type);
453 /* if it is in direct space */
454 if (IN_DIRSPACE(space)) {
455 sym->aop = aop = newAsmop (AOP_DIR);
456 aop->aopu.aop_dir = sym->rname ;
457 aop->size = getSize(sym->type);
461 /* special case for a function */
462 if (IS_FUNC(sym->type)) {
463 sym->aop = aop = newAsmop(AOP_IMMD);
464 ALLOC(aop->aopu.aop_immd,strlen(sym->rname)+1);
465 strcpy(aop->aopu.aop_immd,sym->rname);
466 aop->size = FPTRSIZE;
470 /* only remaining is far space */
471 /* in which case DPTR gets the address */
472 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
477 emitcode ("mov","dptr,#%s", sym->rname);
482 emitcode ("mov","dptr,#%s", sym->rname);
484 aop->size = getSize(sym->type);
486 /* if it is in code space */
487 if (IN_CODESPACE(space))
493 /*-----------------------------------------------------------------*/
494 /* aopForRemat - rematerialzes an object */
495 /*-----------------------------------------------------------------*/
496 static asmop *aopForRemat (symbol *sym)
498 iCode *ic = sym->rematiCode;
499 asmop *aop = newAsmop(AOP_IMMD);
505 val += operandLitValue(IC_RIGHT(ic));
506 else if (ic->op == '-')
507 val -= operandLitValue(IC_RIGHT(ic));
511 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
515 sprintf(buffer,"(%s %c 0x%04x)",
516 OP_SYMBOL(IC_LEFT(ic))->rname,
517 val >= 0 ? '+' : '-',
520 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
522 ALLOC(aop->aopu.aop_immd,strlen(buffer)+1);
523 strcpy(aop->aopu.aop_immd,buffer);
527 /*-----------------------------------------------------------------*/
528 /* regsInCommon - two operands have some registers in common */
529 /*-----------------------------------------------------------------*/
530 static bool regsInCommon (operand *op1, operand *op2)
535 /* if they have registers in common */
536 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
539 sym1 = OP_SYMBOL(op1);
540 sym2 = OP_SYMBOL(op2);
542 if (sym1->nRegs == 0 || sym2->nRegs == 0)
545 for (i = 0 ; i < sym1->nRegs ; i++) {
550 for (j = 0 ; j < sym2->nRegs ;j++ ) {
554 if (sym2->regs[j] == sym1->regs[i])
562 /*-----------------------------------------------------------------*/
563 /* operandsEqu - equivalent */
564 /*-----------------------------------------------------------------*/
565 static bool operandsEqu ( operand *op1, operand *op2)
569 /* if they not symbols */
570 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
573 sym1 = OP_SYMBOL(op1);
574 sym2 = OP_SYMBOL(op2);
576 /* if both are itemps & one is spilt
577 and the other is not then false */
578 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
579 sym1->isspilt != sym2->isspilt )
582 /* if they are the same */
586 if (strcmp(sym1->rname,sym2->rname) == 0)
590 /* if left is a tmp & right is not */
594 (sym1->usl.spillLoc == sym2))
601 (sym2->usl.spillLoc == sym1))
607 /*-----------------------------------------------------------------*/
608 /* sameRegs - two asmops have the same registers */
609 /*-----------------------------------------------------------------*/
610 static bool sameRegs (asmop *aop1, asmop *aop2 )
616 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
623 if (aop1->type != AOP_REG ||
624 aop2->type != AOP_REG )
627 if (aop1->size != aop2->size )
630 for (i = 0 ; i < aop1->size ; i++ )
631 if (aop1->aopu.aop_reg[i] !=
632 aop2->aopu.aop_reg[i] )
638 /*-----------------------------------------------------------------*/
639 /* aopOp - allocates an asmop for an operand : */
640 /*-----------------------------------------------------------------*/
641 static void aopOp (operand *op, iCode *ic, bool result, bool useDP2)
650 /* if this a literal */
651 if (IS_OP_LITERAL(op)) {
652 op->aop = aop = newAsmop(AOP_LIT);
653 aop->aopu.aop_lit = op->operand.valOperand;
654 aop->size = getSize(operandType(op));
658 /* if already has a asmop then continue */
662 /* if the underlying symbol has a aop */
663 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
664 op->aop = OP_SYMBOL(op)->aop;
668 /* if this is a true symbol */
669 if (IS_TRUE_SYMOP(op)) {
670 op->aop = aopForSym(ic,OP_SYMBOL(op),result, useDP2);
674 /* this is a temporary : this has
680 e) can be a return use only */
685 /* if the type is a conditional */
686 if (sym->regType == REG_CND) {
687 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
692 /* if it is spilt then two situations
694 b) has a spill location */
695 if (sym->isspilt || sym->nRegs == 0) {
697 /* rematerialize it NOW */
699 sym->aop = op->aop = aop =
701 aop->size = getSize(sym->type);
707 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
708 aop->size = getSize(sym->type);
709 for ( i = 0 ; i < 2 ; i++ )
710 aop->aopu.aop_str[i] = accUse[i];
719 /* a AOP_STR uses DPTR, but DPTR is already in use;
722 fprintf(stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
725 aop = op->aop = sym->aop = newAsmop(AOP_STR);
726 aop->size = getSize(sym->type);
727 for ( i = 0 ; i < fReturnSize_390 ; i++ )
728 aop->aopu.aop_str[i] = fReturn[i];
732 /* else spill location */
733 sym->aop = op->aop = aop =
734 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
735 aop->size = getSize(sym->type);
739 /* must be in a register */
740 sym->aop = op->aop = aop = newAsmop(AOP_REG);
741 aop->size = sym->nRegs;
742 for ( i = 0 ; i < sym->nRegs ;i++)
743 aop->aopu.aop_reg[i] = sym->regs[i];
746 /*-----------------------------------------------------------------*/
747 /* freeAsmop - free up the asmop given to an operand */
748 /*----------------------------------------------------------------*/
749 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
766 /* depending on the asmop type only three cases need work AOP_RO
767 , AOP_R1 && AOP_STK */
772 emitcode ("pop","ar0");
776 bitVectUnSetBit(ic->rUsed,R0_IDX);
782 emitcode ("pop","ar1");
786 bitVectUnSetBit(ic->rUsed,R1_IDX);
792 int stk = aop->aopu.aop_stk + aop->size;
793 bitVectUnSetBit(ic->rUsed,R0_IDX);
794 bitVectUnSetBit(ic->rUsed,R1_IDX);
796 getFreePtr(ic,&aop,FALSE);
798 if (options.stack10bit)
800 /* I'm not sure what to do here yet... */
803 "*** Warning: probably generating bad code for "
804 "10 bit stack mode.\n");
808 emitcode ("mov","a,_bp");
809 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
810 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
812 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
816 emitcode("pop","acc");
817 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
819 emitcode("dec","%s",aop->aopu.aop_ptr->name);
822 freeAsmop(op,NULL,ic,TRUE);
824 emitcode("pop","ar0");
829 emitcode("pop","ar1");
836 /* all other cases just dealloc */
840 OP_SYMBOL(op)->aop = NULL;
841 /* if the symbol has a spill */
843 SPIL_LOC(op)->aop = NULL;
848 /*------------------------------------------------------------------*/
849 /* aopGet - for fetching value of the aop */
851 /* Set canClobberACC if you are aure it is OK to clobber the value */
852 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe,*/
853 /* just less efficient. */
854 /*------------------------------------------------------------------*/
856 static char *aopGet (asmop *aop,
865 /* offset is greater than
867 if (offset > (aop->size - 1) &&
868 aop->type != AOP_LIT)
871 /* depending on type */
876 /* if we need to increment it */
877 while (offset > aop->coff) {
878 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
882 while (offset < aop->coff) {
883 emitcode("dec","%s",aop->aopu.aop_ptr->name);
889 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
890 return (dname ? "acc" : "a");
892 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
893 ALLOC(rs,strlen(s)+1);
900 if (aop->type == AOP_DPTR2)
904 #ifndef KEVIN_BROKE_IT
908 emitcode("xch", "a, ap");
914 while (offset > aop->coff) {
915 emitcode ("inc","dptr");
919 while (offset < aop->coff) {
920 emitcode("lcall","__decdptr");
927 emitcode("movc","a,@a+dptr");
930 emitcode("movx","a,@dptr");
933 if (aop->type == AOP_DPTR2)
937 #ifndef KEVIN_BROKE_IT
941 emitcode("xch", "a, ap");
946 return (dname ? "acc" : "a");
950 sprintf (s,"#%s",aop->aopu.aop_immd);
953 sprintf(s,"#(%s >> %d)",
959 ALLOC(rs,strlen(s)+1);
965 sprintf(s,"(%s + %d)",
969 sprintf(s,"%s",aop->aopu.aop_dir);
970 ALLOC(rs,strlen(s)+1);
976 return aop->aopu.aop_reg[offset]->dname;
978 return aop->aopu.aop_reg[offset]->name;
982 emitcode("mov","c,%s",aop->aopu.aop_dir);
983 emitcode("rlc","a") ;
984 return (dname ? "acc" : "a");
987 if (!offset && dname)
989 return aop->aopu.aop_str[offset];
992 return aopLiteral (aop->aopu.aop_lit,offset);
996 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1000 return aop->aopu.aop_str[offset];
1004 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1005 "aopget got unsupported aop->type");
1008 /*-----------------------------------------------------------------*/
1009 /* aopPut - puts a string for a aop */
1010 /*-----------------------------------------------------------------*/
1011 static void aopPut (asmop *aop, char *s, int offset)
1016 if (aop->size && offset > ( aop->size - 1)) {
1017 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1018 "aopPut got offset > aop->size");
1022 /* will assign value to value */
1023 /* depending on where it is ofcourse */
1024 switch (aop->type) {
1027 sprintf(d,"(%s + %d)",
1028 aop->aopu.aop_dir,offset);
1030 sprintf(d,"%s",aop->aopu.aop_dir);
1033 emitcode("mov","%s,%s",d,s);
1038 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1039 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1041 strcmp(s,"r0") == 0 ||
1042 strcmp(s,"r1") == 0 ||
1043 strcmp(s,"r2") == 0 ||
1044 strcmp(s,"r3") == 0 ||
1045 strcmp(s,"r4") == 0 ||
1046 strcmp(s,"r5") == 0 ||
1047 strcmp(s,"r6") == 0 ||
1048 strcmp(s,"r7") == 0 )
1049 emitcode("mov","%s,%s",
1050 aop->aopu.aop_reg[offset]->dname,s);
1052 emitcode("mov","%s,%s",
1053 aop->aopu.aop_reg[offset]->name,s);
1060 if (aop->type == AOP_DPTR2)
1067 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1068 "aopPut writting to code space");
1072 while (offset > aop->coff) {
1074 emitcode ("inc","dptr");
1077 while (offset < aop->coff) {
1079 emitcode("lcall","__decdptr");
1084 /* if not in accumulater */
1087 emitcode ("movx","@dptr,a");
1089 if (aop->type == AOP_DPTR2)
1097 while (offset > aop->coff) {
1099 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1101 while (offset < aop->coff) {
1103 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1109 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1114 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1116 if (strcmp(s,"r0") == 0 ||
1117 strcmp(s,"r1") == 0 ||
1118 strcmp(s,"r2") == 0 ||
1119 strcmp(s,"r3") == 0 ||
1120 strcmp(s,"r4") == 0 ||
1121 strcmp(s,"r5") == 0 ||
1122 strcmp(s,"r6") == 0 ||
1123 strcmp(s,"r7") == 0 ) {
1125 sprintf(buffer,"a%s",s);
1126 emitcode("mov","@%s,%s",
1127 aop->aopu.aop_ptr->name,buffer);
1129 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1134 if (strcmp(s,"a") == 0)
1135 emitcode("push","acc");
1137 emitcode("push","%s",s);
1142 /* if bit variable */
1143 if (!aop->aopu.aop_dir) {
1144 emitcode("clr","a");
1145 emitcode("rlc","a");
1148 emitcode("clr","%s",aop->aopu.aop_dir);
1151 emitcode("setb","%s",aop->aopu.aop_dir);
1154 emitcode("mov","%s,c",aop->aopu.aop_dir);
1156 lbl = newiTempLabel(NULL);
1158 if (strcmp(s,"a")) {
1161 emitcode("clr","c");
1162 emitcode("jz","%05d$",lbl->key+100);
1163 emitcode("cpl","c");
1164 emitcode("","%05d$:",lbl->key+100);
1165 emitcode("mov","%s,c",aop->aopu.aop_dir);
1172 if (strcmp(aop->aopu.aop_str[offset],s))
1173 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1178 if (!offset && (strcmp(s,"acc") == 0))
1181 if (strcmp(aop->aopu.aop_str[offset],s))
1182 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1186 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1187 "aopPut got unsupported aop->type");
1194 /*-----------------------------------------------------------------*/
1195 /* reAdjustPreg - points a register back to where it should */
1196 /*-----------------------------------------------------------------*/
1197 static void reAdjustPreg (asmop *aop)
1202 if ((size = aop->size) <= 1)
1205 switch (aop->type) {
1209 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1213 if (aop->type == AOP_DPTR2)
1220 emitcode("lcall","__decdptr");
1223 if (aop->type == AOP_DPTR2)
1233 #define AOP(op) op->aop
1234 #define AOP_TYPE(op) AOP(op)->type
1235 #define AOP_SIZE(op) AOP(op)->size
1236 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1237 AOP_TYPE(x) == AOP_R0))
1239 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1240 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1243 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1244 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1245 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1247 /* Workaround for DS80C390 bug: div ab may return bogus results
1248 * if A is accessed in instruction immediately before the div.
1250 * Will be fixed in B4 rev of processor, Dallas claims.
1253 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1254 if (!AOP_NEEDSACC(RIGHT)) \
1256 /* We can load A first, then B, since \
1257 * B (the RIGHT operand) won't clobber A, \
1258 * thus avoiding touching A right before the div. \
1260 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1261 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1263 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1267 /* Just stuff in a nop after loading A. */ \
1268 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1269 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1271 emitcode("nop", "; workaround for DS80C390 div bug."); \
1274 /*-----------------------------------------------------------------*/
1275 /* genNotFloat - generates not for float operations */
1276 /*-----------------------------------------------------------------*/
1277 static void genNotFloat (operand *op, operand *res)
1283 D(emitcode(";", "genNotFloat "););
1285 /* we will put 127 in the first byte of
1287 aopPut(AOP(res),"#127",0);
1288 size = AOP_SIZE(op) - 1;
1291 _startLazyDPSEvaluation();
1292 l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
1296 emitcode("orl","a,%s",
1298 offset++,FALSE,FALSE,FALSE));
1300 _endLazyDPSEvaluation();
1301 tlbl = newiTempLabel(NULL);
1303 tlbl = newiTempLabel(NULL);
1304 aopPut(res->aop,one,1);
1305 emitcode("jz","%05d$",(tlbl->key+100));
1306 aopPut(res->aop,zero,1);
1307 emitcode("","%05d$:",(tlbl->key+100));
1309 size = res->aop->size - 2;
1311 /* put zeros in the rest */
1313 aopPut(res->aop,zero,offset++);
1316 /*-----------------------------------------------------------------*/
1317 /* opIsGptr: returns non-zero if the passed operand is */
1318 /* a generic pointer type. */
1319 /*-----------------------------------------------------------------*/
1320 static int opIsGptr(operand *op)
1322 sym_link *type = operandType(op);
1324 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1331 /*-----------------------------------------------------------------*/
1332 /* getDataSize - get the operand data size */
1333 /*-----------------------------------------------------------------*/
1334 static int getDataSize(operand *op)
1337 size = AOP_SIZE(op);
1338 if (size == GPTRSIZE)
1340 sym_link *type = operandType(op);
1341 if (IS_GENPTR(type))
1343 /* generic pointer; arithmetic operations
1344 * should ignore the high byte (pointer type).
1352 /*-----------------------------------------------------------------*/
1353 /* outAcc - output Acc */
1354 /*-----------------------------------------------------------------*/
1355 static void outAcc(operand *result)
1358 size = getDataSize(result);
1361 aopPut(AOP(result),"a",0);
1364 /* unsigned or positive */
1366 aopPut(AOP(result),zero,offset++);
1371 /*-----------------------------------------------------------------*/
1372 /* outBitC - output a bit C */
1373 /*-----------------------------------------------------------------*/
1374 static void outBitC(operand *result)
1376 /* if the result is bit */
1377 if (AOP_TYPE(result) == AOP_CRY)
1379 aopPut(AOP(result),"c",0);
1383 emitcode("clr","a");
1384 emitcode("rlc","a");
1389 /*-----------------------------------------------------------------*/
1390 /* toBoolean - emit code for orl a,operator(sizeop) */
1391 /*-----------------------------------------------------------------*/
1392 static void toBoolean(operand *oper)
1394 int size = AOP_SIZE(oper) - 1;
1397 /* The generic part of a generic pointer should
1398 * not participate in it's truth value.
1400 * i.e. 0x10000000 is zero.
1404 D(emitcode(";", "toBoolean: generic ptr special case."););
1408 _startLazyDPSEvaluation();
1409 if (AOP_NEEDSACC(oper))
1411 emitcode("push", "b");
1412 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1416 MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1420 if (AOP_NEEDSACC(oper))
1422 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1426 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1429 _endLazyDPSEvaluation();
1431 if (AOP_NEEDSACC(oper))
1433 emitcode("mov", "a,b");
1434 emitcode("pop", "b");
1439 /*-----------------------------------------------------------------*/
1440 /* genNot - generate code for ! operation */
1441 /*-----------------------------------------------------------------*/
1442 static void genNot (iCode *ic)
1445 sym_link *optype = operandType(IC_LEFT(ic));
1447 D(emitcode(";", "genNot "););
1449 /* assign asmOps to operand & result */
1450 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1451 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1453 /* if in bit space then a special case */
1454 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1455 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1456 emitcode("cpl","c");
1457 outBitC(IC_RESULT(ic));
1461 /* if type float then do float */
1462 if (IS_FLOAT(optype)) {
1463 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1467 toBoolean(IC_LEFT(ic));
1469 tlbl = newiTempLabel(NULL);
1470 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1471 emitcode("","%05d$:",tlbl->key+100);
1472 outBitC(IC_RESULT(ic));
1475 /* release the aops */
1476 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1477 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1481 /*-----------------------------------------------------------------*/
1482 /* genCpl - generate code for complement */
1483 /*-----------------------------------------------------------------*/
1484 static void genCpl (iCode *ic)
1489 D(emitcode(";", "genCpl "););
1492 /* assign asmOps to operand & result */
1493 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1494 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1496 /* if both are in bit space then
1498 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1499 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1501 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1502 emitcode("cpl","c");
1503 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1507 size = AOP_SIZE(IC_RESULT(ic));
1508 _startLazyDPSEvaluation();
1510 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1512 emitcode("cpl","a");
1513 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1515 _endLazyDPSEvaluation();
1519 /* release the aops */
1520 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1521 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1524 /*-----------------------------------------------------------------*/
1525 /* genUminusFloat - unary minus for floating points */
1526 /*-----------------------------------------------------------------*/
1527 static void genUminusFloat(operand *op,operand *result)
1529 int size ,offset =0 ;
1531 /* for this we just need to flip the
1532 first it then copy the rest in place */
1533 D(emitcode(";", "genUminusFloat"););
1535 _startLazyDPSEvaluation();
1536 size = AOP_SIZE(op) - 1;
1537 l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1540 emitcode("cpl","acc.7");
1541 aopPut(AOP(result),"a",3);
1545 aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1549 _endLazyDPSEvaluation();
1552 /*-----------------------------------------------------------------*/
1553 /* genUminus - unary minus code generation */
1554 /*-----------------------------------------------------------------*/
1555 static void genUminus (iCode *ic)
1558 sym_link *optype, *rtype;
1560 D(emitcode(";", "genUminus "););
1564 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1565 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1567 /* if both in bit space then special
1569 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1570 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1572 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1573 emitcode("cpl","c");
1574 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1578 optype = operandType(IC_LEFT(ic));
1579 rtype = operandType(IC_RESULT(ic));
1581 /* if float then do float stuff */
1582 if (IS_FLOAT(optype)) {
1583 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1587 /* otherwise subtract from zero */
1588 size = AOP_SIZE(IC_LEFT(ic));
1590 _startLazyDPSEvaluation();
1592 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1593 if (!strcmp(l,"a")) {
1596 emitcode("cpl","a");
1597 emitcode("addc", "a,#0");
1601 emitcode("clr","a");
1602 emitcode("subb","a,%s",l);
1604 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1606 _endLazyDPSEvaluation();
1608 /* if any remaining bytes in the result */
1609 /* we just need to propagate the sign */
1610 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1611 emitcode("rlc","a");
1612 emitcode("subb","a,acc");
1614 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1618 /* release the aops */
1619 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1620 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1623 /*-----------------------------------------------------------------*/
1624 /* saveRegisters - will look for a call and save the registers */
1625 /*-----------------------------------------------------------------*/
1626 static void saveRegisters(iCode *lic)
1634 for (ic = lic ; ic ; ic = ic->next)
1635 if (ic->op == CALL || ic->op == PCALL)
1639 fprintf(stderr,"found parameter push with no function call\n");
1643 /* if the registers have been saved already then
1645 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1648 /* find the registers in use at this time
1649 and push them away to safety */
1650 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1654 if (options.useXstack) {
1655 if (bitVectBitValue(rsave,R0_IDX))
1656 emitcode("mov","b,r0");
1657 emitcode("mov","r0,%s",spname);
1658 for (i = 0 ; i < ds390_nRegs ; i++) {
1659 if (bitVectBitValue(rsave,i)) {
1661 emitcode("mov","a,b");
1663 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1664 emitcode("movx","@r0,a");
1665 emitcode("inc","r0");
1668 emitcode("mov","%s,r0",spname);
1669 if (bitVectBitValue(rsave,R0_IDX))
1670 emitcode("mov","r0,b");
1672 for (i = 0 ; i < ds390_nRegs ; i++) {
1673 if (bitVectBitValue(rsave,i))
1674 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1677 detype = getSpec(operandType(IC_LEFT(ic)));
1679 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1680 IS_ISR(currFunc->etype) &&
1683 saverbank(SPEC_BANK(detype),ic,TRUE);
1686 /*-----------------------------------------------------------------*/
1687 /* unsaveRegisters - pop the pushed registers */
1688 /*-----------------------------------------------------------------*/
1689 static void unsaveRegisters (iCode *ic)
1693 /* find the registers in use at this time
1694 and push them away to safety */
1695 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1698 if (options.useXstack) {
1699 emitcode("mov","r0,%s",spname);
1700 for (i = ds390_nRegs ; i >= 0 ; i--) {
1701 if (bitVectBitValue(rsave,i)) {
1702 emitcode("dec","r0");
1703 emitcode("movx","a,@r0");
1705 emitcode("mov","b,a");
1707 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1711 emitcode("mov","%s,r0",spname);
1712 if (bitVectBitValue(rsave,R0_IDX))
1713 emitcode("mov","r0,b");
1715 for (i = ds390_nRegs ; i >= 0 ; i--) {
1716 if (bitVectBitValue(rsave,i))
1717 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1723 /*-----------------------------------------------------------------*/
1725 /*-----------------------------------------------------------------*/
1726 static void pushSide(operand * oper, int size)
1729 _startLazyDPSEvaluation();
1731 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1732 if (AOP_TYPE(oper) != AOP_REG &&
1733 AOP_TYPE(oper) != AOP_DIR &&
1735 emitcode("mov","a,%s",l);
1736 emitcode("push","acc");
1738 emitcode("push","%s",l);
1740 _endLazyDPSEvaluation();
1743 /*-----------------------------------------------------------------*/
1744 /* assignResultValue - */
1745 /*-----------------------------------------------------------------*/
1746 static void assignResultValue(operand * oper)
1749 int size = AOP_SIZE(oper);
1751 _startLazyDPSEvaluation();
1753 aopPut(AOP(oper),fReturn[offset],offset);
1756 _endLazyDPSEvaluation();
1760 /*-----------------------------------------------------------------*/
1761 /* genXpush - pushes onto the external stack */
1762 /*-----------------------------------------------------------------*/
1763 static void genXpush (iCode *ic)
1765 asmop *aop = newAsmop(0);
1767 int size,offset = 0;
1769 D(emitcode(";", "genXpush "););
1771 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1772 r = getFreePtr(ic,&aop,FALSE);
1775 emitcode("mov","%s,_spx",r->name);
1777 size = AOP_SIZE(IC_LEFT(ic));
1778 _startLazyDPSEvaluation();
1781 char *l = aopGet(AOP(IC_LEFT(ic)),
1782 offset++,FALSE,FALSE,TRUE);
1784 emitcode("movx","@%s,a",r->name);
1785 emitcode("inc","%s",r->name);
1788 _endLazyDPSEvaluation();
1791 emitcode("mov","_spx,%s",r->name);
1793 freeAsmop(NULL,aop,ic,TRUE);
1794 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1797 /*-----------------------------------------------------------------*/
1798 /* genIpush - genrate code for pushing this gets a little complex */
1799 /*-----------------------------------------------------------------*/
1800 static void genIpush (iCode *ic)
1802 int size, offset = 0 ;
1805 D(emitcode(";", "genIpush "););
1808 /* if this is not a parm push : ie. it is spill push
1809 and spill push is always done on the local stack */
1810 if (!ic->parmPush) {
1812 /* and the item is spilt then do nothing */
1813 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1816 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1817 size = AOP_SIZE(IC_LEFT(ic));
1818 /* push it on the stack */
1819 _startLazyDPSEvaluation();
1821 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1826 emitcode("push","%s",l);
1828 _endLazyDPSEvaluation();
1832 /* this is a paramter push: in this case we call
1833 the routine to find the call and save those
1834 registers that need to be saved */
1837 /* if use external stack then call the external
1838 stack pushing routine */
1839 if (options.useXstack) {
1844 /* then do the push */
1845 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1847 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1848 size = AOP_SIZE(IC_LEFT(ic));
1850 _startLazyDPSEvaluation();
1852 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1853 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1854 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1856 emitcode("mov","a,%s",l);
1857 emitcode("push","acc");
1859 emitcode("push","%s",l);
1861 _endLazyDPSEvaluation();
1863 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1866 /*-----------------------------------------------------------------*/
1867 /* genIpop - recover the registers: can happen only for spilling */
1868 /*-----------------------------------------------------------------*/
1869 static void genIpop (iCode *ic)
1873 D(emitcode(";", "genIpop "););
1876 /* if the temp was not pushed then */
1877 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1880 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1881 size = AOP_SIZE(IC_LEFT(ic));
1883 _startLazyDPSEvaluation();
1886 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1889 _endLazyDPSEvaluation();
1891 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1894 /*-----------------------------------------------------------------*/
1895 /* unsaverbank - restores the resgister bank from stack */
1896 /*-----------------------------------------------------------------*/
1897 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1904 if (options.useXstack) {
1906 r = getFreePtr(ic,&aop,FALSE);
1909 emitcode("mov","%s,_spx",r->name);
1910 emitcode("movx","a,@%s",r->name);
1911 emitcode("mov","psw,a");
1912 emitcode("dec","%s",r->name);
1915 emitcode ("pop","psw");
1918 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1919 if (options.useXstack) {
1920 emitcode("movx","a,@%s",r->name);
1921 emitcode("mov","(%s+%d),a",
1922 regs390[i].base,8*bank+regs390[i].offset);
1923 emitcode("dec","%s",r->name);
1926 emitcode("pop","(%s+%d)",
1927 regs390[i].base,8*bank+regs390[i].offset);
1930 if (options.useXstack) {
1932 emitcode("mov","_spx,%s",r->name);
1933 freeAsmop(NULL,aop,ic,TRUE);
1938 /*-----------------------------------------------------------------*/
1939 /* saverbank - saves an entire register bank on the stack */
1940 /*-----------------------------------------------------------------*/
1941 static void saverbank (int bank, iCode *ic, bool pushPsw)
1947 if (options.useXstack) {
1950 r = getFreePtr(ic,&aop,FALSE);
1951 emitcode("mov","%s,_spx",r->name);
1955 for (i = 0 ; i < ds390_nRegs ;i++) {
1956 if (options.useXstack) {
1957 emitcode("inc","%s",r->name);
1958 emitcode("mov","a,(%s+%d)",
1959 regs390[i].base,8*bank+regs390[i].offset);
1960 emitcode("movx","@%s,a",r->name);
1962 emitcode("push","(%s+%d)",
1963 regs390[i].base,8*bank+regs390[i].offset);
1967 if (options.useXstack) {
1968 emitcode("mov","a,psw");
1969 emitcode("movx","@%s,a",r->name);
1970 emitcode("inc","%s",r->name);
1971 emitcode("mov","_spx,%s",r->name);
1972 freeAsmop (NULL,aop,ic,TRUE);
1975 emitcode("push","psw");
1977 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1983 /*-----------------------------------------------------------------*/
1984 /* genCall - generates a call statement */
1985 /*-----------------------------------------------------------------*/
1986 static void genCall (iCode *ic)
1990 D(emitcode(";", "genCall "););
1992 /* if caller saves & we have not saved then */
1996 /* if we are calling a function that is not using
1997 the same register bank then we need to save the
1998 destination registers on the stack */
1999 detype = getSpec(operandType(IC_LEFT(ic)));
2001 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2002 IS_ISR(currFunc->etype) &&
2005 saverbank(SPEC_BANK(detype),ic,TRUE);
2007 /* if send set is not empty the assign */
2011 for (sic = setFirstItem(_G.sendSet) ; sic ;
2012 sic = setNextItem(_G.sendSet))
2014 int size, offset = 0;
2016 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
2017 size = AOP_SIZE(IC_LEFT(sic));
2019 _startLazyDPSEvaluation();
2021 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2022 FALSE, FALSE, TRUE);
2023 if (strcmp(l,fReturn[offset]))
2024 emitcode("mov","%s,%s",
2029 _endLazyDPSEvaluation();
2030 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2035 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2036 OP_SYMBOL(IC_LEFT(ic))->rname :
2037 OP_SYMBOL(IC_LEFT(ic))->name));
2039 /* if we need assign a result value */
2040 if ((IS_ITEMP(IC_RESULT(ic)) &&
2041 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2042 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2043 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2046 /* Not really related to LAZY_DPS_OPT, but don't want
2047 * another testing flag right now...
2049 #define FAR_RETURN_OPT
2050 #ifdef FAR_RETURN_OPT
2051 if (isOperandInFarSpace(IC_RESULT(ic))
2052 && getSize(operandType(IC_RESULT(ic))) <= 2)
2054 int size = getSize(operandType(IC_RESULT(ic)));
2056 /* Special case for 1 or 2 byte return in far space. */
2057 emitcode(";", "Kevin function call abuse #1");
2062 emitcode("mov", "b,%s", fReturn[1]);
2065 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2066 aopPut(AOP(IC_RESULT(ic)),"a",0);
2070 aopPut(AOP(IC_RESULT(ic)),"b",1);
2072 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2078 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2081 assignResultValue(IC_RESULT(ic));
2083 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2086 if (!isOperandInFarSpace(IC_RESULT(ic)))
2089 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2092 assignResultValue(IC_RESULT(ic));
2094 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2098 /* Result is in far space, and requires DPTR to access
2099 * it. Push the result onto the stack and restore from
2102 int size = getSize(operandType(IC_RESULT(ic)));
2103 int offset = size - 1;
2106 emitcode(";", "Kevin function call abuse #1");
2108 /* first push the right side on to the stack */
2109 /* NB: this relies on the fact that "a" is the last
2110 * register in fReturn. If it were not, the MOVA
2111 * would potentially clobber a returned byte in A.
2114 l = fReturn[offset--];
2116 emitcode ("push","acc");
2119 /* now assign DPTR to result */
2120 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2121 size = AOP_SIZE(IC_RESULT(ic));
2122 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
2124 emitcode ("pop","acc");
2125 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
2127 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2132 /* adjust the stack for parameters if
2134 if (IC_LEFT(ic)->parmBytes) {
2136 if (IC_LEFT(ic)->parmBytes > 3) {
2137 emitcode("mov","a,%s",spname);
2138 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2139 emitcode("mov","%s,a",spname);
2141 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2142 emitcode("dec","%s",spname);
2146 /* if register bank was saved then pop them */
2148 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2150 /* if we hade saved some registers then unsave them */
2151 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2152 unsaveRegisters (ic);
2157 /*-----------------------------------------------------------------*/
2158 /* genPcall - generates a call by pointer statement */
2159 /*-----------------------------------------------------------------*/
2160 static void genPcall (iCode *ic)
2163 symbol *rlbl = newiTempLabel(NULL);
2165 D(emitcode(";", "genPcall "););
2168 /* if caller saves & we have not saved then */
2172 /* if we are calling a function that is not using
2173 the same register bank then we need to save the
2174 destination registers on the stack */
2175 detype = getSpec(operandType(IC_LEFT(ic)));
2177 IS_ISR(currFunc->etype) &&
2178 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2179 saverbank(SPEC_BANK(detype),ic,TRUE);
2182 /* push the return address on to the stack */
2183 emitcode("mov","a,#%05d$",(rlbl->key+100));
2184 emitcode("push","acc");
2185 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2186 emitcode("push","acc");
2188 if (options.model == MODEL_FLAT24)
2190 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2191 emitcode("push","acc");
2194 /* now push the calling address */
2195 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2197 pushSide(IC_LEFT(ic), FPTRSIZE);
2199 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2201 /* if send set is not empty the assign */
2205 for (sic = setFirstItem(_G.sendSet) ; sic ;
2206 sic = setNextItem(_G.sendSet))
2208 int size, offset = 0;
2210 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2211 size = AOP_SIZE(IC_LEFT(sic));
2212 _startLazyDPSEvaluation();
2215 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2217 if (strcmp(l,fReturn[offset]))
2219 emitcode("mov","%s,%s",
2225 _endLazyDPSEvaluation();
2226 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2232 emitcode("","%05d$:",(rlbl->key+100));
2235 /* if we need assign a result value */
2236 if ((IS_ITEMP(IC_RESULT(ic)) &&
2237 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2238 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2239 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2242 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2245 assignResultValue(IC_RESULT(ic));
2247 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2250 /* adjust the stack for parameters if
2252 if (IC_LEFT(ic)->parmBytes) {
2254 if (IC_LEFT(ic)->parmBytes > 3) {
2255 emitcode("mov","a,%s",spname);
2256 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2257 emitcode("mov","%s,a",spname);
2259 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2260 emitcode("dec","%s",spname);
2264 /* if register bank was saved then unsave them */
2266 (SPEC_BANK(currFunc->etype) !=
2268 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2270 /* if we hade saved some registers then
2273 unsaveRegisters (ic);
2277 /*-----------------------------------------------------------------*/
2278 /* resultRemat - result is rematerializable */
2279 /*-----------------------------------------------------------------*/
2280 static int resultRemat (iCode *ic)
2282 if (SKIP_IC(ic) || ic->op == IFX)
2285 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2286 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2287 if (sym->remat && !POINTER_SET(ic))
2294 #if defined(__BORLANDC__) || defined(_MSC_VER)
2295 #define STRCASECMP stricmp
2297 #define STRCASECMP strcasecmp
2300 /*-----------------------------------------------------------------*/
2301 /* inExcludeList - return 1 if the string is in exclude Reg list */
2302 /*-----------------------------------------------------------------*/
2303 static bool inExcludeList(char *s)
2307 if (options.excludeRegs[i] &&
2308 STRCASECMP(options.excludeRegs[i],"none") == 0)
2311 for ( i = 0 ; options.excludeRegs[i]; i++) {
2312 if (options.excludeRegs[i] &&
2313 STRCASECMP(s,options.excludeRegs[i]) == 0)
2319 /*-----------------------------------------------------------------*/
2320 /* genFunction - generated code for function entry */
2321 /*-----------------------------------------------------------------*/
2322 static void genFunction (iCode *ic)
2327 D(emitcode(";", "genFunction "););
2330 /* create the function header */
2331 emitcode(";","-----------------------------------------");
2332 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2333 emitcode(";","-----------------------------------------");
2335 emitcode("","%s:",sym->rname);
2336 fetype = getSpec(operandType(IC_LEFT(ic)));
2338 /* if critical function then turn interrupts off */
2339 if (SPEC_CRTCL(fetype))
2340 emitcode("clr","ea");
2342 /* here we need to generate the equates for the
2343 register bank if required */
2344 if (SPEC_BANK(fetype) != rbank) {
2347 rbank = SPEC_BANK(fetype);
2348 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2349 if (strcmp(regs390[i].base,"0") == 0)
2350 emitcode("","%s = 0x%02x",
2352 8*rbank+regs390[i].offset);
2354 emitcode ("","%s = %s + 0x%02x",
2357 8*rbank+regs390[i].offset);
2361 /* if this is an interrupt service routine then
2362 save acc, b, dpl, dph */
2363 if (IS_ISR(sym->etype)) {
2365 if (!inExcludeList("acc"))
2366 emitcode ("push","acc");
2367 if (!inExcludeList("b"))
2368 emitcode ("push","b");
2369 if (!inExcludeList("dpl"))
2370 emitcode ("push","dpl");
2371 if (!inExcludeList("dph"))
2372 emitcode ("push","dph");
2373 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2375 emitcode ("push", "dpx");
2376 /* Make sure we're using standard DPTR */
2377 emitcode ("push", "dps");
2378 emitcode ("mov", "dps, #0x00");
2379 if (options.stack10bit)
2381 /* This ISR could conceivably use DPTR2. Better save it. */
2382 emitcode ("push", "dpl1");
2383 emitcode ("push", "dph1");
2384 emitcode ("push", "dpx1");
2385 emitcode ("push", "ap");
2388 /* if this isr has no bank i.e. is going to
2389 run with bank 0 , then we need to save more
2391 if (!SPEC_BANK(sym->etype)) {
2393 /* if this function does not call any other
2394 function then we can be economical and
2395 save only those registers that are used */
2396 if (! sym->hasFcall) {
2399 /* if any registers used */
2400 if (sym->regsUsed) {
2401 /* save the registers used */
2402 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2403 if (bitVectBitValue(sym->regsUsed,i) ||
2404 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2405 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2410 /* this function has a function call cannot
2411 determines register usage so we will have the
2413 saverbank(0,ic,FALSE);
2417 /* if callee-save to be used for this function
2418 then save the registers being used in this function */
2419 if (sym->calleeSave) {
2422 /* if any registers used */
2423 if (sym->regsUsed) {
2424 /* save the registers used */
2425 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2426 if (bitVectBitValue(sym->regsUsed,i) ||
2427 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2428 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2436 /* set the register bank to the desired value */
2437 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2438 emitcode("push","psw");
2439 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2442 if (IS_RENT(sym->etype) || options.stackAuto) {
2444 if (options.useXstack) {
2445 emitcode("mov","r0,%s",spname);
2446 emitcode("mov","a,_bp");
2447 emitcode("movx","@r0,a");
2448 emitcode("inc","%s",spname);
2452 /* set up the stack */
2453 emitcode ("push","_bp"); /* save the callers stack */
2455 emitcode ("mov","_bp,%s",spname);
2458 /* adjust the stack for the function */
2463 werror(W_STACK_OVERFLOW,sym->name);
2465 if (i > 3 && sym->recvSize < 4) {
2467 emitcode ("mov","a,sp");
2468 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2469 emitcode ("mov","sp,a");
2474 emitcode("inc","sp");
2479 emitcode ("mov","a,_spx");
2480 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2481 emitcode ("mov","_spx,a");
2486 /*-----------------------------------------------------------------*/
2487 /* genEndFunction - generates epilogue for functions */
2488 /*-----------------------------------------------------------------*/
2489 static void genEndFunction (iCode *ic)
2491 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2493 D(emitcode(";", "genEndFunction "););
2495 if (IS_RENT(sym->etype) || options.stackAuto)
2497 emitcode ("mov","%s,_bp",spname);
2500 /* if use external stack but some variables were
2501 added to the local stack then decrement the
2503 if (options.useXstack && sym->stack) {
2504 emitcode("mov","a,sp");
2505 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2506 emitcode("mov","sp,a");
2510 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2511 if (options.useXstack) {
2512 emitcode("mov","r0,%s",spname);
2513 emitcode("movx","a,@r0");
2514 emitcode("mov","_bp,a");
2515 emitcode("dec","%s",spname);
2519 emitcode ("pop","_bp");
2523 /* restore the register bank */
2524 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2525 emitcode ("pop","psw");
2527 if (IS_ISR(sym->etype)) {
2529 /* now we need to restore the registers */
2530 /* if this isr has no bank i.e. is going to
2531 run with bank 0 , then we need to save more
2533 if (!SPEC_BANK(sym->etype)) {
2535 /* if this function does not call any other
2536 function then we can be economical and
2537 save only those registers that are used */
2538 if (! sym->hasFcall) {
2541 /* if any registers used */
2542 if (sym->regsUsed) {
2543 /* save the registers used */
2544 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2545 if (bitVectBitValue(sym->regsUsed,i) ||
2546 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2547 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2552 /* this function has a function call cannot
2553 determines register usage so we will have the
2555 unsaverbank(0,ic,FALSE);
2559 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2561 if (options.stack10bit)
2563 emitcode ("pop", "ap");
2564 emitcode ("pop", "dpx1");
2565 emitcode ("pop", "dph1");
2566 emitcode ("pop", "dpl1");
2568 emitcode ("pop", "dps");
2569 emitcode ("pop", "dpx");
2571 if (!inExcludeList("dph"))
2572 emitcode ("pop","dph");
2573 if (!inExcludeList("dpl"))
2574 emitcode ("pop","dpl");
2575 if (!inExcludeList("b"))
2576 emitcode ("pop","b");
2577 if (!inExcludeList("acc"))
2578 emitcode ("pop","acc");
2580 if (SPEC_CRTCL(sym->etype))
2581 emitcode("setb","ea");
2583 /* if debug then send end of function */
2584 /* if (options.debug && currFunc) { */
2587 emitcode("","C$%s$%d$%d$%d ==.",
2588 ic->filename,currFunc->lastLine,
2589 ic->level,ic->block);
2590 if (IS_STATIC(currFunc->etype))
2591 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2593 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2597 emitcode ("reti","");
2600 if (SPEC_CRTCL(sym->etype))
2601 emitcode("setb","ea");
2603 if (sym->calleeSave) {
2606 /* if any registers used */
2607 if (sym->regsUsed) {
2608 /* save the registers used */
2609 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2610 if (bitVectBitValue(sym->regsUsed,i) ||
2611 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2612 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2618 /* if debug then send end of function */
2621 emitcode("","C$%s$%d$%d$%d ==.",
2622 ic->filename,currFunc->lastLine,
2623 ic->level,ic->block);
2624 if (IS_STATIC(currFunc->etype))
2625 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2627 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2631 emitcode ("ret","");
2636 /*-----------------------------------------------------------------*/
2637 /* genRet - generate code for return statement */
2638 /*-----------------------------------------------------------------*/
2639 static void genRet (iCode *ic)
2641 int size,offset = 0 , pushed = 0;
2643 D(emitcode(";", "genRet "););
2645 /* if we have no return value then
2646 just generate the "ret" */
2650 /* we have something to return then
2651 move the return value into place */
2652 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2653 size = AOP_SIZE(IC_LEFT(ic));
2655 _startLazyDPSEvaluation();
2658 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2659 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2661 emitcode("push","%s",l);
2664 l = aopGet(AOP(IC_LEFT(ic)),offset,
2666 if (strcmp(fReturn[offset],l))
2667 emitcode("mov","%s,%s",fReturn[offset++],l);
2670 _endLazyDPSEvaluation();
2675 if (strcmp(fReturn[pushed],"a"))
2676 emitcode("pop",fReturn[pushed]);
2678 emitcode("pop","acc");
2681 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2684 /* generate a jump to the return label
2685 if the next is not the return statement */
2686 if (!(ic->next && ic->next->op == LABEL &&
2687 IC_LABEL(ic->next) == returnLabel))
2689 emitcode("ljmp","%05d$",(returnLabel->key+100));
2693 /*-----------------------------------------------------------------*/
2694 /* genLabel - generates a label */
2695 /*-----------------------------------------------------------------*/
2696 static void genLabel (iCode *ic)
2698 /* special case never generate */
2699 if (IC_LABEL(ic) == entryLabel)
2702 D(emitcode(";", "genLabel "););
2704 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2707 /*-----------------------------------------------------------------*/
2708 /* genGoto - generates a ljmp */
2709 /*-----------------------------------------------------------------*/
2710 static void genGoto (iCode *ic)
2712 D(emitcode(";", "genGoto "););
2713 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2716 /*-----------------------------------------------------------------*/
2717 /* findLabelBackwards: walks back through the iCode chain looking */
2718 /* for the given label. Returns number of iCode instructions */
2719 /* between that label and given ic. */
2720 /* Returns zero if label not found. */
2721 /*-----------------------------------------------------------------*/
2722 static int findLabelBackwards(iCode *ic, int key)
2731 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2733 /* printf("findLabelBackwards = %d\n", count); */
2741 /*-----------------------------------------------------------------*/
2742 /* genPlusIncr :- does addition with increment if possible */
2743 /*-----------------------------------------------------------------*/
2744 static bool genPlusIncr (iCode *ic)
2746 unsigned int icount ;
2747 unsigned int size = getDataSize(IC_RESULT(ic));
2749 /* will try to generate an increment */
2750 /* if the right side is not a literal
2752 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2755 /* if the literal value of the right hand side
2756 is greater than 4 then it is not worth it */
2757 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2760 /* if increment 16 bits in register */
2762 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2763 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2764 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2771 /* If the next instruction is a goto and the goto target
2772 * is <= 5 instructions previous to this, we can generate
2773 * jumps straight to that target.
2775 if (ic->next && ic->next->op == GOTO
2776 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2777 && labelRange <= 5 )
2779 emitcode(";", "tail increment optimized (range %d)", labelRange);
2780 tlbl = IC_LABEL(ic->next);
2785 tlbl = newiTempLabel(NULL);
2788 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2789 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2790 IS_AOP_PREG(IC_RESULT(ic)))
2791 emitcode("cjne","%s,#0x00,%05d$"
2792 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2795 emitcode("clr","a");
2796 emitcode("cjne","a,%s,%05d$"
2797 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2801 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2804 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2805 IS_AOP_PREG(IC_RESULT(ic)))
2806 emitcode("cjne","%s,#0x00,%05d$"
2807 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2810 emitcode("cjne","a,%s,%05d$"
2811 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2814 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2818 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2819 IS_AOP_PREG(IC_RESULT(ic)))
2820 emitcode("cjne","%s,#0x00,%05d$"
2821 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2824 emitcode("cjne","a,%s,%05d$"
2825 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2828 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2833 emitcode("","%05d$:",tlbl->key+100);
2838 /* if the sizes are greater than 1 then we cannot */
2839 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2840 AOP_SIZE(IC_LEFT(ic)) > 1 )
2843 /* we can if the aops of the left & result match or
2844 if they are in registers and the registers are the
2847 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2848 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2849 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2852 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2853 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2854 aopPut(AOP(IC_RESULT(ic)),"a",0);
2857 _startLazyDPSEvaluation();
2860 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2862 _endLazyDPSEvaluation();
2871 /*-----------------------------------------------------------------*/
2872 /* outBitAcc - output a bit in acc */
2873 /*-----------------------------------------------------------------*/
2874 static void outBitAcc(operand *result)
2876 symbol *tlbl = newiTempLabel(NULL);
2877 /* if the result is a bit */
2878 if (AOP_TYPE(result) == AOP_CRY){
2879 aopPut(AOP(result),"a",0);
2882 emitcode("jz","%05d$",tlbl->key+100);
2883 emitcode("mov","a,%s",one);
2884 emitcode("","%05d$:",tlbl->key+100);
2889 /*-----------------------------------------------------------------*/
2890 /* genPlusBits - generates code for addition of two bits */
2891 /*-----------------------------------------------------------------*/
2892 static void genPlusBits (iCode *ic)
2894 D(emitcode(";", "genPlusBits "););
2895 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2896 symbol *lbl = newiTempLabel(NULL);
2897 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2898 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2899 emitcode("cpl","c");
2900 emitcode("","%05d$:",(lbl->key+100));
2901 outBitC(IC_RESULT(ic));
2904 emitcode("clr","a");
2905 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2906 emitcode("rlc","a");
2907 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2908 emitcode("addc","a,#0x00");
2909 outAcc(IC_RESULT(ic));
2913 static void adjustArithmeticResult(iCode *ic)
2915 if (opIsGptr(IC_RESULT(ic)) &&
2916 opIsGptr(IC_LEFT(ic)) &&
2917 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2919 aopPut(AOP(IC_RESULT(ic)),
2920 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2924 if (opIsGptr(IC_RESULT(ic)) &&
2925 opIsGptr(IC_RIGHT(ic)) &&
2926 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2928 aopPut(AOP(IC_RESULT(ic)),
2929 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2933 if (opIsGptr(IC_RESULT(ic)) &&
2934 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2935 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2936 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2937 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2939 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2940 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2945 #define AOP_OP_3(ic) \
2946 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2947 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2948 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2949 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2950 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2952 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2954 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2957 #define AOP_OP_3(ic) \
2958 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2959 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2960 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
2961 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2962 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2963 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2965 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2967 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2970 #define AOP_OP_3_NOFATAL(ic, rc) \
2971 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2972 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2973 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2974 isOperandInFarSpace(IC_RESULT(ic))) \
2976 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
2981 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
2982 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2984 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2985 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2987 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2989 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2993 #define AOP_OP_2(ic) \
2994 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2995 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3000 #define AOP_SET_LOCALS(ic) \
3001 left = IC_LEFT(ic); \
3002 right = IC_RIGHT(ic); \
3003 result = IC_RESULT(ic);
3005 /*-----------------------------------------------------------------*/
3006 /* genPlus - generates code for addition */
3007 /*-----------------------------------------------------------------*/
3008 static void genPlus (iCode *ic)
3010 int size, offset = 0;
3011 bool pushResult = FALSE;
3014 D(emitcode(";", "genPlus "););
3016 /* special cases :- */
3019 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
3020 aopOp (IC_LEFT(ic),ic,FALSE,
3021 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3022 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
3023 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
3029 aopOp (IC_RESULT(ic),ic,TRUE,
3030 ((AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)
3031 || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR)));
3034 AOP_OP_3_NOFATAL(ic, pushResult);
3037 D(emitcode(";", "genPlus: must push result: 3 ops in far space"););
3043 /* if literal, literal on the right or
3044 if left requires ACC or right is already
3046 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)
3047 || ((AOP_NEEDSACC(IC_LEFT(ic))) && !(AOP_NEEDSACC(IC_RIGHT(ic))))
3048 || AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC )
3050 operand *t = IC_RIGHT(ic);
3051 IC_RIGHT(ic) = IC_LEFT(ic);
3053 emitcode(";", "Swapped plus args.");
3056 /* if both left & right are in bit
3058 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3059 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3064 /* if left in bit space & right literal */
3065 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3066 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3067 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3068 /* if result in bit space */
3069 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3070 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
3071 emitcode("cpl","c");
3072 outBitC(IC_RESULT(ic));
3074 size = getDataSize(IC_RESULT(ic));
3075 _startLazyDPSEvaluation();
3077 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3078 emitcode("addc","a,#00");
3079 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3081 _endLazyDPSEvaluation();
3086 /* if I can do an increment instead
3087 of add then GOOD for ME */
3088 if (genPlusIncr (ic) == TRUE)
3090 emitcode(";", "did genPlusIncr");
3095 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3097 _startLazyDPSEvaluation();
3100 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3102 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3104 emitcode("add","a,%s",
3105 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3107 emitcode("addc","a,%s",
3108 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3110 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3112 emitcode("add","a,%s",
3113 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3115 emitcode("addc","a,%s",
3116 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3120 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3124 emitcode("push", "acc");
3128 _endLazyDPSEvaluation();
3132 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3134 size = getDataSize(IC_LEFT(ic));
3135 rSize = getDataSize(IC_RESULT(ic));
3137 /* If the pushed data is bigger than the result,
3138 * simply discard unused bytes. Icky, but works.
3140 * Should we throw a warning here? We're losing data...
3142 while (size > rSize)
3144 D(emitcode(";", "discarding unused result byte."););
3145 emitcode("pop", "acc");
3151 emitcode("clr", "a");
3152 /* Conversly, we haven't pushed enough here.
3153 * just zero-pad, and all is well.
3155 while (size < rSize)
3157 emitcode("push", "acc");
3163 _startLazyDPSEvaluation();
3166 emitcode("pop", "acc");
3167 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3169 _endLazyDPSEvaluation();
3172 adjustArithmeticResult(ic);
3175 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3176 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3177 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3180 /*-----------------------------------------------------------------*/
3181 /* genMinusDec :- does subtraction with deccrement if possible */
3182 /*-----------------------------------------------------------------*/
3183 static bool genMinusDec (iCode *ic)
3185 unsigned int icount ;
3186 unsigned int size = getDataSize(IC_RESULT(ic));
3188 /* will try to generate an increment */
3189 /* if the right side is not a literal
3191 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3194 /* if the literal value of the right hand side
3195 is greater than 4 then it is not worth it */
3196 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3199 /* if decrement 16 bits in register */
3200 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3201 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3202 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3209 /* If the next instruction is a goto and the goto target
3210 * is <= 5 instructions previous to this, we can generate
3211 * jumps straight to that target.
3213 if (ic->next && ic->next->op == GOTO
3214 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3215 && labelRange <= 5 )
3217 emitcode(";", "tail decrement optimized (range %d)", labelRange);
3218 tlbl = IC_LABEL(ic->next);
3223 tlbl = newiTempLabel(NULL);
3227 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3228 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3229 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3230 IS_AOP_PREG(IC_RESULT(ic)))
3231 emitcode("cjne","%s,#0xff,%05d$"
3232 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3235 emitcode("mov","a,#0xff");
3236 emitcode("cjne","a,%s,%05d$"
3237 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3240 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3243 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3244 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3245 IS_AOP_PREG(IC_RESULT(ic)))
3246 emitcode("cjne","%s,#0xff,%05d$"
3247 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3250 emitcode("cjne","a,%s,%05d$"
3251 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3254 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3258 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3259 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3260 IS_AOP_PREG(IC_RESULT(ic)))
3261 emitcode("cjne","%s,#0xff,%05d$"
3262 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3265 emitcode("cjne","a,%s,%05d$"
3266 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3269 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3273 emitcode("","%05d$:",tlbl->key+100);
3278 /* if the sizes are greater than 1 then we cannot */
3279 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3280 AOP_SIZE(IC_LEFT(ic)) > 1 )
3283 /* we can if the aops of the left & result match or
3284 if they are in registers and the registers are the
3287 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3288 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3289 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3291 _startLazyDPSEvaluation();
3294 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3296 _endLazyDPSEvaluation();
3304 /*-----------------------------------------------------------------*/
3305 /* addSign - complete with sign */
3306 /*-----------------------------------------------------------------*/
3307 static void addSign(operand *result, int offset, int sign)
3309 int size = (getDataSize(result) - offset);
3312 emitcode("rlc","a");
3313 emitcode("subb","a,acc");
3315 aopPut(AOP(result),"a",offset++);
3318 aopPut(AOP(result),zero,offset++);
3322 /*-----------------------------------------------------------------*/
3323 /* genMinusBits - generates code for subtraction of two bits */
3324 /*-----------------------------------------------------------------*/
3325 static void genMinusBits (iCode *ic)
3327 symbol *lbl = newiTempLabel(NULL);
3329 D(emitcode(";", "genMinusBits "););
3331 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3332 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3333 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3334 emitcode("cpl","c");
3335 emitcode("","%05d$:",(lbl->key+100));
3336 outBitC(IC_RESULT(ic));
3339 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3340 emitcode("subb","a,acc");
3341 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3342 emitcode("inc","a");
3343 emitcode("","%05d$:",(lbl->key+100));
3344 aopPut(AOP(IC_RESULT(ic)),"a",0);
3345 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3349 /*-----------------------------------------------------------------*/
3350 /* genMinus - generates code for subtraction */
3351 /*-----------------------------------------------------------------*/
3352 static void genMinus (iCode *ic)
3354 int size, offset = 0;
3356 unsigned long lit = 0L;
3357 bool pushResult = FALSE;
3359 D(emitcode(";", "genMinus "););
3361 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3362 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3363 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3364 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3370 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3372 /* special cases :- */
3373 /* if both left & right are in bit space */
3374 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3375 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3380 /* if I can do an decrement instead
3381 of subtract then GOOD for ME */
3382 if (genMinusDec (ic) == TRUE)
3387 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3389 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3393 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3398 /* if literal, add a,#-lit, else normal subb */
3399 _startLazyDPSEvaluation();
3401 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3402 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3403 emitcode("subb","a,%s",
3404 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3406 /* first add without previous c */
3408 emitcode("add","a,#0x%02x",
3409 (unsigned int)(lit & 0x0FFL));
3411 emitcode("addc","a,#0x%02x",
3412 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3417 emitcode("push", "acc");
3421 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3425 _endLazyDPSEvaluation();
3429 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3431 size = getDataSize(IC_LEFT(ic));
3432 rSize = getDataSize(IC_RESULT(ic));
3434 /* If the pushed data is bigger than the result,
3435 * simply discard unused bytes. Icky, but works.
3437 * Should we throw a warning here? We're losing data...
3439 while (size > getDataSize(IC_RESULT(ic)))
3441 emitcode(";", "discarding unused result byte.");
3442 emitcode("pop", "acc");
3448 emitcode("clr", "a");
3449 /* Conversly, we haven't pushed enough here.
3450 * just zero-pad, and all is well.
3452 while (size < rSize)
3454 emitcode("push", "acc");
3462 emitcode("pop", "acc");
3463 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3467 adjustArithmeticResult(ic);
3470 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3471 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3472 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3476 /*-----------------------------------------------------------------*/
3477 /* genMultbits :- multiplication of bits */
3478 /*-----------------------------------------------------------------*/
3479 static void genMultbits (operand *left,
3483 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3484 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3489 /*-----------------------------------------------------------------*/
3490 /* genMultOneByte : 8 bit multiplication & division */
3491 /*-----------------------------------------------------------------*/
3492 static void genMultOneByte (operand *left,
3496 sym_link *opetype = operandType(result);
3501 /* (if two literals, the value is computed before) */
3502 /* if one literal, literal on the right */
3503 if (AOP_TYPE(left) == AOP_LIT){
3509 size = AOP_SIZE(result);
3510 /* signed or unsigned */
3511 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3512 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3514 emitcode("mul","ab");
3515 /* if result size = 1, mul signed = mul unsigned */
3516 aopPut(AOP(result),"a",0);
3518 if (SPEC_USIGN(opetype)){
3519 aopPut(AOP(result),"b",1);
3521 /* for filling the MSBs */
3522 emitcode("clr","a");
3525 emitcode("mov","a,b");
3527 /* adjust the MSB if left or right neg */
3529 /* if one literal */
3530 if (AOP_TYPE(right) == AOP_LIT){
3531 /* AND literal negative */
3532 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3533 /* adjust MSB (c==0 after mul) */
3534 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3538 lbl = newiTempLabel(NULL);
3539 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3540 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3541 emitcode("","%05d$:",(lbl->key+100));
3542 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3543 lbl = newiTempLabel(NULL);
3544 emitcode("jc","%05d$",(lbl->key+100));
3545 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3546 emitcode("","%05d$:",(lbl->key+100));
3549 lbl = newiTempLabel(NULL);
3550 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3551 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3552 emitcode("","%05d$:",(lbl->key+100));
3553 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3554 lbl = newiTempLabel(NULL);
3555 emitcode("jc","%05d$",(lbl->key+100));
3556 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3557 emitcode("","%05d$:",(lbl->key+100));
3559 aopPut(AOP(result),"a",1);
3562 emitcode("rlc","a");
3563 emitcode("subb","a,acc");
3570 aopPut(AOP(result),"a",offset++);
3574 /*-----------------------------------------------------------------*/
3575 /* genMult - generates code for multiplication */
3576 /*-----------------------------------------------------------------*/
3577 static void genMult (iCode *ic)
3579 operand *left = IC_LEFT(ic);
3580 operand *right = IC_RIGHT(ic);
3581 operand *result= IC_RESULT(ic);
3583 D(emitcode(";", "genMult "););
3585 /* assign the amsops */
3588 aopOp (left,ic,FALSE, FALSE);
3589 aopOp (right,ic,FALSE, TRUE);
3590 aopOp (result,ic,TRUE, FALSE);
3593 /* special cases first */
3595 if (AOP_TYPE(left) == AOP_CRY &&
3596 AOP_TYPE(right)== AOP_CRY) {
3597 genMultbits(left,right,result);
3601 /* if both are of size == 1 */
3602 if (AOP_SIZE(left) == 1 &&
3603 AOP_SIZE(right) == 1 ) {
3604 genMultOneByte(left,right,result);
3608 /* should have been converted to function call */
3612 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3613 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3614 freeAsmop(result,NULL,ic,TRUE);
3617 /*-----------------------------------------------------------------*/
3618 /* genDivbits :- division of bits */
3619 /*-----------------------------------------------------------------*/
3620 static void genDivbits (operand *left,
3627 /* the result must be bit */
3628 LOAD_AB_FOR_DIV(left, right, l);
3629 emitcode("div","ab");
3630 emitcode("rrc","a");
3631 aopPut(AOP(result),"c",0);
3634 /*-----------------------------------------------------------------*/
3635 /* genDivOneByte : 8 bit division */
3636 /*-----------------------------------------------------------------*/
3637 static void genDivOneByte (operand *left,
3641 sym_link *opetype = operandType(result);
3646 size = AOP_SIZE(result) - 1;
3648 /* signed or unsigned */
3649 if (SPEC_USIGN(opetype)) {
3650 /* unsigned is easy */
3651 LOAD_AB_FOR_DIV(left, right, l);
3652 emitcode("div","ab");
3653 aopPut(AOP(result),"a",0);
3655 aopPut(AOP(result),zero,offset++);
3659 /* signed is a little bit more difficult */
3661 /* save the signs of the operands */
3662 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3664 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3665 emitcode("push","acc"); /* save it on the stack */
3667 /* now sign adjust for both left & right */
3668 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3670 lbl = newiTempLabel(NULL);
3671 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3672 emitcode("cpl","a");
3673 emitcode("inc","a");
3674 emitcode("","%05d$:",(lbl->key+100));
3675 emitcode("mov","b,a");
3677 /* sign adjust left side */
3678 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3681 lbl = newiTempLabel(NULL);
3682 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3683 emitcode("cpl","a");
3684 emitcode("inc","a");
3685 emitcode("","%05d$:",(lbl->key+100));
3687 /* now the division */
3688 emitcode("nop", "; workaround for DS80C390 div bug.");
3689 emitcode("div","ab");
3690 /* we are interested in the lower order
3692 emitcode("mov","b,a");
3693 lbl = newiTempLabel(NULL);
3694 emitcode("pop","acc");
3695 /* if there was an over flow we don't
3696 adjust the sign of the result */
3697 emitcode("jb","ov,%05d$",(lbl->key+100));
3698 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3700 emitcode("clr","a");
3701 emitcode("subb","a,b");
3702 emitcode("mov","b,a");
3703 emitcode("","%05d$:",(lbl->key+100));
3705 /* now we are done */
3706 aopPut(AOP(result),"b",0);
3708 emitcode("mov","c,b.7");
3709 emitcode("subb","a,acc");
3712 aopPut(AOP(result),"a",offset++);
3716 /*-----------------------------------------------------------------*/
3717 /* genDiv - generates code for division */
3718 /*-----------------------------------------------------------------*/
3719 static void genDiv (iCode *ic)
3721 operand *left = IC_LEFT(ic);
3722 operand *right = IC_RIGHT(ic);
3723 operand *result= IC_RESULT(ic);
3725 D(emitcode(";", "genDiv "););
3727 /* assign the amsops */
3730 aopOp (left,ic,FALSE, FALSE);
3731 aopOp (right,ic,FALSE, TRUE);
3732 aopOp (result,ic,TRUE, FALSE);
3735 /* special cases first */
3737 if (AOP_TYPE(left) == AOP_CRY &&
3738 AOP_TYPE(right)== AOP_CRY) {
3739 genDivbits(left,right,result);
3743 /* if both are of size == 1 */
3744 if (AOP_SIZE(left) == 1 &&
3745 AOP_SIZE(right) == 1 ) {
3746 genDivOneByte(left,right,result);
3750 /* should have been converted to function call */
3753 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3754 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3755 freeAsmop(result,NULL,ic,TRUE);
3758 /*-----------------------------------------------------------------*/
3759 /* genModbits :- modulus of bits */
3760 /*-----------------------------------------------------------------*/
3761 static void genModbits (operand *left,
3768 /* the result must be bit */
3769 LOAD_AB_FOR_DIV(left, right, l);
3770 emitcode("div","ab");
3771 emitcode("mov","a,b");
3772 emitcode("rrc","a");
3773 aopPut(AOP(result),"c",0);
3776 /*-----------------------------------------------------------------*/
3777 /* genModOneByte : 8 bit modulus */
3778 /*-----------------------------------------------------------------*/
3779 static void genModOneByte (operand *left,
3783 sym_link *opetype = operandType(result);
3787 /* signed or unsigned */
3788 if (SPEC_USIGN(opetype)) {
3789 /* unsigned is easy */
3790 LOAD_AB_FOR_DIV(left, right, l);
3791 emitcode("div","ab");
3792 aopPut(AOP(result),"b",0);
3796 /* signed is a little bit more difficult */
3798 /* save the signs of the operands */
3799 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3802 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3803 emitcode("push","acc"); /* save it on the stack */
3805 /* now sign adjust for both left & right */
3806 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3809 lbl = newiTempLabel(NULL);
3810 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3811 emitcode("cpl","a");
3812 emitcode("inc","a");
3813 emitcode("","%05d$:",(lbl->key+100));
3814 emitcode("mov","b,a");
3816 /* sign adjust left side */
3817 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3820 lbl = newiTempLabel(NULL);
3821 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3822 emitcode("cpl","a");
3823 emitcode("inc","a");
3824 emitcode("","%05d$:",(lbl->key+100));
3826 /* now the multiplication */
3827 emitcode("nop", "; workaround for DS80C390 div bug.");
3828 emitcode("div","ab");
3829 /* we are interested in the lower order
3831 lbl = newiTempLabel(NULL);
3832 emitcode("pop","acc");
3833 /* if there was an over flow we don't
3834 adjust the sign of the result */
3835 emitcode("jb","ov,%05d$",(lbl->key+100));
3836 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3838 emitcode("clr","a");
3839 emitcode("subb","a,b");
3840 emitcode("mov","b,a");
3841 emitcode("","%05d$:",(lbl->key+100));
3843 /* now we are done */
3844 aopPut(AOP(result),"b",0);
3848 /*-----------------------------------------------------------------*/
3849 /* genMod - generates code for division */
3850 /*-----------------------------------------------------------------*/
3851 static void genMod (iCode *ic)
3853 operand *left = IC_LEFT(ic);
3854 operand *right = IC_RIGHT(ic);
3855 operand *result= IC_RESULT(ic);
3857 D(emitcode(";", "genMod "););
3859 /* assign the amsops */
3862 aopOp (left,ic,FALSE, FALSE);
3863 aopOp (right,ic,FALSE, TRUE);
3864 aopOp (result,ic,TRUE, FALSE);
3867 /* special cases first */
3869 if (AOP_TYPE(left) == AOP_CRY &&
3870 AOP_TYPE(right)== AOP_CRY) {
3871 genModbits(left,right,result);
3875 /* if both are of size == 1 */
3876 if (AOP_SIZE(left) == 1 &&
3877 AOP_SIZE(right) == 1 ) {
3878 genModOneByte(left,right,result);
3882 /* should have been converted to function call */
3886 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3887 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3888 freeAsmop(result,NULL,ic,TRUE);
3891 /*-----------------------------------------------------------------*/
3892 /* genIfxJump :- will create a jump depending on the ifx */
3893 /*-----------------------------------------------------------------*/
3894 static void genIfxJump (iCode *ic, char *jval)
3897 symbol *tlbl = newiTempLabel(NULL);
3900 D(emitcode(";", "genIfxJump "););
3902 /* if true label then we jump if condition
3904 if ( IC_TRUE(ic) ) {
3906 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3907 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3910 /* false label is present */
3911 jlbl = IC_FALSE(ic) ;
3912 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3913 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3915 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3916 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3918 emitcode(inst,"%05d$",tlbl->key+100);
3919 emitcode("ljmp","%05d$",jlbl->key+100);
3920 emitcode("","%05d$:",tlbl->key+100);
3922 /* mark the icode as generated */
3926 /*-----------------------------------------------------------------*/
3927 /* genCmp :- greater or less than comparison */
3928 /*-----------------------------------------------------------------*/
3929 static void genCmp (operand *left,operand *right,
3930 iCode *ic, iCode *ifx, int sign)
3932 int size, offset = 0 ;
3933 unsigned long lit = 0L;
3936 D(emitcode(";", "genCmp"););
3938 result = IC_RESULT(ic);
3940 /* if left & right are bit variables */
3941 if (AOP_TYPE(left) == AOP_CRY &&
3942 AOP_TYPE(right) == AOP_CRY ) {
3943 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3944 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3946 /* subtract right from left if at the
3947 end the carry flag is set then we know that
3948 left is greater than right */
3949 size = max(AOP_SIZE(left),AOP_SIZE(right));
3951 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3952 if((size == 1) && !sign &&
3953 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3954 symbol *lbl = newiTempLabel(NULL);
3955 emitcode("cjne","%s,%s,%05d$",
3956 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3957 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3959 emitcode("","%05d$:",lbl->key+100);
3961 if (AOP_TYPE(right) == AOP_LIT)
3963 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3964 /* optimize if(x < 0) or if(x >= 0) */
3973 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3975 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3976 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3978 aopOp(result,ic,FALSE, FALSE);
3980 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx)
3982 freeAsmop(result,NULL,ic,TRUE);
3983 genIfxJump (ifx,"acc.7");
3988 emitcode("rlc","a");
3990 goto release_freedLR;
3998 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3999 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4000 emitcode(";", "genCmp #2");
4001 if (sign && (size == 0))
4003 emitcode(";", "genCmp #3");
4004 emitcode("xrl","a,#0x80");
4005 if (AOP_TYPE(right) == AOP_LIT)
4007 unsigned long lit = (unsigned long)
4008 floatFromVal(AOP(right)->aopu.aop_lit);
4009 emitcode(";", "genCmp #3.1");
4010 emitcode("subb","a,#0x%02x",
4011 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
4015 emitcode(";", "genCmp #3.2");
4016 if (AOP_NEEDSACC(right))
4018 emitcode("push", "acc");
4020 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
4021 FALSE,FALSE,FALSE));
4022 emitcode("xrl","b,#0x80");
4023 if (AOP_NEEDSACC(right))
4025 emitcode("pop", "acc");
4027 emitcode("subb","a,b");
4034 emitcode(";", "genCmp #4");
4035 if (AOP_NEEDSACC(right))
4038 emitcode(";", "genCmp #4.1");
4039 emitcode("xch", "a, b");
4040 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
4041 emitcode("xch", "a, b");
4046 emitcode(";", "genCmp #4.2");
4047 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
4050 emitcode("subb","a,%s",s);
4057 /* Don't need the left & right operands any more; do need the result. */
4058 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4059 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4061 aopOp(result,ic,FALSE, FALSE);
4065 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result))
4071 /* if the result is used in the next
4072 ifx conditional branch then generate
4073 code a little differently */
4076 genIfxJump (ifx,"c");
4082 /* leave the result in acc */
4084 freeAsmop(result,NULL,ic,TRUE);
4087 /*-----------------------------------------------------------------*/
4088 /* genCmpGt :- greater than comparison */
4089 /*-----------------------------------------------------------------*/
4090 static void genCmpGt (iCode *ic, iCode *ifx)
4092 operand *left, *right;
4093 sym_link *letype , *retype;
4096 D(emitcode(";", "genCmpGt "););
4099 right= IC_RIGHT(ic);
4101 letype = getSpec(operandType(left));
4102 retype =getSpec(operandType(right));
4103 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4105 /* assign the left & right amsops */
4108 genCmp(right, left, ic, ifx, sign);
4111 /*-----------------------------------------------------------------*/
4112 /* genCmpLt - less than comparisons */
4113 /*-----------------------------------------------------------------*/
4114 static void genCmpLt (iCode *ic, iCode *ifx)
4116 operand *left, *right;
4117 sym_link *letype , *retype;
4120 D(emitcode(";", "genCmpLt "););
4123 right= IC_RIGHT(ic);
4125 letype = getSpec(operandType(left));
4126 retype =getSpec(operandType(right));
4127 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4129 /* assign the left & right amsops */
4132 genCmp(left, right, ic, ifx, sign);
4135 /*-----------------------------------------------------------------*/
4136 /* gencjneshort - compare and jump if not equal */
4137 /*-----------------------------------------------------------------*/
4138 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4140 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4142 unsigned long lit = 0L;
4144 D(emitcode(";", "gencjneshort"););
4146 /* if the left side is a literal or
4147 if the right is in a pointer register and left
4149 if ((AOP_TYPE(left) == AOP_LIT) ||
4150 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4156 if(AOP_TYPE(right) == AOP_LIT)
4157 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4159 if (opIsGptr(left) || opIsGptr(right))
4161 /* We are comparing a generic pointer to something.
4162 * Exclude the generic type byte from the comparison.
4165 D(emitcode(";", "cjneshort: generic ptr special case.");)
4169 /* if the right side is a literal then anything goes */
4170 if (AOP_TYPE(right) == AOP_LIT &&
4171 AOP_TYPE(left) != AOP_DIR ) {
4173 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4175 emitcode("cjne","a,%s,%05d$",
4176 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4182 /* if the right side is in a register or in direct space or
4183 if the left is a pointer register & right is not */
4184 else if (AOP_TYPE(right) == AOP_REG ||
4185 AOP_TYPE(right) == AOP_DIR ||
4186 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4187 (IS_AOP_PREG(left) && !IS_AOP_PREG(right)))
4191 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4192 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4193 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4194 emitcode("jnz","%05d$",lbl->key+100);
4196 emitcode("cjne","a,%s,%05d$",
4197 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4202 /* right is a pointer reg need both a & b */
4204 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4206 emitcode("mov","b,%s",l);
4207 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4208 emitcode("cjne","a,b,%05d$",lbl->key+100);
4214 /*-----------------------------------------------------------------*/
4215 /* gencjne - compare and jump if not equal */
4216 /*-----------------------------------------------------------------*/
4217 static void gencjne(operand *left, operand *right, symbol *lbl)
4219 symbol *tlbl = newiTempLabel(NULL);
4221 D(emitcode(";", "gencjne"););
4223 gencjneshort(left, right, lbl);
4225 emitcode("mov","a,%s",one);
4226 emitcode("sjmp","%05d$",tlbl->key+100);
4227 emitcode("","%05d$:",lbl->key+100);
4228 emitcode("clr","a");
4229 emitcode("","%05d$:",tlbl->key+100);
4232 /*-----------------------------------------------------------------*/
4233 /* genCmpEq - generates code for equal to */
4234 /*-----------------------------------------------------------------*/
4235 static void genCmpEq (iCode *ic, iCode *ifx)
4237 operand *left, *right, *result;
4239 D(emitcode(";", "genCmpEq "););
4244 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4245 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4246 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4249 /* if literal, literal on the right or
4250 if the right is in a pointer register and left
4252 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4253 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4254 operand *t = IC_RIGHT(ic);
4255 IC_RIGHT(ic) = IC_LEFT(ic);
4259 if (ifx && /* !AOP_SIZE(result) */
4260 OP_SYMBOL(result) &&
4261 OP_SYMBOL(result)->regType == REG_CND)
4264 /* if they are both bit variables */
4265 if (AOP_TYPE(left) == AOP_CRY &&
4266 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4267 if(AOP_TYPE(right) == AOP_LIT){
4268 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4270 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4271 emitcode("cpl","c");
4272 } else if(lit == 1L) {
4273 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4275 emitcode("clr","c");
4277 /* AOP_TYPE(right) == AOP_CRY */
4279 symbol *lbl = newiTempLabel(NULL);
4280 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4281 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4282 emitcode("cpl","c");
4283 emitcode("","%05d$:",(lbl->key+100));
4285 /* if true label then we jump if condition
4287 tlbl = newiTempLabel(NULL);
4288 if ( IC_TRUE(ifx) ) {
4289 emitcode("jnc","%05d$",tlbl->key+100);
4290 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4292 emitcode("jc","%05d$",tlbl->key+100);
4293 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4295 emitcode("","%05d$:",tlbl->key+100);
4297 tlbl = newiTempLabel(NULL);
4298 gencjneshort(left, right, tlbl);
4299 if ( IC_TRUE(ifx) ) {
4300 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4301 emitcode("","%05d$:",tlbl->key+100);
4303 symbol *lbl = newiTempLabel(NULL);
4304 emitcode("sjmp","%05d$",lbl->key+100);
4305 emitcode("","%05d$:",tlbl->key+100);
4306 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4307 emitcode("","%05d$:",lbl->key+100);
4310 /* mark the icode as generated */
4313 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4314 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4318 /* if they are both bit variables */
4319 if (AOP_TYPE(left) == AOP_CRY &&
4320 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4321 if(AOP_TYPE(right) == AOP_LIT){
4322 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4324 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4325 emitcode("cpl","c");
4326 } else if(lit == 1L) {
4327 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4329 emitcode("clr","c");
4331 /* AOP_TYPE(right) == AOP_CRY */
4333 symbol *lbl = newiTempLabel(NULL);
4334 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4335 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4336 emitcode("cpl","c");
4337 emitcode("","%05d$:",(lbl->key+100));
4340 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4341 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4343 aopOp(result,ic,TRUE, FALSE);
4346 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4351 genIfxJump (ifx,"c");
4354 /* if the result is used in an arithmetic operation
4355 then put the result in place */
4358 gencjne(left,right,newiTempLabel(NULL));
4360 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4361 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4363 aopOp(result,ic,TRUE, FALSE);
4365 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4366 aopPut(AOP(result),"a",0);
4370 genIfxJump (ifx,"a");
4373 /* if the result is used in an arithmetic operation
4374 then put the result in place */
4375 if (AOP_TYPE(result) != AOP_CRY)
4377 /* leave the result in acc */
4381 freeAsmop(result,NULL,ic,TRUE);
4384 /*-----------------------------------------------------------------*/
4385 /* ifxForOp - returns the icode containing the ifx for operand */
4386 /*-----------------------------------------------------------------*/
4387 static iCode *ifxForOp ( operand *op, iCode *ic )
4389 /* if true symbol then needs to be assigned */
4390 if (IS_TRUE_SYMOP(op))
4393 /* if this has register type condition and
4394 the next instruction is ifx with the same operand
4395 and live to of the operand is upto the ifx only then */
4397 ic->next->op == IFX &&
4398 IC_COND(ic->next)->key == op->key &&
4399 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4404 /*-----------------------------------------------------------------*/
4405 /* genAndOp - for && operation */
4406 /*-----------------------------------------------------------------*/
4407 static void genAndOp (iCode *ic)
4409 operand *left,*right, *result;
4412 D(emitcode(";", "genAndOp "););
4414 /* note here that && operations that are in an
4415 if statement are taken away by backPatchLabels
4416 only those used in arthmetic operations remain */
4420 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4421 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4422 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4425 /* if both are bit variables */
4426 if (AOP_TYPE(left) == AOP_CRY &&
4427 AOP_TYPE(right) == AOP_CRY ) {
4428 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4429 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4432 tlbl = newiTempLabel(NULL);
4434 emitcode("jz","%05d$",tlbl->key+100);
4436 emitcode("","%05d$:",tlbl->key+100);
4440 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4441 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4442 freeAsmop(result,NULL,ic,TRUE);
4446 /*-----------------------------------------------------------------*/
4447 /* genOrOp - for || operation */
4448 /*-----------------------------------------------------------------*/
4449 static void genOrOp (iCode *ic)
4451 operand *left,*right, *result;
4454 D(emitcode(";", "genOrOp "););
4456 /* note here that || operations that are in an
4457 if statement are taken away by backPatchLabels
4458 only those used in arthmetic operations remain */
4462 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4463 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4464 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4467 /* if both are bit variables */
4468 if (AOP_TYPE(left) == AOP_CRY &&
4469 AOP_TYPE(right) == AOP_CRY ) {
4470 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4471 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4474 tlbl = newiTempLabel(NULL);
4476 emitcode("jnz","%05d$",tlbl->key+100);
4478 emitcode("","%05d$:",tlbl->key+100);
4482 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4483 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4484 freeAsmop(result,NULL,ic,TRUE);
4487 /*-----------------------------------------------------------------*/
4488 /* isLiteralBit - test if lit == 2^n */
4489 /*-----------------------------------------------------------------*/
4490 static int isLiteralBit(unsigned long lit)
4492 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4493 0x100L,0x200L,0x400L,0x800L,
4494 0x1000L,0x2000L,0x4000L,0x8000L,
4495 0x10000L,0x20000L,0x40000L,0x80000L,
4496 0x100000L,0x200000L,0x400000L,0x800000L,
4497 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4498 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4501 for(idx = 0; idx < 32; idx++)
4507 /*-----------------------------------------------------------------*/
4508 /* continueIfTrue - */
4509 /*-----------------------------------------------------------------*/
4510 static void continueIfTrue (iCode *ic)
4513 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4517 /*-----------------------------------------------------------------*/
4519 /*-----------------------------------------------------------------*/
4520 static void jumpIfTrue (iCode *ic)
4523 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4527 /*-----------------------------------------------------------------*/
4528 /* jmpTrueOrFalse - */
4529 /*-----------------------------------------------------------------*/
4530 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4532 // ugly but optimized by peephole
4534 symbol *nlbl = newiTempLabel(NULL);
4535 emitcode("sjmp","%05d$",nlbl->key+100);
4536 emitcode("","%05d$:",tlbl->key+100);
4537 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4538 emitcode("","%05d$:",nlbl->key+100);
4541 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4542 emitcode("","%05d$:",tlbl->key+100);
4547 /*-----------------------------------------------------------------*/
4548 /* genAnd - code for and */
4549 /*-----------------------------------------------------------------*/
4550 static void genAnd (iCode *ic, iCode *ifx)
4552 operand *left, *right, *result;
4554 unsigned long lit = 0L;
4558 D(emitcode(";", "genAnd "););
4563 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4564 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4565 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4569 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4571 AOP_TYPE(left), AOP_TYPE(right));
4572 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4574 AOP_SIZE(left), AOP_SIZE(right));
4577 /* if left is a literal & right is not then exchange them */
4578 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4579 AOP_NEEDSACC(left)) {
4580 operand *tmp = right ;
4585 /* if result = right then exchange them */
4586 if(sameRegs(AOP(result),AOP(right))){
4587 operand *tmp = right ;
4592 /* if right is bit then exchange them */
4593 if (AOP_TYPE(right) == AOP_CRY &&
4594 AOP_TYPE(left) != AOP_CRY){
4595 operand *tmp = right ;
4599 if(AOP_TYPE(right) == AOP_LIT)
4600 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4602 size = AOP_SIZE(result);
4605 // result = bit & yy;
4606 if (AOP_TYPE(left) == AOP_CRY){
4607 // c = bit & literal;
4608 if(AOP_TYPE(right) == AOP_LIT){
4610 if(size && sameRegs(AOP(result),AOP(left)))
4613 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4616 if(size && (AOP_TYPE(result) == AOP_CRY)){
4617 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4620 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4624 emitcode("clr","c");
4627 if (AOP_TYPE(right) == AOP_CRY){
4629 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4630 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4633 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4635 emitcode("rrc","a");
4636 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4644 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4645 genIfxJump(ifx, "c");
4649 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4650 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4651 if((AOP_TYPE(right) == AOP_LIT) &&
4652 (AOP_TYPE(result) == AOP_CRY) &&
4653 (AOP_TYPE(left) != AOP_CRY)){
4654 int posbit = isLiteralBit(lit);
4658 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4661 emitcode("mov","c,acc.%d",posbit&0x07);
4665 sprintf(buffer,"acc.%d",posbit&0x07);
4666 genIfxJump(ifx, buffer);
4671 symbol *tlbl = newiTempLabel(NULL);
4672 int sizel = AOP_SIZE(left);
4674 emitcode("setb","c");
4676 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4677 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4679 if((posbit = isLiteralBit(bytelit)) != 0)
4680 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4682 if(bytelit != 0x0FFL)
4683 emitcode("anl","a,%s",
4684 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4685 emitcode("jnz","%05d$",tlbl->key+100);
4690 // bit = left & literal
4692 emitcode("clr","c");
4693 emitcode("","%05d$:",tlbl->key+100);
4695 // if(left & literal)
4698 jmpTrueOrFalse(ifx, tlbl);
4706 /* if left is same as result */
4707 if(sameRegs(AOP(result),AOP(left))){
4708 for(;size--; offset++) {
4709 if(AOP_TYPE(right) == AOP_LIT){
4710 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4714 aopPut(AOP(result),zero,offset);
4716 if (IS_AOP_PREG(result)) {
4717 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4718 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4719 aopPut(AOP(result),"a",offset);
4721 emitcode("anl","%s,%s",
4722 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4723 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4725 if (AOP_TYPE(left) == AOP_ACC)
4726 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4728 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4729 if (IS_AOP_PREG(result)) {
4730 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4731 aopPut(AOP(result),"a",offset);
4734 emitcode("anl","%s,a",
4735 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4740 // left & result in different registers
4741 if(AOP_TYPE(result) == AOP_CRY){
4743 // if(size), result in bit
4744 // if(!size && ifx), conditional oper: if(left & right)
4745 symbol *tlbl = newiTempLabel(NULL);
4746 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4748 emitcode("setb","c");
4750 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4751 emitcode("anl","a,%s",
4752 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4753 emitcode("jnz","%05d$",tlbl->key+100);
4758 emitcode("","%05d$:",tlbl->key+100);
4761 jmpTrueOrFalse(ifx, tlbl);
4764 for(;(size--);offset++)
4767 // result = left & right
4768 if(AOP_TYPE(right) == AOP_LIT)
4770 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4773 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4777 else if (bytelit == 0)
4779 aopPut(AOP(result),zero,offset);
4782 D(emitcode(";", "better literal AND."););
4783 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4784 emitcode("anl", "a, %s", aopGet(AOP(right),offset,
4785 FALSE,FALSE,FALSE));
4790 // faster than result <- left, anl result,right
4791 // and better if result is SFR
4792 if (AOP_TYPE(left) == AOP_ACC)
4794 emitcode("anl","a,%s",aopGet(AOP(right),offset,
4795 FALSE,FALSE,FALSE));
4799 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4800 emitcode("anl","a,%s",
4801 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4804 aopPut(AOP(result),"a",offset);
4810 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4811 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4812 freeAsmop(result,NULL,ic,TRUE);
4815 /*-----------------------------------------------------------------*/
4816 /* genOr - code for or */
4817 /*-----------------------------------------------------------------*/
4818 static void genOr (iCode *ic, iCode *ifx)
4820 operand *left, *right, *result;
4822 unsigned long lit = 0L;
4824 D(emitcode(";", "genOr "););
4829 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4830 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4831 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4835 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4837 AOP_TYPE(left), AOP_TYPE(right));
4838 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4840 AOP_SIZE(left), AOP_SIZE(right));
4843 /* if left is a literal & right is not then exchange them */
4844 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4845 AOP_NEEDSACC(left)) {
4846 operand *tmp = right ;
4851 /* if result = right then exchange them */
4852 if(sameRegs(AOP(result),AOP(right))){
4853 operand *tmp = right ;
4858 /* if right is bit then exchange them */
4859 if (AOP_TYPE(right) == AOP_CRY &&
4860 AOP_TYPE(left) != AOP_CRY){
4861 operand *tmp = right ;
4865 if(AOP_TYPE(right) == AOP_LIT)
4866 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4868 size = AOP_SIZE(result);
4872 if (AOP_TYPE(left) == AOP_CRY){
4873 if(AOP_TYPE(right) == AOP_LIT){
4874 // c = bit & literal;
4876 // lit != 0 => result = 1
4877 if(AOP_TYPE(result) == AOP_CRY){
4879 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4881 continueIfTrue(ifx);
4884 emitcode("setb","c");
4886 // lit == 0 => result = left
4887 if(size && sameRegs(AOP(result),AOP(left)))
4889 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4892 if (AOP_TYPE(right) == AOP_CRY){
4894 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4895 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4899 symbol *tlbl = newiTempLabel(NULL);
4900 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4901 emitcode("setb","c");
4902 emitcode("jb","%s,%05d$",
4903 AOP(left)->aopu.aop_dir,tlbl->key+100);
4905 emitcode("jnz","%05d$",tlbl->key+100);
4906 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4907 jmpTrueOrFalse(ifx, tlbl);
4911 emitcode("","%05d$:",tlbl->key+100);
4920 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4921 genIfxJump(ifx, "c");
4925 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4926 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4927 if((AOP_TYPE(right) == AOP_LIT) &&
4928 (AOP_TYPE(result) == AOP_CRY) &&
4929 (AOP_TYPE(left) != AOP_CRY)){
4933 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4935 continueIfTrue(ifx);
4938 // lit = 0, result = boolean(left)
4940 emitcode("setb","c");
4943 symbol *tlbl = newiTempLabel(NULL);
4944 emitcode("jnz","%05d$",tlbl->key+100);
4946 emitcode("","%05d$:",tlbl->key+100);
4948 genIfxJump (ifx,"a");
4956 /* if left is same as result */
4957 if(sameRegs(AOP(result),AOP(left)))
4959 for(;size--; offset++)
4961 if(AOP_TYPE(right) == AOP_LIT){
4962 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4968 if (IS_AOP_PREG(left))
4970 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4971 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4972 aopPut(AOP(result),"a",offset);
4976 emitcode("orl","%s,%s",
4977 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4978 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4984 if (AOP_TYPE(left) == AOP_ACC)
4986 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4990 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4991 if (IS_AOP_PREG(left))
4993 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4994 aopPut(AOP(result),"a",offset);
4998 emitcode("orl","%s,a",
4999 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5007 // left & result in different registers
5008 if(AOP_TYPE(result) == AOP_CRY)
5011 // if(size), result in bit
5012 // if(!size && ifx), conditional oper: if(left | right)
5013 symbol *tlbl = newiTempLabel(NULL);
5014 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5016 emitcode("setb","c");
5018 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5019 emitcode("orl","a,%s",
5020 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5021 emitcode("jnz","%05d$",tlbl->key+100);
5026 emitcode("","%05d$:",tlbl->key+100);
5029 jmpTrueOrFalse(ifx, tlbl);
5033 for(;(size--);offset++)
5036 // result = left & right
5037 if(AOP_TYPE(right) == AOP_LIT)
5039 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5042 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5046 D(emitcode(";", "better literal OR."););
5047 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5048 emitcode("orl", "a, %s", aopGet(AOP(right),offset,
5049 FALSE,FALSE,FALSE));
5054 // faster than result <- left, anl result,right
5055 // and better if result is SFR
5056 if (AOP_TYPE(left) == AOP_ACC)
5058 emitcode("orl","a,%s",aopGet(AOP(right),offset,
5059 FALSE,FALSE,FALSE));
5063 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5064 emitcode("orl","a,%s",
5065 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5068 aopPut(AOP(result),"a",offset);
5074 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5075 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5076 freeAsmop(result,NULL,ic,TRUE);
5079 /*-----------------------------------------------------------------*/
5080 /* genXor - code for xclusive or */
5081 /*-----------------------------------------------------------------*/
5082 static void genXor (iCode *ic, iCode *ifx)
5084 operand *left, *right, *result;
5086 unsigned long lit = 0L;
5088 D(emitcode(";", "genXor "););
5093 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
5094 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
5095 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
5099 emitcode("","; Type res[%d] = l[%d]&r[%d]",
5101 AOP_TYPE(left), AOP_TYPE(right));
5102 emitcode("","; Size res[%d] = l[%d]&r[%d]",
5104 AOP_SIZE(left), AOP_SIZE(right));
5107 /* if left is a literal & right is not ||
5108 if left needs acc & right does not */
5109 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5110 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5111 operand *tmp = right ;
5116 /* if result = right then exchange them */
5117 if(sameRegs(AOP(result),AOP(right))){
5118 operand *tmp = right ;
5123 /* if right is bit then exchange them */
5124 if (AOP_TYPE(right) == AOP_CRY &&
5125 AOP_TYPE(left) != AOP_CRY){
5126 operand *tmp = right ;
5130 if(AOP_TYPE(right) == AOP_LIT)
5131 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5133 size = AOP_SIZE(result);
5137 if (AOP_TYPE(left) == AOP_CRY){
5138 if(AOP_TYPE(right) == AOP_LIT){
5139 // c = bit & literal;
5141 // lit>>1 != 0 => result = 1
5142 if(AOP_TYPE(result) == AOP_CRY){
5144 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5146 continueIfTrue(ifx);
5149 emitcode("setb","c");
5153 // lit == 0, result = left
5154 if(size && sameRegs(AOP(result),AOP(left)))
5156 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5158 // lit == 1, result = not(left)
5159 if(size && sameRegs(AOP(result),AOP(left))){
5160 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5163 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5164 emitcode("cpl","c");
5171 symbol *tlbl = newiTempLabel(NULL);
5172 if (AOP_TYPE(right) == AOP_CRY){
5174 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5177 int sizer = AOP_SIZE(right);
5179 // if val>>1 != 0, result = 1
5180 emitcode("setb","c");
5182 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5184 // test the msb of the lsb
5185 emitcode("anl","a,#0xfe");
5186 emitcode("jnz","%05d$",tlbl->key+100);
5190 emitcode("rrc","a");
5192 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5193 emitcode("cpl","c");
5194 emitcode("","%05d$:",(tlbl->key+100));
5201 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5202 genIfxJump(ifx, "c");
5206 if(sameRegs(AOP(result),AOP(left))){
5207 /* if left is same as result */
5208 for(;size--; offset++) {
5209 if(AOP_TYPE(right) == AOP_LIT){
5210 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5213 if (IS_AOP_PREG(left)) {
5214 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5215 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5216 aopPut(AOP(result),"a",offset);
5218 emitcode("xrl","%s,%s",
5219 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5220 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5222 if (AOP_TYPE(left) == AOP_ACC)
5223 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5225 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5226 if (IS_AOP_PREG(left)) {
5227 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5228 aopPut(AOP(result),"a",offset);
5230 emitcode("xrl","%s,a",
5231 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5236 // left & result in different registers
5237 if(AOP_TYPE(result) == AOP_CRY){
5239 // if(size), result in bit
5240 // if(!size && ifx), conditional oper: if(left ^ right)
5241 symbol *tlbl = newiTempLabel(NULL);
5242 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5244 emitcode("setb","c");
5246 if((AOP_TYPE(right) == AOP_LIT) &&
5247 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5248 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5250 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5251 emitcode("xrl","a,%s",
5252 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5254 emitcode("jnz","%05d$",tlbl->key+100);
5259 emitcode("","%05d$:",tlbl->key+100);
5262 jmpTrueOrFalse(ifx, tlbl);
5263 } else for(;(size--);offset++)
5266 // result = left & right
5267 if(AOP_TYPE(right) == AOP_LIT)
5269 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5272 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5276 D(emitcode(";", "better literal XOR."););
5277 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5278 emitcode("xrl", "a, %s", aopGet(AOP(right),offset,
5279 FALSE,FALSE,FALSE));
5283 // faster than result <- left, anl result,right
5284 // and better if result is SFR
5285 if (AOP_TYPE(left) == AOP_ACC)
5287 emitcode("xrl","a,%s",aopGet(AOP(right),offset,
5288 FALSE,FALSE,FALSE));
5292 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5293 emitcode("xrl","a,%s",
5294 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5297 aopPut(AOP(result),"a",offset);
5302 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5303 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5304 freeAsmop(result,NULL,ic,TRUE);
5307 /*-----------------------------------------------------------------*/
5308 /* genInline - write the inline code out */
5309 /*-----------------------------------------------------------------*/
5310 static void genInline (iCode *ic)
5312 char buffer[MAX_INLINEASM];
5316 D(emitcode(";", "genInline "););
5318 _G.inLine += (!options.asmpeep);
5319 strcpy(buffer,IC_INLINE(ic));
5321 /* emit each line as a code */
5340 /* emitcode("",buffer); */
5341 _G.inLine -= (!options.asmpeep);
5344 /*-----------------------------------------------------------------*/
5345 /* genRRC - rotate right with carry */
5346 /*-----------------------------------------------------------------*/
5347 static void genRRC (iCode *ic)
5349 operand *left , *result ;
5350 int size, offset = 0;
5353 D(emitcode(";", "genRRC "););
5355 /* rotate right with carry */
5357 result=IC_RESULT(ic);
5358 aopOp (left,ic,FALSE, FALSE);
5359 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5361 /* move it to the result */
5362 size = AOP_SIZE(result);
5366 _startLazyDPSEvaluation();
5368 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5370 emitcode("rrc","a");
5371 if (AOP_SIZE(result) > 1)
5372 aopPut(AOP(result),"a",offset--);
5374 _endLazyDPSEvaluation();
5376 /* now we need to put the carry into the
5377 highest order byte of the result */
5378 if (AOP_SIZE(result) > 1) {
5379 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5382 emitcode("mov","acc.7,c");
5383 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5384 freeAsmop(left,NULL,ic,TRUE);
5385 freeAsmop(result,NULL,ic,TRUE);
5388 /*-----------------------------------------------------------------*/
5389 /* genRLC - generate code for rotate left with carry */
5390 /*-----------------------------------------------------------------*/
5391 static void genRLC (iCode *ic)
5393 operand *left , *result ;
5394 int size, offset = 0;
5397 D(emitcode(";", "genRLC "););
5399 /* rotate right with carry */
5401 result=IC_RESULT(ic);
5402 aopOp (left,ic,FALSE, FALSE);
5403 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5405 /* move it to the result */
5406 size = AOP_SIZE(result);
5409 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5411 emitcode("add","a,acc");
5412 if (AOP_SIZE(result) > 1)
5414 aopPut(AOP(result),"a",offset++);
5417 _startLazyDPSEvaluation();
5419 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5421 emitcode("rlc","a");
5422 if (AOP_SIZE(result) > 1)
5423 aopPut(AOP(result),"a",offset++);
5425 _endLazyDPSEvaluation();
5427 /* now we need to put the carry into the
5428 highest order byte of the result */
5429 if (AOP_SIZE(result) > 1) {
5430 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5433 emitcode("mov","acc.0,c");
5434 aopPut(AOP(result),"a",0);
5435 freeAsmop(left,NULL,ic,TRUE);
5436 freeAsmop(result,NULL,ic,TRUE);
5439 /*-----------------------------------------------------------------*/
5440 /* genGetHbit - generates code get highest order bit */
5441 /*-----------------------------------------------------------------*/
5442 static void genGetHbit (iCode *ic)
5444 operand *left, *result;
5446 result=IC_RESULT(ic);
5447 aopOp (left,ic,FALSE, FALSE);
5448 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5450 D(emitcode(";", "genGetHbit "););
5452 /* get the highest order byte into a */
5453 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5454 if(AOP_TYPE(result) == AOP_CRY){
5455 emitcode("rlc","a");
5460 emitcode("anl","a,#0x01");
5465 freeAsmop(left,NULL,ic,TRUE);
5466 freeAsmop(result,NULL,ic,TRUE);
5469 /*-----------------------------------------------------------------*/
5470 /* AccRol - rotate left accumulator by known count */
5471 /*-----------------------------------------------------------------*/
5472 static void AccRol (int shCount)
5474 shCount &= 0x0007; // shCount : 0..7
5486 emitcode("swap","a");
5490 emitcode("swap","a");
5493 emitcode("swap","a");
5506 /*-----------------------------------------------------------------*/
5507 /* AccLsh - left shift accumulator by known count */
5508 /*-----------------------------------------------------------------*/
5509 static void AccLsh (int shCount)
5513 emitcode("add","a,acc");
5516 emitcode("add","a,acc");
5517 emitcode("add","a,acc");
5519 /* rotate left accumulator */
5521 /* and kill the lower order bits */
5522 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5527 /*-----------------------------------------------------------------*/
5528 /* AccRsh - right shift accumulator by known count */
5529 /*-----------------------------------------------------------------*/
5530 static void AccRsh (int shCount)
5535 emitcode("rrc","a");
5537 /* rotate right accumulator */
5538 AccRol(8 - shCount);
5539 /* and kill the higher order bits */
5540 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5547 /*-----------------------------------------------------------------*/
5548 /* AccSRsh - signed right shift accumulator by known count */
5549 /*-----------------------------------------------------------------*/
5550 static void AccSRsh (int shCount)
5555 emitcode("mov","c,acc.7");
5556 emitcode("rrc","a");
5557 } else if(shCount == 2){
5558 emitcode("mov","c,acc.7");
5559 emitcode("rrc","a");
5560 emitcode("mov","c,acc.7");
5561 emitcode("rrc","a");
5563 tlbl = newiTempLabel(NULL);
5564 /* rotate right accumulator */
5565 AccRol(8 - shCount);
5566 /* and kill the higher order bits */
5567 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5568 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5569 emitcode("orl","a,#0x%02x",
5570 (unsigned char)~SRMask[shCount]);
5571 emitcode("","%05d$:",tlbl->key+100);
5579 /*-----------------------------------------------------------------*/
5580 /* shiftR1Left2Result - shift right one byte from left to result */
5581 /*-----------------------------------------------------------------*/
5582 static void shiftR1Left2Result (operand *left, int offl,
5583 operand *result, int offr,
5584 int shCount, int sign)
5586 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5587 /* shift right accumulator */
5592 aopPut(AOP(result),"a",offr);
5598 /*-----------------------------------------------------------------*/
5599 /* shiftL1Left2Result - shift left one byte from left to result */
5600 /*-----------------------------------------------------------------*/
5601 static void shiftL1Left2Result (operand *left, int offl,
5602 operand *result, int offr, int shCount)
5605 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5607 /* shift left accumulator */
5609 aopPut(AOP(result),"a",offr);
5615 /*-----------------------------------------------------------------*/
5616 /* movLeft2Result - move byte from left to result */
5617 /*-----------------------------------------------------------------*/
5618 static void movLeft2Result (operand *left, int offl,
5619 operand *result, int offr, int sign)
5622 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5623 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5625 if (*l == '@' && (IS_AOP_PREG(result))) {
5626 emitcode("mov","a,%s",l);
5627 aopPut(AOP(result),"a",offr);
5630 aopPut(AOP(result),l,offr);
5632 /* MSB sign in acc.7 ! */
5633 if(getDataSize(left) == offl+1){
5634 emitcode("mov","a,%s",l);
5635 aopPut(AOP(result),"a",offr);
5645 /*-----------------------------------------------------------------*/
5646 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5647 /*-----------------------------------------------------------------*/
5648 static void AccAXRrl1 (char *x)
5650 emitcode("rrc","a");
5651 emitcode("xch","a,%s", x);
5652 emitcode("rrc","a");
5653 emitcode("xch","a,%s", x);
5659 /*-----------------------------------------------------------------*/
5660 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5661 /*-----------------------------------------------------------------*/
5662 static void AccAXLrl1 (char *x)
5664 emitcode("xch","a,%s",x);
5665 emitcode("rlc","a");
5666 emitcode("xch","a,%s",x);
5667 emitcode("rlc","a");
5673 /*-----------------------------------------------------------------*/
5674 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5675 /*-----------------------------------------------------------------*/
5676 static void AccAXLsh1 (char *x)
5678 emitcode("xch","a,%s",x);
5679 emitcode("add","a,acc");
5680 emitcode("xch","a,%s",x);
5681 emitcode("rlc","a");
5687 /*-----------------------------------------------------------------*/
5688 /* AccAXLsh - left shift a:x by known count (0..7) */
5689 /*-----------------------------------------------------------------*/
5690 static void AccAXLsh (char *x, int shCount)
5704 case 5 : // AAAAABBB:CCCCCDDD
5705 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5706 emitcode("anl","a,#0x%02x",
5707 SLMask[shCount]); // BBB00000:CCCCCDDD
5708 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5709 AccRol(shCount); // DDDCCCCC:BBB00000
5710 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5711 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5712 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5713 emitcode("anl","a,#0x%02x",
5714 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5715 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5716 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5718 case 6 : // AAAAAABB:CCCCCCDD
5719 emitcode("anl","a,#0x%02x",
5720 SRMask[shCount]); // 000000BB:CCCCCCDD
5721 emitcode("mov","c,acc.0"); // c = B
5722 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5723 AccAXRrl1(x); // BCCCCCCD:D000000B
5724 AccAXRrl1(x); // BBCCCCCC:DD000000
5726 case 7 : // a:x <<= 7
5727 emitcode("anl","a,#0x%02x",
5728 SRMask[shCount]); // 0000000B:CCCCCCCD
5729 emitcode("mov","c,acc.0"); // c = B
5730 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5731 AccAXRrl1(x); // BCCCCCCC:D0000000
5741 /*-----------------------------------------------------------------*/
5742 /* AccAXRsh - right shift a:x known count (0..7) */
5743 /*-----------------------------------------------------------------*/
5744 static void AccAXRsh (char *x, int shCount)
5751 AccAXRrl1(x); // 0->a:x
5755 AccAXRrl1(x); // 0->a:x
5757 AccAXRrl1(x); // 0->a:x
5761 case 5 : // AAAAABBB:CCCCCDDD = a:x
5762 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5763 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5764 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5765 emitcode("anl","a,#0x%02x",
5766 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5767 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5768 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5769 emitcode("anl","a,#0x%02x",
5770 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5771 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5772 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5773 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5775 case 6 : // AABBBBBB:CCDDDDDD
5776 emitcode("mov","c,acc.7");
5777 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5778 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5779 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5780 emitcode("anl","a,#0x%02x",
5781 SRMask[shCount]); // 000000AA:BBBBBBCC
5783 case 7 : // ABBBBBBB:CDDDDDDD
5784 emitcode("mov","c,acc.7"); // c = A
5785 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5786 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5787 emitcode("anl","a,#0x%02x",
5788 SRMask[shCount]); // 0000000A:BBBBBBBC
5798 /*-----------------------------------------------------------------*/
5799 /* AccAXRshS - right shift signed a:x known count (0..7) */
5800 /*-----------------------------------------------------------------*/
5801 static void AccAXRshS (char *x, int shCount)
5808 emitcode("mov","c,acc.7");
5809 AccAXRrl1(x); // s->a:x
5812 emitcode("mov","c,acc.7");
5813 AccAXRrl1(x); // s->a:x
5814 emitcode("mov","c,acc.7");
5815 AccAXRrl1(x); // s->a:x
5819 case 5 : // AAAAABBB:CCCCCDDD = a:x
5820 tlbl = newiTempLabel(NULL);
5821 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5822 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5823 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5824 emitcode("anl","a,#0x%02x",
5825 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5826 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5827 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5828 emitcode("anl","a,#0x%02x",
5829 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5830 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5831 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5832 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5833 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5834 emitcode("orl","a,#0x%02x",
5835 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5836 emitcode("","%05d$:",tlbl->key+100);
5837 break; // SSSSAAAA:BBBCCCCC
5838 case 6 : // AABBBBBB:CCDDDDDD
5839 tlbl = newiTempLabel(NULL);
5840 emitcode("mov","c,acc.7");
5841 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5842 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5843 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5844 emitcode("anl","a,#0x%02x",
5845 SRMask[shCount]); // 000000AA:BBBBBBCC
5846 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5847 emitcode("orl","a,#0x%02x",
5848 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5849 emitcode("","%05d$:",tlbl->key+100);
5851 case 7 : // ABBBBBBB:CDDDDDDD
5852 tlbl = newiTempLabel(NULL);
5853 emitcode("mov","c,acc.7"); // c = A
5854 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5855 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5856 emitcode("anl","a,#0x%02x",
5857 SRMask[shCount]); // 0000000A:BBBBBBBC
5858 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5859 emitcode("orl","a,#0x%02x",
5860 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5861 emitcode("","%05d$:",tlbl->key+100);
5871 /*-----------------------------------------------------------------*/
5872 /* shiftL2Left2Result - shift left two bytes from left to result */
5873 /*-----------------------------------------------------------------*/
5874 static void shiftL2Left2Result (operand *left, int offl,
5875 operand *result, int offr, int shCount)
5877 if(sameRegs(AOP(result), AOP(left)) &&
5878 ((offl + MSB16) == offr)){
5879 /* don't crash result[offr] */
5880 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5881 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5883 movLeft2Result(left,offl, result, offr, 0);
5884 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5886 /* ax << shCount (x = lsb(result))*/
5887 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5888 aopPut(AOP(result),"a",offr+MSB16);
5894 /*-----------------------------------------------------------------*/
5895 /* shiftR2Left2Result - shift right two bytes from left to result */
5896 /*-----------------------------------------------------------------*/
5897 static void shiftR2Left2Result (operand *left, int offl,
5898 operand *result, int offr,
5899 int shCount, int sign)
5901 if(sameRegs(AOP(result), AOP(left)) &&
5902 ((offl + MSB16) == offr)){
5903 /* don't crash result[offr] */
5904 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5905 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5907 movLeft2Result(left,offl, result, offr, 0);
5908 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5910 /* a:x >> shCount (x = lsb(result))*/
5912 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5914 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5915 if(getDataSize(result) > 1)
5916 aopPut(AOP(result),"a",offr+MSB16);
5922 /*-----------------------------------------------------------------*/
5923 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5924 /*-----------------------------------------------------------------*/
5925 static void shiftLLeftOrResult (operand *left, int offl,
5926 operand *result, int offr, int shCount)
5928 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5929 /* shift left accumulator */
5931 /* or with result */
5932 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5933 /* back to result */
5934 aopPut(AOP(result),"a",offr);
5940 /*-----------------------------------------------------------------*/
5941 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5942 /*-----------------------------------------------------------------*/
5943 static void shiftRLeftOrResult (operand *left, int offl,
5944 operand *result, int offr, int shCount)
5946 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5947 /* shift right accumulator */
5949 /* or with result */
5950 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5951 /* back to result */
5952 aopPut(AOP(result),"a",offr);
5958 /*-----------------------------------------------------------------*/
5959 /* genlshOne - left shift a one byte quantity by known count */
5960 /*-----------------------------------------------------------------*/
5961 static void genlshOne (operand *result, operand *left, int shCount)
5963 D(emitcode(";", "genlshOne "););
5964 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5970 /*-----------------------------------------------------------------*/
5971 /* genlshTwo - left shift two bytes by known amount != 0 */
5972 /*-----------------------------------------------------------------*/
5973 static void genlshTwo (operand *result,operand *left, int shCount)
5977 D(emitcode(";", "genlshTwo "););
5979 size = getDataSize(result);
5981 /* if shCount >= 8 */
5987 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5989 movLeft2Result(left, LSB, result, MSB16, 0);
5991 aopPut(AOP(result),zero,LSB);
5994 /* 1 <= shCount <= 7 */
5997 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5999 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6006 /*-----------------------------------------------------------------*/
6007 /* shiftLLong - shift left one long from left to result */
6008 /* offl = LSB or MSB16 */
6009 /*-----------------------------------------------------------------*/
6010 static void shiftLLong (operand *left, operand *result, int offr )
6013 int size = AOP_SIZE(result);
6015 if(size >= LSB+offr){
6016 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
6018 emitcode("add","a,acc");
6019 if (sameRegs(AOP(left),AOP(result)) &&
6020 size >= MSB16+offr && offr != LSB )
6021 emitcode("xch","a,%s",
6022 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
6024 aopPut(AOP(result),"a",LSB+offr);
6027 if(size >= MSB16+offr){
6028 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6029 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
6032 emitcode("rlc","a");
6033 if (sameRegs(AOP(left),AOP(result)) &&
6034 size >= MSB24+offr && offr != LSB)
6035 emitcode("xch","a,%s",
6036 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
6038 aopPut(AOP(result),"a",MSB16+offr);
6041 if(size >= MSB24+offr){
6042 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6043 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
6046 emitcode("rlc","a");
6047 if (sameRegs(AOP(left),AOP(result)) &&
6048 size >= MSB32+offr && offr != LSB )
6049 emitcode("xch","a,%s",
6050 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
6052 aopPut(AOP(result),"a",MSB24+offr);
6055 if(size > MSB32+offr){
6056 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6057 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
6060 emitcode("rlc","a");
6061 aopPut(AOP(result),"a",MSB32+offr);
6064 aopPut(AOP(result),zero,LSB);
6070 /*-----------------------------------------------------------------*/
6071 /* genlshFour - shift four byte by a known amount != 0 */
6072 /*-----------------------------------------------------------------*/
6073 static void genlshFour (operand *result, operand *left, int shCount)
6077 D(emitcode(";", "genlshFour "););
6079 size = AOP_SIZE(result);
6081 /* if shifting more that 3 bytes */
6082 if (shCount >= 24 ) {
6085 /* lowest order of left goes to the highest
6086 order of the destination */
6087 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6089 movLeft2Result(left, LSB, result, MSB32, 0);
6090 aopPut(AOP(result),zero,LSB);
6091 aopPut(AOP(result),zero,MSB16);
6092 aopPut(AOP(result),zero,MSB32);
6096 /* more than two bytes */
6097 else if ( shCount >= 16 ) {
6098 /* lower order two bytes goes to higher order two bytes */
6100 /* if some more remaining */
6102 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6104 movLeft2Result(left, MSB16, result, MSB32, 0);
6105 movLeft2Result(left, LSB, result, MSB24, 0);
6107 aopPut(AOP(result),zero,MSB16);
6108 aopPut(AOP(result),zero,LSB);
6112 /* if more than 1 byte */
6113 else if ( shCount >= 8 ) {
6114 /* lower order three bytes goes to higher order three bytes */
6118 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6120 movLeft2Result(left, LSB, result, MSB16, 0);
6122 else{ /* size = 4 */
6124 movLeft2Result(left, MSB24, result, MSB32, 0);
6125 movLeft2Result(left, MSB16, result, MSB24, 0);
6126 movLeft2Result(left, LSB, result, MSB16, 0);
6127 aopPut(AOP(result),zero,LSB);
6129 else if(shCount == 1)
6130 shiftLLong(left, result, MSB16);
6132 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6133 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6134 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6135 aopPut(AOP(result),zero,LSB);
6140 /* 1 <= shCount <= 7 */
6141 else if(shCount <= 2){
6142 shiftLLong(left, result, LSB);
6144 shiftLLong(result, result, LSB);
6146 /* 3 <= shCount <= 7, optimize */
6148 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6149 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6150 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6157 /*-----------------------------------------------------------------*/
6158 /* genLeftShiftLiteral - left shifting by known count */
6159 /*-----------------------------------------------------------------*/
6160 static void genLeftShiftLiteral (operand *left,
6165 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6168 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
6170 freeAsmop(right,NULL,ic,TRUE);
6172 aopOp(left,ic,FALSE, FALSE);
6173 aopOp(result,ic,FALSE, TRUE);
6175 size = getSize(operandType(result));
6178 emitcode("; shift left ","result %d, left %d",size,
6182 /* I suppose that the left size >= result size */
6185 movLeft2Result(left, size, result, size, 0);
6189 else if(shCount >= (size * 8))
6191 aopPut(AOP(result),zero,size);
6195 genlshOne (result,left,shCount);
6199 case 3: /* bug: this is for generic pointers, I bet. */
6200 genlshTwo (result,left,shCount);
6204 genlshFour (result,left,shCount);
6208 freeAsmop(left,NULL,ic,TRUE);
6209 freeAsmop(result,NULL,ic,TRUE);
6213 /*-----------------------------------------------------------------*/
6214 /* genLeftShift - generates code for left shifting */
6215 /*-----------------------------------------------------------------*/
6216 static void genLeftShift (iCode *ic)
6218 operand *left,*right, *result;
6221 symbol *tlbl , *tlbl1;
6223 D(emitcode(";", "genLeftShift "););
6225 right = IC_RIGHT(ic);
6227 result = IC_RESULT(ic);
6229 aopOp(right,ic,FALSE, FALSE);
6232 /* if the shift count is known then do it
6233 as efficiently as possible */
6234 if (AOP_TYPE(right) == AOP_LIT) {
6235 genLeftShiftLiteral (left,right,result,ic);
6240 /* shift count is unknown then we have to form
6241 a loop get the loop count in B : Note: we take
6242 only the lower order byte since shifting
6243 more that 32 bits make no sense anyway, ( the
6244 largest size of an object can be only 32 bits ) */
6246 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6247 emitcode("inc","b");
6248 freeAsmop (right,NULL,ic,TRUE);
6249 aopOp(left,ic,FALSE, FALSE);
6250 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6252 /* now move the left to the result if they are not the
6254 if (!sameRegs(AOP(left),AOP(result)) &&
6255 AOP_SIZE(result) > 1) {
6257 size = AOP_SIZE(result);
6259 _startLazyDPSEvaluation();
6261 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6262 if (*l == '@' && (IS_AOP_PREG(result))) {
6264 emitcode("mov","a,%s",l);
6265 aopPut(AOP(result),"a",offset);
6267 aopPut(AOP(result),l,offset);
6270 _endLazyDPSEvaluation();
6273 tlbl = newiTempLabel(NULL);
6274 size = AOP_SIZE(result);
6276 tlbl1 = newiTempLabel(NULL);
6278 /* if it is only one byte then */
6280 symbol *tlbl1 = newiTempLabel(NULL);
6282 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6284 emitcode("sjmp","%05d$",tlbl1->key+100);
6285 emitcode("","%05d$:",tlbl->key+100);
6286 emitcode("add","a,acc");
6287 emitcode("","%05d$:",tlbl1->key+100);
6288 emitcode("djnz","b,%05d$",tlbl->key+100);
6289 aopPut(AOP(result),"a",0);
6293 reAdjustPreg(AOP(result));
6295 emitcode("sjmp","%05d$",tlbl1->key+100);
6296 emitcode("","%05d$:",tlbl->key+100);
6297 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6299 emitcode("add","a,acc");
6300 aopPut(AOP(result),"a",offset++);
6301 _startLazyDPSEvaluation();
6303 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6305 emitcode("rlc","a");
6306 aopPut(AOP(result),"a",offset++);
6308 _endLazyDPSEvaluation();
6309 reAdjustPreg(AOP(result));
6311 emitcode("","%05d$:",tlbl1->key+100);
6312 emitcode("djnz","b,%05d$",tlbl->key+100);
6314 freeAsmop(left,NULL,ic,TRUE);
6315 freeAsmop(result,NULL,ic,TRUE);
6320 /*-----------------------------------------------------------------*/
6321 /* genrshOne - right shift a one byte quantity by known count */
6322 /*-----------------------------------------------------------------*/
6323 static void genrshOne (operand *result, operand *left,
6324 int shCount, int sign)
6326 D(emitcode(";", "genrshOne"););
6327 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6333 /*-----------------------------------------------------------------*/
6334 /* genrshTwo - right shift two bytes by known amount != 0 */
6335 /*-----------------------------------------------------------------*/
6336 static void genrshTwo (operand *result,operand *left,
6337 int shCount, int sign)
6339 D(emitcode(";", "genrshTwo"););
6341 /* if shCount >= 8 */
6345 shiftR1Left2Result(left, MSB16, result, LSB,
6348 movLeft2Result(left, MSB16, result, LSB, sign);
6349 addSign(result, MSB16, sign);
6352 /* 1 <= shCount <= 7 */
6354 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6360 /*-----------------------------------------------------------------*/
6361 /* shiftRLong - shift right one long from left to result */
6362 /* offl = LSB or MSB16 */
6363 /*-----------------------------------------------------------------*/
6364 static void shiftRLong (operand *left, int offl,
6365 operand *result, int sign)
6368 emitcode("clr","c");
6369 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6371 emitcode("mov","c,acc.7");
6372 emitcode("rrc","a");
6373 aopPut(AOP(result),"a",MSB32-offl);
6375 /* add sign of "a" */
6376 addSign(result, MSB32, sign);
6378 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6379 emitcode("rrc","a");
6380 aopPut(AOP(result),"a",MSB24-offl);
6382 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6383 emitcode("rrc","a");
6384 aopPut(AOP(result),"a",MSB16-offl);
6387 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6388 emitcode("rrc","a");
6389 aopPut(AOP(result),"a",LSB);
6396 /*-----------------------------------------------------------------*/
6397 /* genrshFour - shift four byte by a known amount != 0 */
6398 /*-----------------------------------------------------------------*/
6399 static void genrshFour (operand *result, operand *left,
6400 int shCount, int sign)
6402 D(emitcode(";", "genrshFour"););
6404 /* if shifting more that 3 bytes */
6405 if(shCount >= 24 ) {
6408 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6410 movLeft2Result(left, MSB32, result, LSB, sign);
6411 addSign(result, MSB16, sign);
6413 else if(shCount >= 16){
6416 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6418 movLeft2Result(left, MSB24, result, LSB, 0);
6419 movLeft2Result(left, MSB32, result, MSB16, sign);
6421 addSign(result, MSB24, sign);
6423 else if(shCount >= 8){
6426 shiftRLong(left, MSB16, result, sign);
6427 else if(shCount == 0){
6428 movLeft2Result(left, MSB16, result, LSB, 0);
6429 movLeft2Result(left, MSB24, result, MSB16, 0);
6430 movLeft2Result(left, MSB32, result, MSB24, sign);
6431 addSign(result, MSB32, sign);
6434 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6435 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6436 /* the last shift is signed */
6437 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6438 addSign(result, MSB32, sign);
6441 else{ /* 1 <= shCount <= 7 */
6443 shiftRLong(left, LSB, result, sign);
6445 shiftRLong(result, LSB, result, sign);
6448 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6449 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6450 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6458 /*-----------------------------------------------------------------*/
6459 /* genRightShiftLiteral - right shifting by known count */
6460 /*-----------------------------------------------------------------*/
6461 static void genRightShiftLiteral (operand *left,
6467 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6470 D(emitcode(";", "genRightShiftLiteral"););
6472 freeAsmop(right,NULL,ic,TRUE);
6474 aopOp(left,ic,FALSE, FALSE);
6475 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6478 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6482 size = getDataSize(left);
6483 /* test the LEFT size !!! */
6485 /* I suppose that the left size >= result size */
6487 size = getDataSize(result);
6489 movLeft2Result(left, size, result, size, 0);
6492 else if(shCount >= (size * 8)){
6494 /* get sign in acc.7 */
6495 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6496 addSign(result, LSB, sign);
6500 genrshOne (result,left,shCount,sign);
6504 genrshTwo (result,left,shCount,sign);
6508 genrshFour (result,left,shCount,sign);
6514 freeAsmop(left,NULL,ic,TRUE);
6515 freeAsmop(result,NULL,ic,TRUE);
6520 /*-----------------------------------------------------------------*/
6521 /* genSignedRightShift - right shift of signed number */
6522 /*-----------------------------------------------------------------*/
6523 static void genSignedRightShift (iCode *ic)
6525 operand *right, *left, *result;
6528 symbol *tlbl, *tlbl1 ;
6530 D(emitcode(";", "genSignedRightShift "););
6532 /* we do it the hard way put the shift count in b
6533 and loop thru preserving the sign */
6535 right = IC_RIGHT(ic);
6537 result = IC_RESULT(ic);
6539 aopOp(right,ic,FALSE, FALSE);
6542 if ( AOP_TYPE(right) == AOP_LIT) {
6543 genRightShiftLiteral (left,right,result,ic,1);
6547 /* shift count is unknown then we have to form
6548 a loop get the loop count in B : Note: we take
6549 only the lower order byte since shifting
6550 more that 32 bits make no sense anyway, ( the
6551 largest size of an object can be only 32 bits ) */
6553 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6554 emitcode("inc","b");
6555 freeAsmop (right,NULL,ic,TRUE);
6556 aopOp(left,ic,FALSE, FALSE);
6557 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6559 /* now move the left to the result if they are not the
6561 if (!sameRegs(AOP(left),AOP(result)) &&
6562 AOP_SIZE(result) > 1) {
6564 size = AOP_SIZE(result);
6566 _startLazyDPSEvaluation();
6568 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6569 if (*l == '@' && IS_AOP_PREG(result)) {
6571 emitcode("mov","a,%s",l);
6572 aopPut(AOP(result),"a",offset);
6574 aopPut(AOP(result),l,offset);
6577 _endLazyDPSEvaluation();
6580 /* mov the highest order bit to OVR */
6581 tlbl = newiTempLabel(NULL);
6582 tlbl1= newiTempLabel(NULL);
6584 size = AOP_SIZE(result);
6586 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6587 emitcode("rlc","a");
6588 emitcode("mov","ov,c");
6589 /* if it is only one byte then */
6591 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6593 emitcode("sjmp","%05d$",tlbl1->key+100);
6594 emitcode("","%05d$:",tlbl->key+100);
6595 emitcode("mov","c,ov");
6596 emitcode("rrc","a");
6597 emitcode("","%05d$:",tlbl1->key+100);
6598 emitcode("djnz","b,%05d$",tlbl->key+100);
6599 aopPut(AOP(result),"a",0);
6603 reAdjustPreg(AOP(result));
6604 emitcode("sjmp","%05d$",tlbl1->key+100);
6605 emitcode("","%05d$:",tlbl->key+100);
6606 emitcode("mov","c,ov");
6607 _startLazyDPSEvaluation();
6609 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6611 emitcode("rrc","a");
6612 aopPut(AOP(result),"a",offset--);
6614 _endLazyDPSEvaluation();
6615 reAdjustPreg(AOP(result));
6616 emitcode("","%05d$:",tlbl1->key+100);
6617 emitcode("djnz","b,%05d$",tlbl->key+100);
6620 freeAsmop(left,NULL,ic,TRUE);
6621 freeAsmop(result,NULL,ic,TRUE);
6624 /*-----------------------------------------------------------------*/
6625 /* genRightShift - generate code for right shifting */
6626 /*-----------------------------------------------------------------*/
6627 static void genRightShift (iCode *ic)
6629 operand *right, *left, *result;
6633 symbol *tlbl, *tlbl1 ;
6635 D(emitcode(";", "genRightShift "););
6637 /* if signed then we do it the hard way preserve the
6638 sign bit moving it inwards */
6639 retype = getSpec(operandType(IC_RESULT(ic)));
6641 if (!SPEC_USIGN(retype)) {
6642 genSignedRightShift (ic);
6646 /* signed & unsigned types are treated the same : i.e. the
6647 signed is NOT propagated inwards : quoting from the
6648 ANSI - standard : "for E1 >> E2, is equivalent to division
6649 by 2**E2 if unsigned or if it has a non-negative value,
6650 otherwise the result is implementation defined ", MY definition
6651 is that the sign does not get propagated */
6653 right = IC_RIGHT(ic);
6655 result = IC_RESULT(ic);
6657 aopOp(right,ic,FALSE, FALSE);
6660 /* if the shift count is known then do it
6661 as efficiently as possible */
6662 if (AOP_TYPE(right) == AOP_LIT) {
6663 genRightShiftLiteral (left,right,result,ic, 0);
6668 /* shift count is unknown then we have to form
6669 a loop get the loop count in B : Note: we take
6670 only the lower order byte since shifting
6671 more that 32 bits make no sense anyway, ( the
6672 largest size of an object can be only 32 bits ) */
6674 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6675 emitcode("inc","b");
6676 freeAsmop (right,NULL,ic,TRUE);
6677 aopOp(left,ic,FALSE, FALSE);
6678 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6680 /* now move the left to the result if they are not the
6682 if (!sameRegs(AOP(left),AOP(result)) &&
6683 AOP_SIZE(result) > 1) {
6685 size = AOP_SIZE(result);
6687 _startLazyDPSEvaluation();
6689 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6690 if (*l == '@' && IS_AOP_PREG(result)) {
6692 emitcode("mov","a,%s",l);
6693 aopPut(AOP(result),"a",offset);
6695 aopPut(AOP(result),l,offset);
6698 _endLazyDPSEvaluation();
6701 tlbl = newiTempLabel(NULL);
6702 tlbl1= newiTempLabel(NULL);
6703 size = AOP_SIZE(result);
6706 /* if it is only one byte then */
6708 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6710 emitcode("sjmp","%05d$",tlbl1->key+100);
6711 emitcode("","%05d$:",tlbl->key+100);
6713 emitcode("rrc","a");
6714 emitcode("","%05d$:",tlbl1->key+100);
6715 emitcode("djnz","b,%05d$",tlbl->key+100);
6716 aopPut(AOP(result),"a",0);
6720 reAdjustPreg(AOP(result));
6721 emitcode("sjmp","%05d$",tlbl1->key+100);
6722 emitcode("","%05d$:",tlbl->key+100);
6724 _startLazyDPSEvaluation();
6726 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6728 emitcode("rrc","a");
6729 aopPut(AOP(result),"a",offset--);
6731 _endLazyDPSEvaluation();
6732 reAdjustPreg(AOP(result));
6734 emitcode("","%05d$:",tlbl1->key+100);
6735 emitcode("djnz","b,%05d$",tlbl->key+100);
6738 freeAsmop(left,NULL,ic,TRUE);
6739 freeAsmop(result,NULL,ic,TRUE);
6742 /*-----------------------------------------------------------------*/
6743 /* genUnpackBits - generates code for unpacking bits */
6744 /*-----------------------------------------------------------------*/
6745 static void genUnpackBits (operand *result, char *rname, int ptype)
6752 D(emitcode(";", "genUnpackBits "););
6754 etype = getSpec(operandType(result));
6756 /* read the first byte */
6761 emitcode("mov","a,@%s",rname);
6765 emitcode("movx","a,@%s",rname);
6769 emitcode("movx","a,@dptr");
6773 emitcode("clr","a");
6774 emitcode("movc","a","@a+dptr");
6778 emitcode("lcall","__gptrget");
6782 /* if we have bitdisplacement then it fits */
6783 /* into this byte completely or if length is */
6784 /* less than a byte */
6785 if ((shCnt = SPEC_BSTR(etype)) ||
6786 (SPEC_BLEN(etype) <= 8)) {
6788 /* shift right acc */
6791 emitcode("anl","a,#0x%02x",
6792 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6793 aopPut(AOP(result),"a",offset);
6797 /* bit field did not fit in a byte */
6798 rlen = SPEC_BLEN(etype) - 8;
6799 aopPut(AOP(result),"a",offset++);
6806 emitcode("inc","%s",rname);
6807 emitcode("mov","a,@%s",rname);
6811 emitcode("inc","%s",rname);
6812 emitcode("movx","a,@%s",rname);
6816 emitcode("inc","dptr");
6817 emitcode("movx","a,@dptr");
6821 emitcode("clr","a");
6822 emitcode("inc","dptr");
6823 emitcode("movc","a","@a+dptr");
6827 emitcode("inc","dptr");
6828 emitcode("lcall","__gptrget");
6833 /* if we are done */
6837 aopPut(AOP(result),"a",offset++);
6842 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6843 aopPut(AOP(result),"a",offset);
6850 /*-----------------------------------------------------------------*/
6851 /* genDataPointerGet - generates code when ptr offset is known */
6852 /*-----------------------------------------------------------------*/
6853 static void genDataPointerGet (operand *left,
6859 int size , offset = 0;
6860 aopOp(result,ic,TRUE, FALSE);
6862 /* get the string representation of the name */
6863 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6864 size = AOP_SIZE(result);
6865 _startLazyDPSEvaluation();
6868 sprintf(buffer,"(%s + %d)",l+1,offset);
6870 sprintf(buffer,"%s",l+1);
6871 aopPut(AOP(result),buffer,offset++);
6873 _endLazyDPSEvaluation();
6875 freeAsmop(left,NULL,ic,TRUE);
6876 freeAsmop(result,NULL,ic,TRUE);
6879 /*-----------------------------------------------------------------*/
6880 /* genNearPointerGet - emitcode for near pointer fetch */
6881 /*-----------------------------------------------------------------*/
6882 static void genNearPointerGet (operand *left,
6889 sym_link *rtype, *retype, *letype;
6890 sym_link *ltype = operandType(left);
6893 rtype = operandType(result);
6894 retype= getSpec(rtype);
6895 letype= getSpec(ltype);
6897 aopOp(left,ic,FALSE, FALSE);
6899 /* if left is rematerialisable and
6900 result is not bit variable type and
6901 the left is pointer to data space i.e
6902 lower 128 bytes of space */
6903 if (AOP_TYPE(left) == AOP_IMMD &&
6904 !IS_BITVAR(retype) &&
6905 !IS_BITVAR(letype) &&
6906 DCL_TYPE(ltype) == POINTER) {
6907 genDataPointerGet (left,result,ic);
6911 /* if the value is already in a pointer register
6912 then don't need anything more */
6913 if (!AOP_INPREG(AOP(left))) {
6914 /* otherwise get a free pointer register */
6916 preg = getFreePtr(ic,&aop,FALSE);
6917 emitcode("mov","%s,%s",
6919 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6920 rname = preg->name ;
6922 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6924 freeAsmop(left,NULL,ic,TRUE);
6925 aopOp (result,ic,FALSE, FALSE);
6927 /* if bitfield then unpack the bits */
6928 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6929 genUnpackBits (result,rname,POINTER);
6931 /* we have can just get the values */
6932 int size = AOP_SIZE(result);
6936 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6938 emitcode("mov","a,@%s",rname);
6939 aopPut(AOP(result),"a",offset);
6941 sprintf(buffer,"@%s",rname);
6942 aopPut(AOP(result),buffer,offset);
6946 emitcode("inc","%s",rname);
6950 /* now some housekeeping stuff */
6952 /* we had to allocate for this iCode */
6953 freeAsmop(NULL,aop,ic,TRUE);
6955 /* we did not allocate which means left
6956 already in a pointer register, then
6957 if size > 0 && this could be used again
6958 we have to point it back to where it
6960 if (AOP_SIZE(result) > 1 &&
6961 !OP_SYMBOL(left)->remat &&
6962 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6964 int size = AOP_SIZE(result) - 1;
6966 emitcode("dec","%s",rname);
6971 freeAsmop(result,NULL,ic,TRUE);
6975 /*-----------------------------------------------------------------*/
6976 /* genPagedPointerGet - emitcode for paged pointer fetch */
6977 /*-----------------------------------------------------------------*/
6978 static void genPagedPointerGet (operand *left,
6985 sym_link *rtype, *retype, *letype;
6987 rtype = operandType(result);
6988 retype= getSpec(rtype);
6989 letype= getSpec(operandType(left));
6990 aopOp(left,ic,FALSE, FALSE);
6992 /* if the value is already in a pointer register
6993 then don't need anything more */
6994 if (!AOP_INPREG(AOP(left))) {
6995 /* otherwise get a free pointer register */
6997 preg = getFreePtr(ic,&aop,FALSE);
6998 emitcode("mov","%s,%s",
7000 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
7001 rname = preg->name ;
7003 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
7005 freeAsmop(left,NULL,ic,TRUE);
7006 aopOp (result,ic,FALSE, FALSE);
7008 /* if bitfield then unpack the bits */
7009 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7010 genUnpackBits (result,rname,PPOINTER);
7012 /* we have can just get the values */
7013 int size = AOP_SIZE(result);
7018 emitcode("movx","a,@%s",rname);
7019 aopPut(AOP(result),"a",offset);
7024 emitcode("inc","%s",rname);
7028 /* now some housekeeping stuff */
7030 /* we had to allocate for this iCode */
7031 freeAsmop(NULL,aop,ic,TRUE);
7033 /* we did not allocate which means left
7034 already in a pointer register, then
7035 if size > 0 && this could be used again
7036 we have to point it back to where it
7038 if (AOP_SIZE(result) > 1 &&
7039 !OP_SYMBOL(left)->remat &&
7040 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7042 int size = AOP_SIZE(result) - 1;
7044 emitcode("dec","%s",rname);
7049 freeAsmop(result,NULL,ic,TRUE);
7054 /*-----------------------------------------------------------------*/
7055 /* genFarPointerGet - gget value from far space */
7056 /*-----------------------------------------------------------------*/
7057 static void genFarPointerGet (operand *left,
7058 operand *result, iCode *ic)
7061 sym_link *retype = getSpec(operandType(result));
7062 sym_link *letype = getSpec(operandType(left));
7063 D(emitcode(";", "genFarPointerGet"););
7065 aopOp(left,ic,FALSE, FALSE);
7067 /* if the operand is already in dptr
7068 then we do nothing else we move the value to dptr */
7069 if (AOP_TYPE(left) != AOP_STR) {
7070 /* if this is remateriazable */
7071 if (AOP_TYPE(left) == AOP_IMMD)
7073 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7077 /* we need to get it byte by byte */
7078 _startLazyDPSEvaluation();
7079 if (AOP_TYPE(left) != AOP_DPTR)
7081 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7082 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7083 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7087 /* We need to generate a load to DPTR indirect through DPTR. */
7088 D(emitcode(";", "genFarPointerGet -- indirection special case."););
7089 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7090 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7091 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7092 emitcode("pop", "dph");
7093 emitcode("pop", "dpl");
7095 _endLazyDPSEvaluation();
7098 /* so dptr know contains the address */
7099 freeAsmop(left,NULL,ic,TRUE);
7100 aopOp(result,ic,FALSE, TRUE);
7102 /* if bit then unpack */
7103 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7104 genUnpackBits(result,"dptr",FPOINTER);
7106 size = AOP_SIZE(result);
7109 _startLazyDPSEvaluation();
7115 emitcode("movx","a,@dptr");
7117 emitcode("inc","dptr");
7119 aopPut(AOP(result),"a",offset++);
7121 _endLazyDPSEvaluation();
7124 freeAsmop(result,NULL,ic,TRUE);
7127 /*-----------------------------------------------------------------*/
7128 /* emitcodePointerGet - gget value from code space */
7129 /*-----------------------------------------------------------------*/
7130 static void emitcodePointerGet (operand *left,
7131 operand *result, iCode *ic)
7134 sym_link *retype = getSpec(operandType(result));
7136 aopOp(left,ic,FALSE, FALSE);
7138 /* if the operand is already in dptr
7139 then we do nothing else we move the value to dptr */
7140 if (AOP_TYPE(left) != AOP_STR) {
7141 /* if this is remateriazable */
7142 if (AOP_TYPE(left) == AOP_IMMD)
7144 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7147 { /* we need to get it byte by byte */
7148 _startLazyDPSEvaluation();
7149 if (AOP_TYPE(left) != AOP_DPTR)
7151 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7152 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7153 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7157 /* We need to generate a load to DPTR indirect through DPTR. */
7158 D(emitcode(";", "gencodePointerGet -- indirection special case."););
7159 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7160 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7161 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7162 emitcode("pop", "dph");
7163 emitcode("pop", "dpl");
7165 _endLazyDPSEvaluation();
7168 /* so dptr know contains the address */
7169 freeAsmop(left,NULL,ic,TRUE);
7170 aopOp(result,ic,FALSE, TRUE);
7172 /* if bit then unpack */
7173 if (IS_BITVAR(retype))
7174 genUnpackBits(result,"dptr",CPOINTER);
7176 size = AOP_SIZE(result);
7179 _startLazyDPSEvaluation();
7185 emitcode("clr","a");
7186 emitcode("movc","a,@a+dptr");
7188 emitcode("inc","dptr");
7189 aopPut(AOP(result),"a",offset++);
7191 _endLazyDPSEvaluation();
7194 freeAsmop(result,NULL,ic,TRUE);
7197 /*-----------------------------------------------------------------*/
7198 /* genGenPointerGet - gget value from generic pointer space */
7199 /*-----------------------------------------------------------------*/
7200 static void genGenPointerGet (operand *left,
7201 operand *result, iCode *ic)
7204 sym_link *retype = getSpec(operandType(result));
7205 sym_link *letype = getSpec(operandType(left));
7207 aopOp(left,ic,FALSE, TRUE);
7209 /* if the operand is already in dptr
7210 then we do nothing else we move the value to dptr */
7211 if (AOP_TYPE(left) != AOP_STR) {
7212 /* if this is remateriazable */
7213 if (AOP_TYPE(left) == AOP_IMMD) {
7214 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7215 emitcode("mov","b,#%d",pointerCode(retype));
7217 else { /* we need to get it byte by byte */
7218 _startLazyDPSEvaluation();
7219 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7220 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7221 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7222 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7223 _endLazyDPSEvaluation();
7226 /* so dptr know contains the address */
7227 freeAsmop(left,NULL,ic,TRUE);
7228 aopOp(result,ic,FALSE, TRUE);
7230 /* if bit then unpack */
7231 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7232 genUnpackBits(result,"dptr",GPOINTER);
7234 size = AOP_SIZE(result);
7238 emitcode("lcall","__gptrget");
7239 aopPut(AOP(result),"a",offset++);
7241 emitcode("inc","dptr");
7245 freeAsmop(result,NULL,ic,TRUE);
7248 /*-----------------------------------------------------------------*/
7249 /* genPointerGet - generate code for pointer get */
7250 /*-----------------------------------------------------------------*/
7251 static void genPointerGet (iCode *ic)
7253 operand *left, *result ;
7254 sym_link *type, *etype;
7257 D(emitcode(";", "genPointerGet "););
7260 result = IC_RESULT(ic) ;
7262 /* depending on the type of pointer we need to
7263 move it to the correct pointer register */
7264 type = operandType(left);
7265 etype = getSpec(type);
7266 /* if left is of type of pointer then it is simple */
7267 if (IS_PTR(type) && !IS_FUNC(type->next))
7268 p_type = DCL_TYPE(type);
7270 /* we have to go by the storage class */
7271 p_type = PTR_TYPE(SPEC_OCLS(etype));
7274 /* now that we have the pointer type we assign
7275 the pointer values */
7280 genNearPointerGet (left,result,ic);
7284 genPagedPointerGet(left,result,ic);
7288 genFarPointerGet (left,result,ic);
7292 emitcodePointerGet (left,result,ic);
7296 genGenPointerGet (left,result,ic);
7302 /*-----------------------------------------------------------------*/
7303 /* genPackBits - generates code for packed bit storage */
7304 /*-----------------------------------------------------------------*/
7305 static void genPackBits (sym_link *etype ,
7307 char *rname, int p_type)
7315 blen = SPEC_BLEN(etype);
7316 bstr = SPEC_BSTR(etype);
7318 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7321 /* if the bit lenth is less than or */
7322 /* it exactly fits a byte then */
7323 if (SPEC_BLEN(etype) <= 8 ) {
7324 shCount = SPEC_BSTR(etype) ;
7326 /* shift left acc */
7329 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7334 emitcode ("mov","b,a");
7335 emitcode("mov","a,@%s",rname);
7339 emitcode ("mov","b,a");
7340 emitcode("movx","a,@dptr");
7344 emitcode ("push","b");
7345 emitcode ("push","acc");
7346 emitcode ("lcall","__gptrget");
7347 emitcode ("pop","b");
7351 emitcode ("anl","a,#0x%02x",(unsigned char)
7352 ((unsigned char)(0xFF << (blen+bstr)) |
7353 (unsigned char)(0xFF >> (8-bstr)) ) );
7354 emitcode ("orl","a,b");
7355 if (p_type == GPOINTER)
7356 emitcode("pop","b");
7362 emitcode("mov","@%s,a",rname);
7366 emitcode("movx","@dptr,a");
7370 emitcode("lcall","__gptrput");
7375 if ( SPEC_BLEN(etype) <= 8 )
7378 emitcode("inc","%s",rname);
7379 rLen = SPEC_BLEN(etype) ;
7381 /* now generate for lengths greater than one byte */
7384 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7394 emitcode("mov","@%s,a",rname);
7396 emitcode("mov","@%s,%s",rname,l);
7401 emitcode("movx","@dptr,a");
7406 emitcode("lcall","__gptrput");
7409 emitcode ("inc","%s",rname);
7414 /* last last was not complete */
7416 /* save the byte & read byte */
7419 emitcode ("mov","b,a");
7420 emitcode("mov","a,@%s",rname);
7424 emitcode ("mov","b,a");
7425 emitcode("movx","a,@dptr");
7429 emitcode ("push","b");
7430 emitcode ("push","acc");
7431 emitcode ("lcall","__gptrget");
7432 emitcode ("pop","b");
7436 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << rLen) );
7437 emitcode ("orl","a,b");
7440 if (p_type == GPOINTER)
7441 emitcode("pop","b");
7446 emitcode("mov","@%s,a",rname);
7450 emitcode("movx","@dptr,a");
7454 emitcode("lcall","__gptrput");
7458 /*-----------------------------------------------------------------*/
7459 /* genDataPointerSet - remat pointer to data space */
7460 /*-----------------------------------------------------------------*/
7461 static void genDataPointerSet(operand *right,
7465 int size, offset = 0 ;
7466 char *l, buffer[256];
7468 aopOp(right,ic,FALSE, FALSE);
7470 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7471 size = AOP_SIZE(right);
7474 sprintf(buffer,"(%s + %d)",l+1,offset);
7476 sprintf(buffer,"%s",l+1);
7477 emitcode("mov","%s,%s",buffer,
7478 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7481 freeAsmop(right,NULL,ic,TRUE);
7482 freeAsmop(result,NULL,ic,TRUE);
7485 /*-----------------------------------------------------------------*/
7486 /* genNearPointerSet - emitcode for near pointer put */
7487 /*-----------------------------------------------------------------*/
7488 static void genNearPointerSet (operand *right,
7495 sym_link *retype, *letype;
7496 sym_link *ptype = operandType(result);
7498 retype= getSpec(operandType(right));
7499 letype= getSpec(ptype);
7501 aopOp(result,ic,FALSE, FALSE);
7503 /* if the result is rematerializable &
7504 in data space & not a bit variable */
7505 if (AOP_TYPE(result) == AOP_IMMD &&
7506 DCL_TYPE(ptype) == POINTER &&
7507 !IS_BITVAR(retype) &&
7508 !IS_BITVAR(letype)) {
7509 genDataPointerSet (right,result,ic);
7513 /* if the value is already in a pointer register
7514 then don't need anything more */
7515 if (!AOP_INPREG(AOP(result))) {
7516 /* otherwise get a free pointer register */
7518 preg = getFreePtr(ic,&aop,FALSE);
7519 emitcode("mov","%s,%s",
7521 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7522 rname = preg->name ;
7524 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7526 freeAsmop(result,NULL,ic,TRUE);
7527 aopOp (right,ic,FALSE, FALSE);
7529 /* if bitfield then unpack the bits */
7530 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7531 genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
7533 /* we have can just get the values */
7534 int size = AOP_SIZE(right);
7538 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7541 emitcode("mov","@%s,a",rname);
7543 emitcode("mov","@%s,%s",rname,l);
7545 emitcode("inc","%s",rname);
7550 /* now some housekeeping stuff */
7552 /* we had to allocate for this iCode */
7553 freeAsmop(NULL,aop,ic,TRUE);
7555 /* we did not allocate which means left
7556 already in a pointer register, then
7557 if size > 0 && this could be used again
7558 we have to point it back to where it
7560 if (AOP_SIZE(right) > 1 &&
7561 !OP_SYMBOL(result)->remat &&
7562 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7564 int size = AOP_SIZE(right) - 1;
7566 emitcode("dec","%s",rname);
7571 freeAsmop(right,NULL,ic,TRUE);
7576 /*-----------------------------------------------------------------*/
7577 /* genPagedPointerSet - emitcode for Paged pointer put */
7578 /*-----------------------------------------------------------------*/
7579 static void genPagedPointerSet (operand *right,
7586 sym_link *retype, *letype;
7588 retype= getSpec(operandType(right));
7589 letype= getSpec(operandType(result));
7591 aopOp(result,ic,FALSE, FALSE);
7593 /* if the value is already in a pointer register
7594 then don't need anything more */
7595 if (!AOP_INPREG(AOP(result))) {
7596 /* otherwise get a free pointer register */
7598 preg = getFreePtr(ic,&aop,FALSE);
7599 emitcode("mov","%s,%s",
7601 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7602 rname = preg->name ;
7604 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7606 freeAsmop(result,NULL,ic,TRUE);
7607 aopOp (right,ic,FALSE, FALSE);
7609 /* if bitfield then unpack the bits */
7610 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7611 genPackBits ((IS_BITVAR(retype) ? retype : letype) ,right,rname,PPOINTER);
7613 /* we have can just get the values */
7614 int size = AOP_SIZE(right);
7618 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7621 emitcode("movx","@%s,a",rname);
7624 emitcode("inc","%s",rname);
7630 /* now some housekeeping stuff */
7632 /* we had to allocate for this iCode */
7633 freeAsmop(NULL,aop,ic,TRUE);
7635 /* we did not allocate which means left
7636 already in a pointer register, then
7637 if size > 0 && this could be used again
7638 we have to point it back to where it
7640 if (AOP_SIZE(right) > 1 &&
7641 !OP_SYMBOL(result)->remat &&
7642 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7644 int size = AOP_SIZE(right) - 1;
7646 emitcode("dec","%s",rname);
7651 freeAsmop(right,NULL,ic,TRUE);
7656 /*-----------------------------------------------------------------*/
7657 /* genFarPointerSet - set value from far space */
7658 /*-----------------------------------------------------------------*/
7659 static void genFarPointerSet (operand *right,
7660 operand *result, iCode *ic)
7663 sym_link *retype = getSpec(operandType(right));
7664 sym_link *letype = getSpec(operandType(result));
7666 aopOp(result,ic,FALSE, FALSE);
7668 /* if the operand is already in dptr
7669 then we do nothing else we move the value to dptr */
7670 if (AOP_TYPE(result) != AOP_STR) {
7671 /* if this is remateriazable */
7672 if (AOP_TYPE(result) == AOP_IMMD)
7673 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7676 /* we need to get it byte by byte */
7677 _startLazyDPSEvaluation();
7678 if (AOP_TYPE(result) != AOP_DPTR)
7680 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7681 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7682 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7686 /* We need to generate a load to DPTR indirect through DPTR. */
7687 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7688 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7689 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7690 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7691 emitcode("pop", "dph");
7692 emitcode("pop", "dpl");
7694 _endLazyDPSEvaluation();
7697 /* so dptr know contains the address */
7698 freeAsmop(result,NULL,ic,TRUE);
7699 aopOp(right,ic,FALSE, TRUE);
7701 /* if bit then unpack */
7702 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7703 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",FPOINTER);
7705 size = AOP_SIZE(right);
7708 _startLazyDPSEvaluation();
7710 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7716 emitcode("movx","@dptr,a");
7718 emitcode("inc","dptr");
7720 _endLazyDPSEvaluation();
7723 freeAsmop(right,NULL,ic,TRUE);
7726 /*-----------------------------------------------------------------*/
7727 /* genGenPointerSet - set value from generic pointer space */
7728 /*-----------------------------------------------------------------*/
7729 static void genGenPointerSet (operand *right,
7730 operand *result, iCode *ic)
7733 sym_link *retype = getSpec(operandType(right));
7734 sym_link *letype = getSpec(operandType(result));
7736 aopOp(result,ic,FALSE, TRUE);
7738 /* if the operand is already in dptr
7739 then we do nothing else we move the value to dptr */
7740 if (AOP_TYPE(result) != AOP_STR) {
7741 _startLazyDPSEvaluation();
7742 /* if this is remateriazable */
7743 if (AOP_TYPE(result) == AOP_IMMD) {
7744 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7745 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7747 else { /* we need to get it byte by byte */
7748 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7749 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7750 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7751 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7753 _endLazyDPSEvaluation();
7755 /* so dptr know contains the address */
7756 freeAsmop(result,NULL,ic,TRUE);
7757 aopOp(right,ic,FALSE, TRUE);
7759 /* if bit then unpack */
7760 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7761 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",GPOINTER);
7763 size = AOP_SIZE(right);
7766 _startLazyDPSEvaluation();
7768 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7774 emitcode("lcall","__gptrput");
7776 emitcode("inc","dptr");
7778 _endLazyDPSEvaluation();
7781 freeAsmop(right,NULL,ic,TRUE);
7784 /*-----------------------------------------------------------------*/
7785 /* genPointerSet - stores the value into a pointer location */
7786 /*-----------------------------------------------------------------*/
7787 static void genPointerSet (iCode *ic)
7789 operand *right, *result ;
7790 sym_link *type, *etype;
7793 D(emitcode(";", "genPointerSet "););
7795 right = IC_RIGHT(ic);
7796 result = IC_RESULT(ic) ;
7798 /* depending on the type of pointer we need to
7799 move it to the correct pointer register */
7800 type = operandType(result);
7801 etype = getSpec(type);
7802 /* if left is of type of pointer then it is simple */
7803 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7804 p_type = DCL_TYPE(type);
7807 /* we have to go by the storage class */
7808 p_type = PTR_TYPE(SPEC_OCLS(etype));
7811 /* now that we have the pointer type we assign
7812 the pointer values */
7817 genNearPointerSet (right,result,ic);
7821 genPagedPointerSet (right,result,ic);
7825 genFarPointerSet (right,result,ic);
7829 genGenPointerSet (right,result,ic);
7835 /*-----------------------------------------------------------------*/
7836 /* genIfx - generate code for Ifx statement */
7837 /*-----------------------------------------------------------------*/
7838 static void genIfx (iCode *ic, iCode *popIc)
7840 operand *cond = IC_COND(ic);
7843 D(emitcode(";", "genIfx "););
7845 aopOp(cond,ic,FALSE, FALSE);
7847 /* get the value into acc */
7848 if (AOP_TYPE(cond) != AOP_CRY)
7852 /* the result is now in the accumulator */
7853 freeAsmop(cond,NULL,ic,TRUE);
7855 /* if there was something to be popped then do it */
7859 /* if the condition is a bit variable */
7860 if (isbit && IS_ITEMP(cond) &&
7862 genIfxJump(ic,SPIL_LOC(cond)->rname);
7864 if (isbit && !IS_ITEMP(cond))
7865 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7872 /*-----------------------------------------------------------------*/
7873 /* genAddrOf - generates code for address of */
7874 /*-----------------------------------------------------------------*/
7875 static void genAddrOf (iCode *ic)
7877 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7880 D(emitcode(";", "genAddrOf "););
7882 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7884 /* if the operand is on the stack then we
7885 need to get the stack offset of this
7888 /* if it has an offset then we need to compute
7891 emitcode("mov","a,_bp");
7892 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7893 aopPut(AOP(IC_RESULT(ic)),"a",0);
7895 /* we can just move _bp */
7896 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7898 /* fill the result with zero */
7899 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7902 if (options.stack10bit && size < (FPTRSIZE - 1))
7905 "*** warning: pointer to stack var truncated.\n");
7912 if (options.stack10bit && offset == 2)
7914 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7918 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7925 /* object not on stack then we need the name */
7926 size = AOP_SIZE(IC_RESULT(ic));
7930 char s[SDCC_NAME_MAX];
7932 sprintf(s,"#(%s >> %d)",
7936 sprintf(s,"#%s",sym->rname);
7937 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7941 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7945 /*-----------------------------------------------------------------*/
7946 /* genFarFarAssign - assignment when both are in far space */
7947 /*-----------------------------------------------------------------*/
7948 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7950 int size = AOP_SIZE(right);
7957 /* This is a net loss for size == 1, but a big gain
7960 D(emitcode(";", "genFarFarAssign (improved)"););
7962 aopOp(result,ic,TRUE, TRUE);
7964 _startLazyDPSEvaluation();
7968 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7972 _endLazyDPSEvaluation();
7973 freeAsmop(result,NULL,ic,FALSE);
7974 freeAsmop(right,NULL,ic,FALSE);
7979 D(emitcode(";", "genFarFarAssign "););
7981 /* first push the right side on to the stack */
7982 _startLazyDPSEvaluation();
7984 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7986 emitcode ("push","acc");
7989 freeAsmop(right,NULL,ic,FALSE);
7990 /* now assign DPTR to result */
7991 aopOp(result,ic,FALSE, FALSE);
7992 size = AOP_SIZE(result);
7994 emitcode ("pop","acc");
7995 aopPut(AOP(result),"a",--offset);
7997 freeAsmop(result,NULL,ic,FALSE);
7998 _endLazyDPSEvaluation();
8002 /*-----------------------------------------------------------------*/
8003 /* genAssign - generate code for assignment */
8004 /*-----------------------------------------------------------------*/
8005 static void genAssign (iCode *ic)
8007 operand *result, *right;
8009 unsigned long lit = 0L;
8011 D(emitcode(";", "genAssign "););
8013 result = IC_RESULT(ic);
8014 right = IC_RIGHT(ic) ;
8016 /* if they are the same */
8017 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8020 aopOp(right,ic,FALSE, FALSE);
8022 emitcode(";", "genAssign: resultIsFar = %s",
8023 isOperandInFarSpace(result) ?
8026 /* special case both in far space */
8027 if ((AOP_TYPE(right) == AOP_DPTR ||
8028 AOP_TYPE(right) == AOP_DPTR2) &&
8029 /* IS_TRUE_SYMOP(result) && */
8030 isOperandInFarSpace(result)) {
8032 genFarFarAssign (result,right,ic);
8036 aopOp(result,ic,TRUE, FALSE);
8038 /* if they are the same registers */
8039 if (sameRegs(AOP(right),AOP(result)))
8042 /* if the result is a bit */
8043 if (AOP_TYPE(result) == AOP_CRY) {
8045 /* if the right size is a literal then
8046 we know what the value is */
8047 if (AOP_TYPE(right) == AOP_LIT) {
8048 if (((int) operandLitValue(right)))
8049 aopPut(AOP(result),one,0);
8051 aopPut(AOP(result),zero,0);
8055 /* the right is also a bit variable */
8056 if (AOP_TYPE(right) == AOP_CRY) {
8057 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8058 aopPut(AOP(result),"c",0);
8064 aopPut(AOP(result),"a",0);
8068 /* bit variables done */
8070 size = AOP_SIZE(result);
8072 if(AOP_TYPE(right) == AOP_LIT)
8073 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8076 (AOP_TYPE(result) != AOP_REG) &&
8077 (AOP_TYPE(right) == AOP_LIT) &&
8078 !IS_FLOAT(operandType(right))
8079 #ifndef LAZY_DPS_OPT
8085 D(emitcode(";", "Kevin's better literal load code"););
8086 _startLazyDPSEvaluation();
8087 while (size && ((unsigned int)(lit >> (offset*8)) != 0))
8090 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
8095 /* And now fill the rest with zeros. */
8098 emitcode("clr","a");
8102 aopPut(AOP(result), "a", offset++);
8104 _endLazyDPSEvaluation();
8106 emitcode("clr","a");
8108 _startLazyDPSEvaluation();
8111 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
8112 aopPut(AOP(result),"a",size);
8115 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
8118 _endLazyDPSEvaluation();
8123 _startLazyDPSEvaluation();
8127 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8131 _endLazyDPSEvaluation();
8135 freeAsmop (right,NULL,ic,FALSE);
8136 freeAsmop (result,NULL,ic,TRUE);
8139 /*-----------------------------------------------------------------*/
8140 /* genJumpTab - generates code for jump table */
8141 /*-----------------------------------------------------------------*/
8142 static void genJumpTab (iCode *ic)
8147 D(emitcode(";", "genJumpTab "););
8149 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
8150 /* get the condition into accumulator */
8151 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
8153 /* multiply by four! */
8154 emitcode("add","a,acc");
8155 emitcode("add","a,acc");
8156 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8158 jtab = newiTempLabel(NULL);
8159 emitcode("mov","dptr,#%05d$",jtab->key+100);
8160 emitcode("jmp","@a+dptr");
8161 emitcode("","%05d$:",jtab->key+100);
8162 /* now generate the jump labels */
8163 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8164 jtab = setNextItem(IC_JTLABELS(ic)))
8165 emitcode("ljmp","%05d$",jtab->key+100);
8169 /*-----------------------------------------------------------------*/
8170 /* genCast - gen code for casting */
8171 /*-----------------------------------------------------------------*/
8172 static void genCast (iCode *ic)
8174 operand *result = IC_RESULT(ic);
8175 sym_link *ctype = operandType(IC_LEFT(ic));
8176 sym_link *rtype = operandType(IC_RIGHT(ic));
8177 operand *right = IC_RIGHT(ic);
8180 D(emitcode(";", "genCast "););
8182 /* if they are equivalent then do nothing */
8183 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8186 aopOp(right,ic,FALSE, FALSE) ;
8187 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
8189 /* if the result is a bit */
8190 if (AOP_TYPE(result) == AOP_CRY) {
8191 /* if the right size is a literal then
8192 we know what the value is */
8193 if (AOP_TYPE(right) == AOP_LIT) {
8194 if (((int) operandLitValue(right)))
8195 aopPut(AOP(result),one,0);
8197 aopPut(AOP(result),zero,0);
8202 /* the right is also a bit variable */
8203 if (AOP_TYPE(right) == AOP_CRY) {
8204 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8205 aopPut(AOP(result),"c",0);
8211 aopPut(AOP(result),"a",0);
8215 /* if they are the same size : or less */
8216 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8218 /* if they are in the same place */
8219 if (sameRegs(AOP(right),AOP(result)))
8222 /* if they in different places then copy */
8223 size = AOP_SIZE(result);
8225 _startLazyDPSEvaluation();
8228 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8232 _endLazyDPSEvaluation();
8237 /* if the result is of type pointer */
8238 if (IS_PTR(ctype)) {
8241 sym_link *type = operandType(right);
8243 /* pointer to generic pointer */
8244 if (IS_GENPTR(ctype)) {
8249 p_type = DCL_TYPE(type);
8253 #if OLD_CAST_BEHAVIOR
8254 /* KV: we are converting a non-pointer type to
8255 * a generic pointer. This (ifdef'd out) code
8256 * says that the resulting generic pointer
8257 * should have the same class as the storage
8258 * location of the non-pointer variable.
8260 * For example, converting an int (which happens
8261 * to be stored in DATA space) to a pointer results
8262 * in a DATA generic pointer; if the original int
8263 * in XDATA space, so will be the resulting pointer.
8265 * I don't like that behavior, and thus this change:
8266 * all such conversions will be forced to XDATA and
8267 * throw a warning. If you want some non-XDATA
8268 * type, or you want to suppress the warning, you
8269 * must go through an intermediate cast, like so:
8271 * char _generic *gp = (char _xdata *)(intVar);
8273 sym_link *etype = getSpec(type);
8275 /* we have to go by the storage class */
8276 if (SPEC_OCLS(etype) != generic)
8278 p_type = PTR_TYPE(SPEC_OCLS(etype));
8283 /* Converting unknown class (i.e. register variable)
8284 * to generic pointer. This is not good, but
8285 * we'll make a guess (and throw a warning).
8288 werror(W_INT_TO_GEN_PTR_CAST);
8292 /* the first two bytes are known */
8293 size = GPTRSIZE - 1;
8295 _startLazyDPSEvaluation();
8298 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8302 _endLazyDPSEvaluation();
8304 /* the last byte depending on type */
8321 /* this should never happen */
8322 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8323 "got unknown pointer type");
8326 aopPut(AOP(result),l, GPTRSIZE - 1);
8330 /* just copy the pointers */
8331 size = AOP_SIZE(result);
8333 _startLazyDPSEvaluation();
8336 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8340 _endLazyDPSEvaluation();
8344 /* so we now know that the size of destination is greater
8345 than the size of the source */
8346 /* we move to result for the size of source */
8347 size = AOP_SIZE(right);
8349 _startLazyDPSEvaluation();
8352 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8356 _endLazyDPSEvaluation();
8358 /* now depending on the sign of the source && destination */
8359 size = AOP_SIZE(result) - AOP_SIZE(right);
8360 /* if unsigned or not an integral type */
8361 /* also, if the source is a bit, we don't need to sign extend, because
8362 * it can't possibly have set the sign bit.
8364 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype) || AOP_TYPE(right) == AOP_CRY)
8368 aopPut(AOP(result),zero,offset++);
8373 /* we need to extend the sign :{ */
8374 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8377 emitcode("rlc","a");
8378 emitcode("subb","a,acc");
8380 aopPut(AOP(result),"a",offset++);
8383 /* we are done hurray !!!! */
8386 freeAsmop(right,NULL,ic,TRUE);
8387 freeAsmop(result,NULL,ic,TRUE);
8391 /*-----------------------------------------------------------------*/
8392 /* genDjnz - generate decrement & jump if not zero instrucion */
8393 /*-----------------------------------------------------------------*/
8394 static int genDjnz (iCode *ic, iCode *ifx)
8400 /* if the if condition has a false label
8401 then we cannot save */
8405 /* if the minus is not of the form
8407 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8408 !IS_OP_LITERAL(IC_RIGHT(ic)))
8411 if (operandLitValue(IC_RIGHT(ic)) != 1)
8414 /* if the size of this greater than one then no
8416 if (getSize(operandType(IC_RESULT(ic))) > 1)
8419 /* otherwise we can save BIG */
8420 lbl = newiTempLabel(NULL);
8421 lbl1= newiTempLabel(NULL);
8423 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8425 if (IS_AOP_PREG(IC_RESULT(ic))) {
8426 emitcode("dec","%s",
8427 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8428 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8429 emitcode("jnz","%05d$",lbl->key+100);
8431 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8434 emitcode ("sjmp","%05d$",lbl1->key+100);
8435 emitcode ("","%05d$:",lbl->key+100);
8436 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8437 emitcode ("","%05d$:",lbl1->key+100);
8439 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8444 /*-----------------------------------------------------------------*/
8445 /* genReceive - generate code for a receive iCode */
8446 /*-----------------------------------------------------------------*/
8447 static void genReceive (iCode *ic)
8450 D(emitcode(";", "genReceive "););
8452 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8453 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8454 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8455 int size = getSize(operandType(IC_RESULT(ic)));
8456 int offset = fReturnSize_390 - size;
8458 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8459 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8462 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8463 size = AOP_SIZE(IC_RESULT(ic));
8466 emitcode ("pop","acc");
8467 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8472 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8474 assignResultValue(IC_RESULT(ic));
8477 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8480 /*-----------------------------------------------------------------*/
8481 /* gen390Code - generate code for Dallas 390 based controllers */
8482 /*-----------------------------------------------------------------*/
8483 void gen390Code (iCode *lic)
8488 lineHead = lineCurr = NULL;
8492 /* print the allocation information */
8494 printAllocInfo( currFunc, codeOutFile);
8496 /* if debug information required */
8497 if (options.debug && currFunc) {
8498 //jwk if (currFunc) {
8499 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8501 if (IS_STATIC(currFunc->etype))
8502 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8504 emitcode("","G$%s$0$0 ==.",currFunc->name);
8507 /* stack pointer name */
8508 if (options.useXstack)
8514 for (ic = lic ; ic ; ic = ic->next ) {
8516 if ( cln != ic->lineno ) {
8517 if ( options.debug ) {
8519 emitcode("","C$%s$%d$%d$%d ==.",
8520 ic->filename,ic->lineno,
8521 ic->level,ic->block);
8524 emitcode(";","%s %d",ic->filename,ic->lineno);
8527 /* if the result is marked as
8528 spilt and rematerializable or code for
8529 this has already been generated then
8531 if (resultRemat(ic) || ic->generated )
8534 /* depending on the operation */
8553 /* IPOP happens only when trying to restore a
8554 spilt live range, if there is an ifx statement
8555 following this pop then the if statement might
8556 be using some of the registers being popped which
8557 would destory the contents of the register so
8558 we need to check for this condition and handle it */
8560 ic->next->op == IFX &&
8561 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8562 genIfx (ic->next,ic);
8580 genEndFunction (ic);
8600 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8617 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8621 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8628 /* note these two are xlated by algebraic equivalence
8629 during parsing SDCC.y */
8630 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8631 "got '>=' or '<=' shouldn't have come here");
8635 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8647 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8651 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8655 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8682 case GET_VALUE_AT_ADDRESS:
8687 if (POINTER_SET(ic))
8714 addSet(&_G.sendSet,ic);
8719 /* piCode(ic,stdout); */
8725 /* now we are ready to call the
8726 peep hole optimizer */
8727 if (!options.nopeep)
8728 peepHole (&lineHead);
8730 /* now do the actual printing */
8731 printLine (lineHead,codeOutFile);