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 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
37 #ifdef HAVE_SYS_ISA_DEFS_H
38 #include <sys/isa_defs.h>
44 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
45 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #include "SDCCpeeph.h"
55 char *aopLiteral (value *val, int offset);
58 /* this is the down and dirty file with all kinds of
59 kludgy & hacky stuff. This is what it is all about
60 CODE GENERATION for a specific MCU . some of the
61 routines may be reusable, will have to see */
63 static char *zero = "#0x00";
64 static char *one = "#0x01";
69 unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
70 static char *fReturn[] = {"dpl","dph","dpx", "b","a" };
71 static char *accUse[] = {"a","b"};
73 static short rbank = -1;
85 extern int ds390_ptrRegReq ;
86 extern int ds390_nRegs;
87 extern FILE *codeOutFile;
88 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 (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_ATOMIC(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_ATOMIC(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];
716 aop = op->aop = sym->aop = newAsmop(AOP_STR);
717 aop->size = getSize(sym->type);
718 for ( i = 0 ; i < fReturnSize_390 ; i++ )
719 aop->aopu.aop_str[i] = fReturn[i];
723 /* else spill location */
724 sym->aop = op->aop = aop =
725 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
726 aop->size = getSize(sym->type);
730 /* must be in a register */
731 sym->aop = op->aop = aop = newAsmop(AOP_REG);
732 aop->size = sym->nRegs;
733 for ( i = 0 ; i < sym->nRegs ;i++)
734 aop->aopu.aop_reg[i] = sym->regs[i];
737 /*-----------------------------------------------------------------*/
738 /* freeAsmop - free up the asmop given to an operand */
739 /*----------------------------------------------------------------*/
740 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
757 /* depending on the asmop type only three cases need work AOP_RO
758 , AOP_R1 && AOP_STK */
763 emitcode ("pop","ar0");
767 bitVectUnSetBit(ic->rUsed,R0_IDX);
773 emitcode ("pop","ar1");
777 bitVectUnSetBit(ic->rUsed,R1_IDX);
783 int stk = aop->aopu.aop_stk + aop->size;
784 bitVectUnSetBit(ic->rUsed,R0_IDX);
785 bitVectUnSetBit(ic->rUsed,R1_IDX);
787 getFreePtr(ic,&aop,FALSE);
789 if (options.stack10bit)
791 /* I'm not sure what to do here yet... */
794 "*** Warning: probably generating bad code for "
795 "10 bit stack mode.\n");
799 emitcode ("mov","a,_bp");
800 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
801 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
803 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
807 emitcode("pop","acc");
808 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
810 emitcode("dec","%s",aop->aopu.aop_ptr->name);
813 freeAsmop(op,NULL,ic,TRUE);
815 emitcode("pop","ar0");
820 emitcode("pop","ar1");
827 /* all other cases just dealloc */
831 OP_SYMBOL(op)->aop = NULL;
832 /* if the symbol has a spill */
834 SPIL_LOC(op)->aop = NULL;
839 /*------------------------------------------------------------------*/
840 /* aopGet - for fetching value of the aop */
842 /* Set canClobberACC if you are aure it is OK to clobber the value */
843 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe,*/
844 /* just less efficient. */
845 /*------------------------------------------------------------------*/
847 static char *aopGet (asmop *aop,
856 /* offset is greater than
858 if (offset > (aop->size - 1) &&
859 aop->type != AOP_LIT)
862 /* depending on type */
867 /* if we need to increment it */
868 while (offset > aop->coff) {
869 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
873 while (offset < aop->coff) {
874 emitcode("dec","%s",aop->aopu.aop_ptr->name);
880 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
881 return (dname ? "acc" : "a");
883 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
884 ALLOC_ATOMIC(rs,strlen(s)+1);
891 if (aop->type == AOP_DPTR2)
895 #ifndef KEVIN_BROKE_IT
899 emitcode("xch", "a, ap");
905 while (offset > aop->coff) {
906 emitcode ("inc","dptr");
910 while (offset < aop->coff) {
911 emitcode("lcall","__decdptr");
918 emitcode("movc","a,@a+dptr");
921 emitcode("movx","a,@dptr");
924 if (aop->type == AOP_DPTR2)
928 #ifndef KEVIN_BROKE_IT
932 emitcode("xch", "a, ap");
937 return (dname ? "acc" : "a");
941 sprintf (s,"#%s",aop->aopu.aop_immd);
944 sprintf(s,"#(%s >> %d)",
950 ALLOC_ATOMIC(rs,strlen(s)+1);
956 sprintf(s,"(%s + %d)",
960 sprintf(s,"%s",aop->aopu.aop_dir);
961 ALLOC_ATOMIC(rs,strlen(s)+1);
967 return aop->aopu.aop_reg[offset]->dname;
969 return aop->aopu.aop_reg[offset]->name;
973 emitcode("mov","c,%s",aop->aopu.aop_dir);
974 emitcode("rlc","a") ;
975 return (dname ? "acc" : "a");
978 if (!offset && dname)
980 return aop->aopu.aop_str[offset];
983 return aopLiteral (aop->aopu.aop_lit,offset);
987 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
991 return aop->aopu.aop_str[offset];
995 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
996 "aopget got unsupported aop->type");
999 /*-----------------------------------------------------------------*/
1000 /* aopPut - puts a string for a aop */
1001 /*-----------------------------------------------------------------*/
1002 static void aopPut (asmop *aop, char *s, int offset)
1007 if (aop->size && offset > ( aop->size - 1)) {
1008 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1009 "aopPut got offset > aop->size");
1013 /* will assign value to value */
1014 /* depending on where it is ofcourse */
1015 switch (aop->type) {
1018 sprintf(d,"(%s + %d)",
1019 aop->aopu.aop_dir,offset);
1021 sprintf(d,"%s",aop->aopu.aop_dir);
1024 emitcode("mov","%s,%s",d,s);
1029 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1030 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1032 strcmp(s,"r0") == 0 ||
1033 strcmp(s,"r1") == 0 ||
1034 strcmp(s,"r2") == 0 ||
1035 strcmp(s,"r3") == 0 ||
1036 strcmp(s,"r4") == 0 ||
1037 strcmp(s,"r5") == 0 ||
1038 strcmp(s,"r6") == 0 ||
1039 strcmp(s,"r7") == 0 )
1040 emitcode("mov","%s,%s",
1041 aop->aopu.aop_reg[offset]->dname,s);
1043 emitcode("mov","%s,%s",
1044 aop->aopu.aop_reg[offset]->name,s);
1051 if (aop->type == AOP_DPTR2)
1058 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1059 "aopPut writting to code space");
1063 while (offset > aop->coff) {
1065 emitcode ("inc","dptr");
1068 while (offset < aop->coff) {
1070 emitcode("lcall","__decdptr");
1075 /* if not in accumulater */
1078 emitcode ("movx","@dptr,a");
1080 if (aop->type == AOP_DPTR2)
1088 while (offset > aop->coff) {
1090 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1092 while (offset < aop->coff) {
1094 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1100 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1105 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1107 if (strcmp(s,"r0") == 0 ||
1108 strcmp(s,"r1") == 0 ||
1109 strcmp(s,"r2") == 0 ||
1110 strcmp(s,"r3") == 0 ||
1111 strcmp(s,"r4") == 0 ||
1112 strcmp(s,"r5") == 0 ||
1113 strcmp(s,"r6") == 0 ||
1114 strcmp(s,"r7") == 0 ) {
1116 sprintf(buffer,"a%s",s);
1117 emitcode("mov","@%s,%s",
1118 aop->aopu.aop_ptr->name,buffer);
1120 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1125 if (strcmp(s,"a") == 0)
1126 emitcode("push","acc");
1128 emitcode("push","%s",s);
1133 /* if bit variable */
1134 if (!aop->aopu.aop_dir) {
1135 emitcode("clr","a");
1136 emitcode("rlc","a");
1139 emitcode("clr","%s",aop->aopu.aop_dir);
1142 emitcode("setb","%s",aop->aopu.aop_dir);
1145 emitcode("mov","%s,c",aop->aopu.aop_dir);
1147 lbl = newiTempLabel(NULL);
1149 if (strcmp(s,"a")) {
1152 emitcode("clr","c");
1153 emitcode("jz","%05d$",lbl->key+100);
1154 emitcode("cpl","c");
1155 emitcode("","%05d$:",lbl->key+100);
1156 emitcode("mov","%s,c",aop->aopu.aop_dir);
1163 if (strcmp(aop->aopu.aop_str[offset],s))
1164 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1169 if (!offset && (strcmp(s,"acc") == 0))
1172 if (strcmp(aop->aopu.aop_str[offset],s))
1173 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1177 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1178 "aopPut got unsupported aop->type");
1185 /*-----------------------------------------------------------------*/
1186 /* reAdjustPreg - points a register back to where it should */
1187 /*-----------------------------------------------------------------*/
1188 static void reAdjustPreg (asmop *aop)
1193 if ((size = aop->size) <= 1)
1196 switch (aop->type) {
1200 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1204 if (aop->type == AOP_DPTR2)
1211 emitcode("lcall","__decdptr");
1214 if (aop->type == AOP_DPTR2)
1224 #define AOP(op) op->aop
1225 #define AOP_TYPE(op) AOP(op)->type
1226 #define AOP_SIZE(op) AOP(op)->size
1227 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1228 AOP_TYPE(x) == AOP_R0))
1230 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1231 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1234 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1235 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1236 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1238 /* Workaround for DS80C390 bug: div ab may return bogus results
1239 * if A is accessed in instruction immediately before the div.
1241 * Will be fixed in B4 rev of processor, Dallas claims.
1244 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1245 if (!AOP_NEEDSACC(RIGHT)) \
1247 /* We can load A first, then B, since \
1248 * B (the RIGHT operand) won't clobber A, \
1249 * thus avoiding touching A right before the div. \
1251 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1252 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1254 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1258 /* Just stuff in a nop after loading A. */ \
1259 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1260 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1262 emitcode("nop", "; workaround for DS80C390 div bug."); \
1265 /*-----------------------------------------------------------------*/
1266 /* genNotFloat - generates not for float operations */
1267 /*-----------------------------------------------------------------*/
1268 static void genNotFloat (operand *op, operand *res)
1274 D(emitcode(";", "genNotFloat "););
1276 /* we will put 127 in the first byte of
1278 aopPut(AOP(res),"#127",0);
1279 size = AOP_SIZE(op) - 1;
1282 _startLazyDPSEvaluation();
1283 l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
1287 emitcode("orl","a,%s",
1289 offset++,FALSE,FALSE,FALSE));
1291 _endLazyDPSEvaluation();
1292 tlbl = newiTempLabel(NULL);
1294 tlbl = newiTempLabel(NULL);
1295 aopPut(res->aop,one,1);
1296 emitcode("jz","%05d$",(tlbl->key+100));
1297 aopPut(res->aop,zero,1);
1298 emitcode("","%05d$:",(tlbl->key+100));
1300 size = res->aop->size - 2;
1302 /* put zeros in the rest */
1304 aopPut(res->aop,zero,offset++);
1307 /*-----------------------------------------------------------------*/
1308 /* opIsGptr: returns non-zero if the passed operand is */
1309 /* a generic pointer type. */
1310 /*-----------------------------------------------------------------*/
1311 static int opIsGptr(operand *op)
1313 link *type = operandType(op);
1315 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1322 /*-----------------------------------------------------------------*/
1323 /* getDataSize - get the operand data size */
1324 /*-----------------------------------------------------------------*/
1325 static int getDataSize(operand *op)
1328 size = AOP_SIZE(op);
1329 if (size == GPTRSIZE)
1331 link *type = operandType(op);
1332 if (IS_GENPTR(type))
1334 /* generic pointer; arithmetic operations
1335 * should ignore the high byte (pointer type).
1343 /*-----------------------------------------------------------------*/
1344 /* outAcc - output Acc */
1345 /*-----------------------------------------------------------------*/
1346 static void outAcc(operand *result)
1349 size = getDataSize(result);
1351 aopPut(AOP(result),"a",0);
1354 /* unsigned or positive */
1356 aopPut(AOP(result),zero,offset++);
1361 /*-----------------------------------------------------------------*/
1362 /* outBitC - output a bit C */
1363 /*-----------------------------------------------------------------*/
1364 static void outBitC(operand *result)
1366 /* if the result is bit */
1367 if (AOP_TYPE(result) == AOP_CRY)
1368 aopPut(AOP(result),"c",0);
1370 emitcode("clr","a");
1371 emitcode("rlc","a");
1376 /*-----------------------------------------------------------------*/
1377 /* toBoolean - emit code for orl a,operator(sizeop) */
1378 /*-----------------------------------------------------------------*/
1379 static void toBoolean(operand *oper)
1381 int size = AOP_SIZE(oper) - 1;
1384 /* The generic part of a generic pointer should
1385 * not participate in it's truth value.
1387 * i.e. 0x10000000 is zero.
1391 D(emitcode(";", "toBoolean: generic ptr special case."););
1395 _startLazyDPSEvaluation();
1396 if (AOP_NEEDSACC(oper))
1398 emitcode("push", "b");
1399 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1403 MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1407 if (AOP_NEEDSACC(oper))
1409 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1413 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1416 _endLazyDPSEvaluation();
1418 if (AOP_NEEDSACC(oper))
1420 emitcode("mov", "a,b");
1421 emitcode("pop", "b");
1426 /*-----------------------------------------------------------------*/
1427 /* genNot - generate code for ! operation */
1428 /*-----------------------------------------------------------------*/
1429 static void genNot (iCode *ic)
1432 link *optype = operandType(IC_LEFT(ic));
1434 D(emitcode(";", "genNot "););
1436 /* assign asmOps to operand & result */
1437 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1438 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1440 /* if in bit space then a special case */
1441 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1442 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1443 emitcode("cpl","c");
1444 outBitC(IC_RESULT(ic));
1448 /* if type float then do float */
1449 if (IS_FLOAT(optype)) {
1450 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1454 toBoolean(IC_LEFT(ic));
1456 tlbl = newiTempLabel(NULL);
1457 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1458 emitcode("","%05d$:",tlbl->key+100);
1459 outBitC(IC_RESULT(ic));
1462 /* release the aops */
1463 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1464 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1468 /*-----------------------------------------------------------------*/
1469 /* genCpl - generate code for complement */
1470 /*-----------------------------------------------------------------*/
1471 static void genCpl (iCode *ic)
1476 D(emitcode(";", "genCpl "););
1479 /* assign asmOps to operand & result */
1480 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1481 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1483 /* if both are in bit space then
1485 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1486 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1488 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1489 emitcode("cpl","c");
1490 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1494 size = AOP_SIZE(IC_RESULT(ic));
1495 _startLazyDPSEvaluation();
1497 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1499 emitcode("cpl","a");
1500 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1502 _endLazyDPSEvaluation();
1506 /* release the aops */
1507 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1508 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1511 /*-----------------------------------------------------------------*/
1512 /* genUminusFloat - unary minus for floating points */
1513 /*-----------------------------------------------------------------*/
1514 static void genUminusFloat(operand *op,operand *result)
1516 int size ,offset =0 ;
1518 /* for this we just need to flip the
1519 first it then copy the rest in place */
1520 D(emitcode(";", "genUminusFloat"););
1522 _startLazyDPSEvaluation();
1523 size = AOP_SIZE(op) - 1;
1524 l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1527 emitcode("cpl","acc.7");
1528 aopPut(AOP(result),"a",3);
1532 aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1536 _endLazyDPSEvaluation();
1539 /*-----------------------------------------------------------------*/
1540 /* genUminus - unary minus code generation */
1541 /*-----------------------------------------------------------------*/
1542 static void genUminus (iCode *ic)
1545 link *optype, *rtype;
1547 D(emitcode(";", "genUminus "););
1551 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1552 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1554 /* if both in bit space then special
1556 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1557 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1559 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1560 emitcode("cpl","c");
1561 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1565 optype = operandType(IC_LEFT(ic));
1566 rtype = operandType(IC_RESULT(ic));
1568 /* if float then do float stuff */
1569 if (IS_FLOAT(optype)) {
1570 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1574 /* otherwise subtract from zero */
1575 size = AOP_SIZE(IC_LEFT(ic));
1578 _startLazyDPSEvaluation();
1580 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1581 if (!strcmp(l,"a")) {
1584 emitcode("cpl","a");
1585 emitcode("addc", "a,#0");
1589 emitcode("clr","a");
1590 emitcode("subb","a,%s",l);
1592 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1594 _endLazyDPSEvaluation();
1596 /* if any remaining bytes in the result */
1597 /* we just need to propagate the sign */
1598 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1599 emitcode("rlc","a");
1600 emitcode("subb","a,acc");
1602 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1606 /* release the aops */
1607 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1608 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1611 /*-----------------------------------------------------------------*/
1612 /* saveRegisters - will look for a call and save the registers */
1613 /*-----------------------------------------------------------------*/
1614 static void saveRegisters(iCode *lic)
1622 for (ic = lic ; ic ; ic = ic->next)
1623 if (ic->op == CALL || ic->op == PCALL)
1627 fprintf(stderr,"found parameter push with no function call\n");
1631 /* if the registers have been saved already then
1633 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1636 /* find the registers in use at this time
1637 and push them away to safety */
1638 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1642 if (options.useXstack) {
1643 if (bitVectBitValue(rsave,R0_IDX))
1644 emitcode("mov","b,r0");
1645 emitcode("mov","r0,%s",spname);
1646 for (i = 0 ; i < ds390_nRegs ; i++) {
1647 if (bitVectBitValue(rsave,i)) {
1649 emitcode("mov","a,b");
1651 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1652 emitcode("movx","@r0,a");
1653 emitcode("inc","r0");
1656 emitcode("mov","%s,r0",spname);
1657 if (bitVectBitValue(rsave,R0_IDX))
1658 emitcode("mov","r0,b");
1660 for (i = 0 ; i < ds390_nRegs ; i++) {
1661 if (bitVectBitValue(rsave,i))
1662 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1665 detype = getSpec(operandType(IC_LEFT(ic)));
1667 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1668 IS_ISR(currFunc->etype) &&
1671 saverbank(SPEC_BANK(detype),ic,TRUE);
1674 /*-----------------------------------------------------------------*/
1675 /* unsaveRegisters - pop the pushed registers */
1676 /*-----------------------------------------------------------------*/
1677 static void unsaveRegisters (iCode *ic)
1681 /* find the registers in use at this time
1682 and push them away to safety */
1683 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1686 if (options.useXstack) {
1687 emitcode("mov","r0,%s",spname);
1688 for (i = ds390_nRegs ; i >= 0 ; i--) {
1689 if (bitVectBitValue(rsave,i)) {
1690 emitcode("dec","r0");
1691 emitcode("movx","a,@r0");
1693 emitcode("mov","b,a");
1695 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1699 emitcode("mov","%s,r0",spname);
1700 if (bitVectBitValue(rsave,R0_IDX))
1701 emitcode("mov","r0,b");
1703 for (i = ds390_nRegs ; i >= 0 ; i--) {
1704 if (bitVectBitValue(rsave,i))
1705 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1711 /*-----------------------------------------------------------------*/
1713 /*-----------------------------------------------------------------*/
1714 static void pushSide(operand * oper, int size)
1717 _startLazyDPSEvaluation();
1719 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1720 if (AOP_TYPE(oper) != AOP_REG &&
1721 AOP_TYPE(oper) != AOP_DIR &&
1723 emitcode("mov","a,%s",l);
1724 emitcode("push","acc");
1726 emitcode("push","%s",l);
1728 _endLazyDPSEvaluation();
1731 /*-----------------------------------------------------------------*/
1732 /* assignResultValue - */
1733 /*-----------------------------------------------------------------*/
1734 static void assignResultValue(operand * oper)
1737 int size = AOP_SIZE(oper);
1739 _startLazyDPSEvaluation();
1741 aopPut(AOP(oper),fReturn[offset],offset);
1744 _endLazyDPSEvaluation();
1748 /*-----------------------------------------------------------------*/
1749 /* genXpush - pushes onto the external stack */
1750 /*-----------------------------------------------------------------*/
1751 static void genXpush (iCode *ic)
1753 asmop *aop = newAsmop(0);
1755 int size,offset = 0;
1757 D(emitcode(";", "genXpush "););
1759 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1760 r = getFreePtr(ic,&aop,FALSE);
1763 emitcode("mov","%s,_spx",r->name);
1765 size = AOP_SIZE(IC_LEFT(ic));
1766 _startLazyDPSEvaluation();
1769 char *l = aopGet(AOP(IC_LEFT(ic)),
1770 offset++,FALSE,FALSE,TRUE);
1772 emitcode("movx","@%s,a",r->name);
1773 emitcode("inc","%s",r->name);
1776 _endLazyDPSEvaluation();
1779 emitcode("mov","_spx,%s",r->name);
1781 freeAsmop(NULL,aop,ic,TRUE);
1782 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1785 /*-----------------------------------------------------------------*/
1786 /* genIpush - genrate code for pushing this gets a little complex */
1787 /*-----------------------------------------------------------------*/
1788 static void genIpush (iCode *ic)
1790 int size, offset = 0 ;
1793 D(emitcode(";", "genIpush "););
1796 /* if this is not a parm push : ie. it is spill push
1797 and spill push is always done on the local stack */
1798 if (!ic->parmPush) {
1800 /* and the item is spilt then do nothing */
1801 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1804 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1805 size = AOP_SIZE(IC_LEFT(ic));
1806 /* push it on the stack */
1807 _startLazyDPSEvaluation();
1809 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1814 emitcode("push","%s",l);
1816 _endLazyDPSEvaluation();
1820 /* this is a paramter push: in this case we call
1821 the routine to find the call and save those
1822 registers that need to be saved */
1825 /* if use external stack then call the external
1826 stack pushing routine */
1827 if (options.useXstack) {
1832 /* then do the push */
1833 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1836 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1837 size = AOP_SIZE(IC_LEFT(ic));
1839 _startLazyDPSEvaluation();
1841 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1842 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1843 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1845 emitcode("mov","a,%s",l);
1846 emitcode("push","acc");
1848 emitcode("push","%s",l);
1850 _endLazyDPSEvaluation();
1852 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1855 /*-----------------------------------------------------------------*/
1856 /* genIpop - recover the registers: can happen only for spilling */
1857 /*-----------------------------------------------------------------*/
1858 static void genIpop (iCode *ic)
1862 D(emitcode(";", "genIpop "););
1865 /* if the temp was not pushed then */
1866 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1869 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1870 size = AOP_SIZE(IC_LEFT(ic));
1872 _startLazyDPSEvaluation();
1875 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1878 _endLazyDPSEvaluation();
1880 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1883 /*-----------------------------------------------------------------*/
1884 /* unsaverbank - restores the resgister bank from stack */
1885 /*-----------------------------------------------------------------*/
1886 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1893 if (options.useXstack) {
1895 r = getFreePtr(ic,&aop,FALSE);
1898 emitcode("mov","%s,_spx",r->name);
1899 emitcode("movx","a,@%s",r->name);
1900 emitcode("mov","psw,a");
1901 emitcode("dec","%s",r->name);
1904 emitcode ("pop","psw");
1907 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1908 if (options.useXstack) {
1909 emitcode("movx","a,@%s",r->name);
1910 emitcode("mov","(%s+%d),a",
1911 regs390[i].base,8*bank+regs390[i].offset);
1912 emitcode("dec","%s",r->name);
1915 emitcode("pop","(%s+%d)",
1916 regs390[i].base,8*bank+regs390[i].offset);
1919 if (options.useXstack) {
1921 emitcode("mov","_spx,%s",r->name);
1922 freeAsmop(NULL,aop,ic,TRUE);
1927 /*-----------------------------------------------------------------*/
1928 /* saverbank - saves an entire register bank on the stack */
1929 /*-----------------------------------------------------------------*/
1930 static void saverbank (int bank, iCode *ic, bool pushPsw)
1936 if (options.useXstack) {
1939 r = getFreePtr(ic,&aop,FALSE);
1940 emitcode("mov","%s,_spx",r->name);
1944 for (i = 0 ; i < ds390_nRegs ;i++) {
1945 if (options.useXstack) {
1946 emitcode("inc","%s",r->name);
1947 emitcode("mov","a,(%s+%d)",
1948 regs390[i].base,8*bank+regs390[i].offset);
1949 emitcode("movx","@%s,a",r->name);
1951 emitcode("push","(%s+%d)",
1952 regs390[i].base,8*bank+regs390[i].offset);
1956 if (options.useXstack) {
1957 emitcode("mov","a,psw");
1958 emitcode("movx","@%s,a",r->name);
1959 emitcode("inc","%s",r->name);
1960 emitcode("mov","_spx,%s",r->name);
1961 freeAsmop (NULL,aop,ic,TRUE);
1964 emitcode("push","psw");
1966 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1972 /*-----------------------------------------------------------------*/
1973 /* genCall - generates a call statement */
1974 /*-----------------------------------------------------------------*/
1975 static void genCall (iCode *ic)
1979 D(emitcode(";", "genCall "););
1981 /* if caller saves & we have not saved then */
1985 /* if we are calling a function that is not using
1986 the same register bank then we need to save the
1987 destination registers on the stack */
1988 detype = getSpec(operandType(IC_LEFT(ic)));
1990 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1991 IS_ISR(currFunc->etype) &&
1994 saverbank(SPEC_BANK(detype),ic,TRUE);
1996 /* if send set is not empty the assign */
2000 for (sic = setFirstItem(_G.sendSet) ; sic ;
2001 sic = setNextItem(_G.sendSet))
2003 int size, offset = 0;
2005 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
2006 size = AOP_SIZE(IC_LEFT(sic));
2008 _startLazyDPSEvaluation();
2010 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2011 FALSE, FALSE, TRUE);
2012 if (strcmp(l,fReturn[offset]))
2013 emitcode("mov","%s,%s",
2018 _endLazyDPSEvaluation();
2019 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2024 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2025 OP_SYMBOL(IC_LEFT(ic))->rname :
2026 OP_SYMBOL(IC_LEFT(ic))->name));
2028 /* if we need assign a result value */
2029 if ((IS_ITEMP(IC_RESULT(ic)) &&
2030 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2031 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2032 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2035 /* Not really related to LAZY_DPS_OPT, but don't want
2036 * another testing flag right now...
2038 #define FAR_RETURN_OPT
2039 #ifdef FAR_RETURN_OPT
2040 if (isOperandInFarSpace(IC_RESULT(ic))
2041 && getSize(operandType(IC_RESULT(ic))) <= 2)
2043 int size = getSize(operandType(IC_RESULT(ic)));
2045 /* Special case for 1 or 2 byte return in far space. */
2046 emitcode(";", "Kevin function call abuse #1");
2051 emitcode("mov", "b,%s", fReturn[1]);
2054 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2055 aopPut(AOP(IC_RESULT(ic)),"a",0);
2059 aopPut(AOP(IC_RESULT(ic)),"b",1);
2061 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2067 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2070 assignResultValue(IC_RESULT(ic));
2072 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2075 if (!isOperandInFarSpace(IC_RESULT(ic)))
2078 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2081 assignResultValue(IC_RESULT(ic));
2083 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2087 /* Result is in far space, and requires DPTR to access
2088 * it. Push the result onto the stack and restore from
2091 int size = getSize(operandType(IC_RESULT(ic)));
2092 int offset = size - 1;
2095 emitcode(";", "Kevin function call abuse #1");
2097 /* first push the right side on to the stack */
2098 /* NB: this relies on the fact that "a" is the last
2099 * register in fReturn. If it were not, the MOVA
2100 * would potentially clobber a returned byte in A.
2103 l = fReturn[offset--];
2105 emitcode ("push","acc");
2108 /* now assign DPTR to result */
2109 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2110 size = AOP_SIZE(IC_RESULT(ic));
2111 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
2113 emitcode ("pop","acc");
2114 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
2116 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2121 /* adjust the stack for parameters if
2123 if (IC_LEFT(ic)->parmBytes) {
2125 if (IC_LEFT(ic)->parmBytes > 3) {
2126 emitcode("mov","a,%s",spname);
2127 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2128 emitcode("mov","%s,a",spname);
2130 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2131 emitcode("dec","%s",spname);
2135 /* if register bank was saved then pop them */
2137 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2139 /* if we hade saved some registers then unsave them */
2140 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2141 unsaveRegisters (ic);
2146 /*-----------------------------------------------------------------*/
2147 /* genPcall - generates a call by pointer statement */
2148 /*-----------------------------------------------------------------*/
2149 static void genPcall (iCode *ic)
2152 symbol *rlbl = newiTempLabel(NULL);
2154 D(emitcode(";", "genPcall "););
2157 /* if caller saves & we have not saved then */
2161 /* if we are calling a function that is not using
2162 the same register bank then we need to save the
2163 destination registers on the stack */
2164 detype = getSpec(operandType(IC_LEFT(ic)));
2166 IS_ISR(currFunc->etype) &&
2167 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2168 saverbank(SPEC_BANK(detype),ic,TRUE);
2171 /* push the return address on to the stack */
2172 emitcode("mov","a,#%05d$",(rlbl->key+100));
2173 emitcode("push","acc");
2174 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2175 emitcode("push","acc");
2177 if (options.model == MODEL_FLAT24)
2179 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2180 emitcode("push","acc");
2183 /* now push the calling address */
2184 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2186 pushSide(IC_LEFT(ic), FPTRSIZE);
2188 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2190 /* if send set is not empty the assign */
2194 for (sic = setFirstItem(_G.sendSet) ; sic ;
2195 sic = setNextItem(_G.sendSet))
2197 int size, offset = 0;
2199 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2200 size = AOP_SIZE(IC_LEFT(sic));
2201 _startLazyDPSEvaluation();
2204 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2206 if (strcmp(l,fReturn[offset]))
2208 emitcode("mov","%s,%s",
2214 _endLazyDPSEvaluation();
2215 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2221 emitcode("","%05d$:",(rlbl->key+100));
2224 /* if we need assign a result value */
2225 if ((IS_ITEMP(IC_RESULT(ic)) &&
2226 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2227 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2228 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2231 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2234 assignResultValue(IC_RESULT(ic));
2236 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2239 /* adjust the stack for parameters if
2241 if (IC_LEFT(ic)->parmBytes) {
2243 if (IC_LEFT(ic)->parmBytes > 3) {
2244 emitcode("mov","a,%s",spname);
2245 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2246 emitcode("mov","%s,a",spname);
2248 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2249 emitcode("dec","%s",spname);
2253 /* if register bank was saved then unsave them */
2255 (SPEC_BANK(currFunc->etype) !=
2257 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2259 /* if we hade saved some registers then
2262 unsaveRegisters (ic);
2266 /*-----------------------------------------------------------------*/
2267 /* resultRemat - result is rematerializable */
2268 /*-----------------------------------------------------------------*/
2269 static int resultRemat (iCode *ic)
2271 if (SKIP_IC(ic) || ic->op == IFX)
2274 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2275 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2276 if (sym->remat && !POINTER_SET(ic))
2284 #define STRCASECMP stricmp
2286 #define STRCASECMP strcasecmp
2289 /*-----------------------------------------------------------------*/
2290 /* inExcludeList - return 1 if the string is in exclude Reg list */
2291 /*-----------------------------------------------------------------*/
2292 static bool inExcludeList(char *s)
2296 if (options.excludeRegs[i] &&
2297 STRCASECMP(options.excludeRegs[i],"none") == 0)
2300 for ( i = 0 ; options.excludeRegs[i]; i++) {
2301 if (options.excludeRegs[i] &&
2302 STRCASECMP(s,options.excludeRegs[i]) == 0)
2308 /*-----------------------------------------------------------------*/
2309 /* genFunction - generated code for function entry */
2310 /*-----------------------------------------------------------------*/
2311 static void genFunction (iCode *ic)
2316 D(emitcode(";", "genFunction "););
2319 /* create the function header */
2320 emitcode(";","-----------------------------------------");
2321 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2322 emitcode(";","-----------------------------------------");
2324 emitcode("","%s:",sym->rname);
2325 fetype = getSpec(operandType(IC_LEFT(ic)));
2327 /* if critical function then turn interrupts off */
2328 if (SPEC_CRTCL(fetype))
2329 emitcode("clr","ea");
2331 /* here we need to generate the equates for the
2332 register bank if required */
2333 if (SPEC_BANK(fetype) != rbank) {
2336 rbank = SPEC_BANK(fetype);
2337 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2338 if (strcmp(regs390[i].base,"0") == 0)
2339 emitcode("","%s = 0x%02x",
2341 8*rbank+regs390[i].offset);
2343 emitcode ("","%s = %s + 0x%02x",
2346 8*rbank+regs390[i].offset);
2350 /* if this is an interrupt service routine then
2351 save acc, b, dpl, dph */
2352 if (IS_ISR(sym->etype)) {
2354 if (!inExcludeList("acc"))
2355 emitcode ("push","acc");
2356 if (!inExcludeList("b"))
2357 emitcode ("push","b");
2358 if (!inExcludeList("dpl"))
2359 emitcode ("push","dpl");
2360 if (!inExcludeList("dph"))
2361 emitcode ("push","dph");
2362 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2364 emitcode ("push", "dpx");
2365 /* Make sure we're using standard DPTR */
2366 emitcode ("push", "dps");
2367 emitcode ("mov", "dps, #0x00");
2368 if (options.stack10bit)
2370 /* This ISR could conceivably use DPTR2. Better save it. */
2371 emitcode ("push", "dpl1");
2372 emitcode ("push", "dph1");
2373 emitcode ("push", "dpx1");
2374 emitcode ("push", "ap");
2377 /* if this isr has no bank i.e. is going to
2378 run with bank 0 , then we need to save more
2380 if (!SPEC_BANK(sym->etype)) {
2382 /* if this function does not call any other
2383 function then we can be economical and
2384 save only those registers that are used */
2385 if (! sym->hasFcall) {
2388 /* if any registers used */
2389 if (sym->regsUsed) {
2390 /* save the registers used */
2391 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2392 if (bitVectBitValue(sym->regsUsed,i) ||
2393 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2394 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2399 /* this function has a function call cannot
2400 determines register usage so we will have the
2402 saverbank(0,ic,FALSE);
2406 /* if callee-save to be used for this function
2407 then save the registers being used in this function */
2408 if (sym->calleeSave) {
2411 /* if any registers used */
2412 if (sym->regsUsed) {
2413 /* save the registers used */
2414 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2415 if (bitVectBitValue(sym->regsUsed,i) ||
2416 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2417 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2425 /* set the register bank to the desired value */
2426 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2427 emitcode("push","psw");
2428 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2431 if (IS_RENT(sym->etype) || options.stackAuto) {
2433 if (options.useXstack) {
2434 emitcode("mov","r0,%s",spname);
2435 emitcode("mov","a,_bp");
2436 emitcode("movx","@r0,a");
2437 emitcode("inc","%s",spname);
2441 /* set up the stack */
2442 emitcode ("push","_bp"); /* save the callers stack */
2444 emitcode ("mov","_bp,%s",spname);
2447 /* adjust the stack for the function */
2452 werror(W_STACK_OVERFLOW,sym->name);
2454 if (i > 3 && sym->recvSize < 4) {
2456 emitcode ("mov","a,sp");
2457 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2458 emitcode ("mov","sp,a");
2463 emitcode("inc","sp");
2468 emitcode ("mov","a,_spx");
2469 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2470 emitcode ("mov","_spx,a");
2475 /*-----------------------------------------------------------------*/
2476 /* genEndFunction - generates epilogue for functions */
2477 /*-----------------------------------------------------------------*/
2478 static void genEndFunction (iCode *ic)
2480 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2482 D(emitcode(";", "genEndFunction "););
2484 if (IS_RENT(sym->etype) || options.stackAuto)
2486 emitcode ("mov","%s,_bp",spname);
2489 /* if use external stack but some variables were
2490 added to the local stack then decrement the
2492 if (options.useXstack && sym->stack) {
2493 emitcode("mov","a,sp");
2494 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2495 emitcode("mov","sp,a");
2499 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2500 if (options.useXstack) {
2501 emitcode("mov","r0,%s",spname);
2502 emitcode("movx","a,@r0");
2503 emitcode("mov","_bp,a");
2504 emitcode("dec","%s",spname);
2508 emitcode ("pop","_bp");
2512 /* restore the register bank */
2513 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2514 emitcode ("pop","psw");
2516 if (IS_ISR(sym->etype)) {
2518 /* now we need to restore the registers */
2519 /* if this isr has no bank i.e. is going to
2520 run with bank 0 , then we need to save more
2522 if (!SPEC_BANK(sym->etype)) {
2524 /* if this function does not call any other
2525 function then we can be economical and
2526 save only those registers that are used */
2527 if (! sym->hasFcall) {
2530 /* if any registers used */
2531 if (sym->regsUsed) {
2532 /* save the registers used */
2533 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2534 if (bitVectBitValue(sym->regsUsed,i) ||
2535 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2536 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2541 /* this function has a function call cannot
2542 determines register usage so we will have the
2544 unsaverbank(0,ic,FALSE);
2548 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2550 if (options.stack10bit)
2552 emitcode ("pop", "ap");
2553 emitcode ("pop", "dpx1");
2554 emitcode ("pop", "dph1");
2555 emitcode ("pop", "dpl1");
2557 emitcode ("pop", "dps");
2558 emitcode ("pop", "dpx");
2560 if (!inExcludeList("dph"))
2561 emitcode ("pop","dph");
2562 if (!inExcludeList("dpl"))
2563 emitcode ("pop","dpl");
2564 if (!inExcludeList("b"))
2565 emitcode ("pop","b");
2566 if (!inExcludeList("acc"))
2567 emitcode ("pop","acc");
2569 if (SPEC_CRTCL(sym->etype))
2570 emitcode("setb","ea");
2572 /* if debug then send end of function */
2573 /* if (options.debug && currFunc) { */
2576 emitcode("","C$%s$%d$%d$%d ==.",
2577 ic->filename,currFunc->lastLine,
2578 ic->level,ic->block);
2579 if (IS_STATIC(currFunc->etype))
2580 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2582 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2586 emitcode ("reti","");
2589 if (SPEC_CRTCL(sym->etype))
2590 emitcode("setb","ea");
2592 if (sym->calleeSave) {
2595 /* if any registers used */
2596 if (sym->regsUsed) {
2597 /* save the registers used */
2598 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2599 if (bitVectBitValue(sym->regsUsed,i) ||
2600 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2601 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2607 /* if debug then send end of function */
2610 emitcode("","C$%s$%d$%d$%d ==.",
2611 ic->filename,currFunc->lastLine,
2612 ic->level,ic->block);
2613 if (IS_STATIC(currFunc->etype))
2614 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2616 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2620 emitcode ("ret","");
2625 /*-----------------------------------------------------------------*/
2626 /* genRet - generate code for return statement */
2627 /*-----------------------------------------------------------------*/
2628 static void genRet (iCode *ic)
2630 int size,offset = 0 , pushed = 0;
2632 D(emitcode(";", "genRet "););
2634 /* if we have no return value then
2635 just generate the "ret" */
2639 /* we have something to return then
2640 move the return value into place */
2641 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2642 size = AOP_SIZE(IC_LEFT(ic));
2644 _startLazyDPSEvaluation();
2647 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2648 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2650 emitcode("push","%s",l);
2653 l = aopGet(AOP(IC_LEFT(ic)),offset,
2655 if (strcmp(fReturn[offset],l))
2656 emitcode("mov","%s,%s",fReturn[offset++],l);
2659 _endLazyDPSEvaluation();
2664 if (strcmp(fReturn[pushed],"a"))
2665 emitcode("pop",fReturn[pushed]);
2667 emitcode("pop","acc");
2670 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2673 /* generate a jump to the return label
2674 if the next is not the return statement */
2675 if (!(ic->next && ic->next->op == LABEL &&
2676 IC_LABEL(ic->next) == returnLabel))
2678 emitcode("ljmp","%05d$",(returnLabel->key+100));
2682 /*-----------------------------------------------------------------*/
2683 /* genLabel - generates a label */
2684 /*-----------------------------------------------------------------*/
2685 static void genLabel (iCode *ic)
2687 /* special case never generate */
2688 if (IC_LABEL(ic) == entryLabel)
2691 D(emitcode(";", "genLabel "););
2693 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2696 /*-----------------------------------------------------------------*/
2697 /* genGoto - generates a ljmp */
2698 /*-----------------------------------------------------------------*/
2699 static void genGoto (iCode *ic)
2701 D(emitcode(";", "genGoto "););
2702 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2705 /*-----------------------------------------------------------------*/
2706 /* findLabelBackwards: walks back through the iCode chain looking */
2707 /* for the given label. Returns number of iCode instructions */
2708 /* between that label and given ic. */
2709 /* Returns zero if label not found. */
2710 /*-----------------------------------------------------------------*/
2711 static int findLabelBackwards(iCode *ic, int key)
2720 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2722 /* printf("findLabelBackwards = %d\n", count); */
2730 /*-----------------------------------------------------------------*/
2731 /* genPlusIncr :- does addition with increment if possible */
2732 /*-----------------------------------------------------------------*/
2733 static bool genPlusIncr (iCode *ic)
2735 unsigned int icount ;
2736 unsigned int size = getDataSize(IC_RESULT(ic));
2738 /* will try to generate an increment */
2739 /* if the right side is not a literal
2741 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2744 /* if the literal value of the right hand side
2745 is greater than 4 then it is not worth it */
2746 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2749 /* if increment 16 bits in register */
2751 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2752 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2753 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2760 /* If the next instruction is a goto and the goto target
2761 * is <= 5 instructions previous to this, we can generate
2762 * jumps straight to that target.
2764 if (ic->next && ic->next->op == GOTO
2765 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2766 && labelRange <= 5 )
2768 emitcode(";", "tail increment optimized (range %d)", labelRange);
2769 tlbl = IC_LABEL(ic->next);
2774 tlbl = newiTempLabel(NULL);
2777 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2778 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2779 IS_AOP_PREG(IC_RESULT(ic)))
2780 emitcode("cjne","%s,#0x00,%05d$"
2781 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2784 emitcode("clr","a");
2785 emitcode("cjne","a,%s,%05d$"
2786 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2790 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2793 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2794 IS_AOP_PREG(IC_RESULT(ic)))
2795 emitcode("cjne","%s,#0x00,%05d$"
2796 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2799 emitcode("cjne","a,%s,%05d$"
2800 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2803 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2807 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2808 IS_AOP_PREG(IC_RESULT(ic)))
2809 emitcode("cjne","%s,#0x00,%05d$"
2810 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2813 emitcode("cjne","a,%s,%05d$"
2814 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2817 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2822 emitcode("","%05d$:",tlbl->key+100);
2827 /* if the sizes are greater than 1 then we cannot */
2828 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2829 AOP_SIZE(IC_LEFT(ic)) > 1 )
2832 /* we can if the aops of the left & result match or
2833 if they are in registers and the registers are the
2836 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2837 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2838 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2841 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2842 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2843 aopPut(AOP(IC_RESULT(ic)),"a",0);
2846 _startLazyDPSEvaluation();
2849 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2851 _endLazyDPSEvaluation();
2860 /*-----------------------------------------------------------------*/
2861 /* outBitAcc - output a bit in acc */
2862 /*-----------------------------------------------------------------*/
2863 static void outBitAcc(operand *result)
2865 symbol *tlbl = newiTempLabel(NULL);
2866 /* if the result is a bit */
2867 if (AOP_TYPE(result) == AOP_CRY){
2868 aopPut(AOP(result),"a",0);
2871 emitcode("jz","%05d$",tlbl->key+100);
2872 emitcode("mov","a,%s",one);
2873 emitcode("","%05d$:",tlbl->key+100);
2878 /*-----------------------------------------------------------------*/
2879 /* genPlusBits - generates code for addition of two bits */
2880 /*-----------------------------------------------------------------*/
2881 static void genPlusBits (iCode *ic)
2883 D(emitcode(";", "genPlusBits "););
2884 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2885 symbol *lbl = newiTempLabel(NULL);
2886 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2887 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2888 emitcode("cpl","c");
2889 emitcode("","%05d$:",(lbl->key+100));
2890 outBitC(IC_RESULT(ic));
2893 emitcode("clr","a");
2894 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2895 emitcode("rlc","a");
2896 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2897 emitcode("addc","a,#0x00");
2898 outAcc(IC_RESULT(ic));
2902 static void adjustArithmeticResult(iCode *ic)
2904 if (opIsGptr(IC_RESULT(ic)) &&
2905 opIsGptr(IC_LEFT(ic)) &&
2906 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2908 aopPut(AOP(IC_RESULT(ic)),
2909 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2913 if (opIsGptr(IC_RESULT(ic)) &&
2914 opIsGptr(IC_RIGHT(ic)) &&
2915 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2917 aopPut(AOP(IC_RESULT(ic)),
2918 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2922 if (opIsGptr(IC_RESULT(ic)) &&
2923 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2924 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2925 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2926 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2928 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2929 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2933 #define AOP_OP_3(ic) \
2934 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2935 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2936 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2937 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2938 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2940 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2942 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2945 #define AOP_SET_LOCALS(ic) \
2946 left = IC_LEFT(ic); \
2947 right = IC_RIGHT(ic); \
2948 result = IC_RESULT(ic);
2950 /*-----------------------------------------------------------------*/
2951 /* genPlus - generates code for addition */
2952 /*-----------------------------------------------------------------*/
2953 static void genPlus (iCode *ic)
2955 int size, offset = 0;
2956 bool pushResult = FALSE;
2959 D(emitcode(";", "genPlus "););
2961 /* special cases :- */
2964 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2965 aopOp (IC_LEFT(ic),ic,FALSE,
2966 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
2968 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2969 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2971 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2972 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2978 aopOp (IC_RESULT(ic),ic,TRUE,
2979 ((AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)
2980 || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR)));
2982 /* if literal, literal on the right or
2983 if left requires ACC or right is already
2985 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2986 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2987 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2988 operand *t = IC_RIGHT(ic);
2989 IC_RIGHT(ic) = IC_LEFT(ic);
2993 /* if both left & right are in bit
2995 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2996 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3001 /* if left in bit space & right literal */
3002 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3003 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3004 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3005 /* if result in bit space */
3006 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3007 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
3008 emitcode("cpl","c");
3009 outBitC(IC_RESULT(ic));
3011 size = getDataSize(IC_RESULT(ic));
3012 _startLazyDPSEvaluation();
3014 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3015 emitcode("addc","a,#00");
3016 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3018 _endLazyDPSEvaluation();
3023 /* if I can do an increment instead
3024 of add then GOOD for ME */
3025 if (genPlusIncr (ic) == TRUE)
3029 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3031 _startLazyDPSEvaluation();
3034 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3036 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3038 emitcode("add","a,%s",
3039 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3041 emitcode("addc","a,%s",
3042 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3044 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3046 emitcode("add","a,%s",
3047 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3049 emitcode("addc","a,%s",
3050 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3054 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3058 emitcode("push", "acc");
3062 _endLazyDPSEvaluation();
3066 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3068 size = getDataSize(IC_LEFT(ic));
3069 rSize = getDataSize(IC_RESULT(ic));
3071 /* If the pushed data is bigger than the result,
3072 * simply discard unused bytes. Icky, but works.
3074 * Should we throw a warning here? We're losing data...
3076 while (size > rSize)
3078 D(emitcode(";", "discarding unused result byte."););
3079 emitcode("pop", "acc");
3085 emitcode("clr", "a");
3086 /* Conversly, we haven't pushed enough here.
3087 * just zero-pad, and all is well.
3089 while (size < rSize)
3091 emitcode("push", "acc");
3097 _startLazyDPSEvaluation();
3100 emitcode("pop", "acc");
3101 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3103 _endLazyDPSEvaluation();
3106 adjustArithmeticResult(ic);
3109 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3110 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3111 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3114 /*-----------------------------------------------------------------*/
3115 /* genMinusDec :- does subtraction with deccrement if possible */
3116 /*-----------------------------------------------------------------*/
3117 static bool genMinusDec (iCode *ic)
3119 unsigned int icount ;
3120 unsigned int size = getDataSize(IC_RESULT(ic));
3122 /* will try to generate an increment */
3123 /* if the right side is not a literal
3125 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3128 /* if the literal value of the right hand side
3129 is greater than 4 then it is not worth it */
3130 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3133 /* if decrement 16 bits in register */
3134 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3135 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3136 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3143 /* If the next instruction is a goto and the goto target
3144 * is <= 5 instructions previous to this, we can generate
3145 * jumps straight to that target.
3147 if (ic->next && ic->next->op == GOTO
3148 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3149 && labelRange <= 5 )
3151 emitcode(";", "tail decrement optimized (range %d)", labelRange);
3152 tlbl = IC_LABEL(ic->next);
3157 tlbl = newiTempLabel(NULL);
3161 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3162 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3163 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3164 IS_AOP_PREG(IC_RESULT(ic)))
3165 emitcode("cjne","%s,#0xff,%05d$"
3166 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3169 emitcode("mov","a,#0xff");
3170 emitcode("cjne","a,%s,%05d$"
3171 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3174 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3177 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3178 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3179 IS_AOP_PREG(IC_RESULT(ic)))
3180 emitcode("cjne","%s,#0xff,%05d$"
3181 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3184 emitcode("cjne","a,%s,%05d$"
3185 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3188 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3192 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3193 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3194 IS_AOP_PREG(IC_RESULT(ic)))
3195 emitcode("cjne","%s,#0xff,%05d$"
3196 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3199 emitcode("cjne","a,%s,%05d$"
3200 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3203 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3207 emitcode("","%05d$:",tlbl->key+100);
3212 /* if the sizes are greater than 1 then we cannot */
3213 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3214 AOP_SIZE(IC_LEFT(ic)) > 1 )
3217 /* we can if the aops of the left & result match or
3218 if they are in registers and the registers are the
3221 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3222 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3223 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3225 _startLazyDPSEvaluation();
3228 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3230 _endLazyDPSEvaluation();
3238 /*-----------------------------------------------------------------*/
3239 /* addSign - complete with sign */
3240 /*-----------------------------------------------------------------*/
3241 static void addSign(operand *result, int offset, int sign)
3243 int size = (getDataSize(result) - offset);
3246 emitcode("rlc","a");
3247 emitcode("subb","a,acc");
3249 aopPut(AOP(result),"a",offset++);
3252 aopPut(AOP(result),zero,offset++);
3256 /*-----------------------------------------------------------------*/
3257 /* genMinusBits - generates code for subtraction of two bits */
3258 /*-----------------------------------------------------------------*/
3259 static void genMinusBits (iCode *ic)
3261 symbol *lbl = newiTempLabel(NULL);
3263 D(emitcode(";", "genMinusBits "););
3265 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3266 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3267 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3268 emitcode("cpl","c");
3269 emitcode("","%05d$:",(lbl->key+100));
3270 outBitC(IC_RESULT(ic));
3273 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3274 emitcode("subb","a,acc");
3275 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3276 emitcode("inc","a");
3277 emitcode("","%05d$:",(lbl->key+100));
3278 aopPut(AOP(IC_RESULT(ic)),"a",0);
3279 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3283 /*-----------------------------------------------------------------*/
3284 /* genMinus - generates code for subtraction */
3285 /*-----------------------------------------------------------------*/
3286 static void genMinus (iCode *ic)
3288 int size, offset = 0;
3290 unsigned long lit = 0L;
3291 bool pushResult = FALSE;
3293 D(emitcode(";", "genMinus "););
3295 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3296 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3297 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3298 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3304 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3306 /* special cases :- */
3307 /* if both left & right are in bit space */
3308 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3309 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3314 /* if I can do an decrement instead
3315 of subtract then GOOD for ME */
3316 if (genMinusDec (ic) == TRUE)
3321 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3323 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3327 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3332 /* if literal, add a,#-lit, else normal subb */
3333 _startLazyDPSEvaluation();
3335 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3336 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3337 emitcode("subb","a,%s",
3338 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3340 /* first add without previous c */
3342 emitcode("add","a,#0x%02x",
3343 (unsigned int)(lit & 0x0FFL));
3345 emitcode("addc","a,#0x%02x",
3346 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3351 emitcode("push", "acc");
3355 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3359 _endLazyDPSEvaluation();
3363 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3365 size = getDataSize(IC_LEFT(ic));
3366 rSize = getDataSize(IC_RESULT(ic));
3368 /* If the pushed data is bigger than the result,
3369 * simply discard unused bytes. Icky, but works.
3371 * Should we throw a warning here? We're losing data...
3373 while (size > getDataSize(IC_RESULT(ic)))
3375 emitcode(";", "discarding unused result byte.");
3376 emitcode("pop", "acc");
3382 emitcode("clr", "a");
3383 /* Conversly, we haven't pushed enough here.
3384 * just zero-pad, and all is well.
3386 while (size < rSize)
3388 emitcode("push", "acc");
3396 emitcode("pop", "acc");
3397 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3401 adjustArithmeticResult(ic);
3404 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3405 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3406 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3410 /*-----------------------------------------------------------------*/
3411 /* genMultbits :- multiplication of bits */
3412 /*-----------------------------------------------------------------*/
3413 static void genMultbits (operand *left,
3417 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3418 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3423 /*-----------------------------------------------------------------*/
3424 /* genMultOneByte : 8 bit multiplication & division */
3425 /*-----------------------------------------------------------------*/
3426 static void genMultOneByte (operand *left,
3430 link *opetype = operandType(result);
3435 /* (if two literals, the value is computed before) */
3436 /* if one literal, literal on the right */
3437 if (AOP_TYPE(left) == AOP_LIT){
3443 size = AOP_SIZE(result);
3444 /* signed or unsigned */
3445 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3446 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3448 emitcode("mul","ab");
3449 /* if result size = 1, mul signed = mul unsigned */
3450 aopPut(AOP(result),"a",0);
3452 if (SPEC_USIGN(opetype)){
3453 aopPut(AOP(result),"b",1);
3455 /* for filling the MSBs */
3456 emitcode("clr","a");
3459 emitcode("mov","a,b");
3461 /* adjust the MSB if left or right neg */
3463 /* if one literal */
3464 if (AOP_TYPE(right) == AOP_LIT){
3465 /* AND literal negative */
3466 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3467 /* adjust MSB (c==0 after mul) */
3468 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3472 lbl = newiTempLabel(NULL);
3473 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3474 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3475 emitcode("","%05d$:",(lbl->key+100));
3476 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3477 lbl = newiTempLabel(NULL);
3478 emitcode("jc","%05d$",(lbl->key+100));
3479 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3480 emitcode("","%05d$:",(lbl->key+100));
3483 lbl = newiTempLabel(NULL);
3484 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3485 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3486 emitcode("","%05d$:",(lbl->key+100));
3487 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3488 lbl = newiTempLabel(NULL);
3489 emitcode("jc","%05d$",(lbl->key+100));
3490 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3491 emitcode("","%05d$:",(lbl->key+100));
3493 aopPut(AOP(result),"a",1);
3496 emitcode("rlc","a");
3497 emitcode("subb","a,acc");
3504 aopPut(AOP(result),"a",offset++);
3508 /*-----------------------------------------------------------------*/
3509 /* genMult - generates code for multiplication */
3510 /*-----------------------------------------------------------------*/
3511 static void genMult (iCode *ic)
3513 operand *left = IC_LEFT(ic);
3514 operand *right = IC_RIGHT(ic);
3515 operand *result= IC_RESULT(ic);
3517 D(emitcode(";", "genMult "););
3519 /* assign the amsops */
3522 aopOp (left,ic,FALSE, FALSE);
3523 aopOp (right,ic,FALSE, TRUE);
3524 aopOp (result,ic,TRUE, FALSE);
3527 /* special cases first */
3529 if (AOP_TYPE(left) == AOP_CRY &&
3530 AOP_TYPE(right)== AOP_CRY) {
3531 genMultbits(left,right,result);
3535 /* if both are of size == 1 */
3536 if (AOP_SIZE(left) == 1 &&
3537 AOP_SIZE(right) == 1 ) {
3538 genMultOneByte(left,right,result);
3542 /* should have been converted to function call */
3546 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3547 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3548 freeAsmop(result,NULL,ic,TRUE);
3551 /*-----------------------------------------------------------------*/
3552 /* genDivbits :- division of bits */
3553 /*-----------------------------------------------------------------*/
3554 static void genDivbits (operand *left,
3561 /* the result must be bit */
3562 LOAD_AB_FOR_DIV(left, right, l);
3563 emitcode("div","ab");
3564 emitcode("rrc","a");
3565 aopPut(AOP(result),"c",0);
3568 /*-----------------------------------------------------------------*/
3569 /* genDivOneByte : 8 bit division */
3570 /*-----------------------------------------------------------------*/
3571 static void genDivOneByte (operand *left,
3575 link *opetype = operandType(result);
3580 size = AOP_SIZE(result) - 1;
3582 /* signed or unsigned */
3583 if (SPEC_USIGN(opetype)) {
3584 /* unsigned is easy */
3585 LOAD_AB_FOR_DIV(left, right, l);
3586 emitcode("div","ab");
3587 aopPut(AOP(result),"a",0);
3589 aopPut(AOP(result),zero,offset++);
3593 /* signed is a little bit more difficult */
3595 /* save the signs of the operands */
3596 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3598 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3599 emitcode("push","acc"); /* save it on the stack */
3601 /* now sign adjust for both left & right */
3602 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3604 lbl = newiTempLabel(NULL);
3605 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3606 emitcode("cpl","a");
3607 emitcode("inc","a");
3608 emitcode("","%05d$:",(lbl->key+100));
3609 emitcode("mov","b,a");
3611 /* sign adjust left side */
3612 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3615 lbl = newiTempLabel(NULL);
3616 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3617 emitcode("cpl","a");
3618 emitcode("inc","a");
3619 emitcode("","%05d$:",(lbl->key+100));
3621 /* now the division */
3622 emitcode("nop", "; workaround for DS80C390 div bug.");
3623 emitcode("div","ab");
3624 /* we are interested in the lower order
3626 emitcode("mov","b,a");
3627 lbl = newiTempLabel(NULL);
3628 emitcode("pop","acc");
3629 /* if there was an over flow we don't
3630 adjust the sign of the result */
3631 emitcode("jb","ov,%05d$",(lbl->key+100));
3632 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3634 emitcode("clr","a");
3635 emitcode("subb","a,b");
3636 emitcode("mov","b,a");
3637 emitcode("","%05d$:",(lbl->key+100));
3639 /* now we are done */
3640 aopPut(AOP(result),"b",0);
3642 emitcode("mov","c,b.7");
3643 emitcode("subb","a,acc");
3646 aopPut(AOP(result),"a",offset++);
3650 /*-----------------------------------------------------------------*/
3651 /* genDiv - generates code for division */
3652 /*-----------------------------------------------------------------*/
3653 static void genDiv (iCode *ic)
3655 operand *left = IC_LEFT(ic);
3656 operand *right = IC_RIGHT(ic);
3657 operand *result= IC_RESULT(ic);
3659 D(emitcode(";", "genDiv "););
3661 /* assign the amsops */
3664 aopOp (left,ic,FALSE, FALSE);
3665 aopOp (right,ic,FALSE, TRUE);
3666 aopOp (result,ic,TRUE, FALSE);
3669 /* special cases first */
3671 if (AOP_TYPE(left) == AOP_CRY &&
3672 AOP_TYPE(right)== AOP_CRY) {
3673 genDivbits(left,right,result);
3677 /* if both are of size == 1 */
3678 if (AOP_SIZE(left) == 1 &&
3679 AOP_SIZE(right) == 1 ) {
3680 genDivOneByte(left,right,result);
3684 /* should have been converted to function call */
3687 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3688 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3689 freeAsmop(result,NULL,ic,TRUE);
3692 /*-----------------------------------------------------------------*/
3693 /* genModbits :- modulus of bits */
3694 /*-----------------------------------------------------------------*/
3695 static void genModbits (operand *left,
3702 /* the result must be bit */
3703 LOAD_AB_FOR_DIV(left, right, l);
3704 emitcode("div","ab");
3705 emitcode("mov","a,b");
3706 emitcode("rrc","a");
3707 aopPut(AOP(result),"c",0);
3710 /*-----------------------------------------------------------------*/
3711 /* genModOneByte : 8 bit modulus */
3712 /*-----------------------------------------------------------------*/
3713 static void genModOneByte (operand *left,
3717 link *opetype = operandType(result);
3721 /* signed or unsigned */
3722 if (SPEC_USIGN(opetype)) {
3723 /* unsigned is easy */
3724 LOAD_AB_FOR_DIV(left, right, l);
3725 emitcode("div","ab");
3726 aopPut(AOP(result),"b",0);
3730 /* signed is a little bit more difficult */
3732 /* save the signs of the operands */
3733 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3736 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3737 emitcode("push","acc"); /* save it on the stack */
3739 /* now sign adjust for both left & right */
3740 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3743 lbl = newiTempLabel(NULL);
3744 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3745 emitcode("cpl","a");
3746 emitcode("inc","a");
3747 emitcode("","%05d$:",(lbl->key+100));
3748 emitcode("mov","b,a");
3750 /* sign adjust left side */
3751 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3754 lbl = newiTempLabel(NULL);
3755 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3756 emitcode("cpl","a");
3757 emitcode("inc","a");
3758 emitcode("","%05d$:",(lbl->key+100));
3760 /* now the multiplication */
3761 emitcode("nop", "; workaround for DS80C390 div bug.");
3762 emitcode("div","ab");
3763 /* we are interested in the lower order
3765 lbl = newiTempLabel(NULL);
3766 emitcode("pop","acc");
3767 /* if there was an over flow we don't
3768 adjust the sign of the result */
3769 emitcode("jb","ov,%05d$",(lbl->key+100));
3770 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3772 emitcode("clr","a");
3773 emitcode("subb","a,b");
3774 emitcode("mov","b,a");
3775 emitcode("","%05d$:",(lbl->key+100));
3777 /* now we are done */
3778 aopPut(AOP(result),"b",0);
3782 /*-----------------------------------------------------------------*/
3783 /* genMod - generates code for division */
3784 /*-----------------------------------------------------------------*/
3785 static void genMod (iCode *ic)
3787 operand *left = IC_LEFT(ic);
3788 operand *right = IC_RIGHT(ic);
3789 operand *result= IC_RESULT(ic);
3791 D(emitcode(";", "genMod "););
3793 /* assign the amsops */
3796 aopOp (left,ic,FALSE, FALSE);
3797 aopOp (right,ic,FALSE, TRUE);
3798 aopOp (result,ic,TRUE, FALSE);
3801 /* special cases first */
3803 if (AOP_TYPE(left) == AOP_CRY &&
3804 AOP_TYPE(right)== AOP_CRY) {
3805 genModbits(left,right,result);
3809 /* if both are of size == 1 */
3810 if (AOP_SIZE(left) == 1 &&
3811 AOP_SIZE(right) == 1 ) {
3812 genModOneByte(left,right,result);
3816 /* should have been converted to function call */
3820 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3821 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3822 freeAsmop(result,NULL,ic,TRUE);
3825 /*-----------------------------------------------------------------*/
3826 /* genIfxJump :- will create a jump depending on the ifx */
3827 /*-----------------------------------------------------------------*/
3828 static void genIfxJump (iCode *ic, char *jval)
3831 symbol *tlbl = newiTempLabel(NULL);
3834 D(emitcode(";", "genIfxJump "););
3836 /* if true label then we jump if condition
3838 if ( IC_TRUE(ic) ) {
3840 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3841 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3844 /* false label is present */
3845 jlbl = IC_FALSE(ic) ;
3846 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3847 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3849 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3850 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3852 emitcode(inst,"%05d$",tlbl->key+100);
3853 emitcode("ljmp","%05d$",jlbl->key+100);
3854 emitcode("","%05d$:",tlbl->key+100);
3856 /* mark the icode as generated */
3860 /*-----------------------------------------------------------------*/
3861 /* genCmp :- greater or less than comparison */
3862 /*-----------------------------------------------------------------*/
3863 static void genCmp (operand *left,operand *right,
3864 operand *result, iCode *ifx, int sign)
3866 int size, offset = 0 ;
3867 unsigned long lit = 0L;
3868 bool swappedOps = FALSE;
3870 D(emitcode(";", "genCmp"););
3873 /* If left if lit and right isn't, swap 'em. */
3874 if (AOP_TYPE(left) == AOP_LIT &&
3875 AOP_TYPE(right) != AOP_LIT)
3877 operand *tmp = left;
3880 D(emitcode(";", "kevin literal hack"););
3881 swappedOps = !swappedOps;
3884 if (AOP_NEEDSACC(right))
3886 if (AOP_NEEDSACC(left))
3888 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3889 "both CMP operands need ACC!");
3894 operand *tmp = left;
3897 D(emitcode(";", "kevin ACC hack"););
3898 swappedOps = !swappedOps;
3903 /* if left & right are bit variables */
3904 if (AOP_TYPE(left) == AOP_CRY &&
3905 AOP_TYPE(right) == AOP_CRY ) {
3906 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3907 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3909 /* subtract right from left if at the
3910 end the carry flag is set then we know that
3911 left is greater than right */
3912 size = max(AOP_SIZE(left),AOP_SIZE(right));
3914 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3915 if((size == 1) && !sign &&
3916 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3917 symbol *lbl = newiTempLabel(NULL);
3918 emitcode("cjne","%s,%s,%05d$",
3919 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3920 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3922 emitcode("","%05d$:",lbl->key+100);
3924 if(AOP_TYPE(right) == AOP_LIT){
3925 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3926 /* optimize if(x < 0) or if(x >= 0) */
3932 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3933 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3934 genIfxJump (ifx,"acc.7");
3938 emitcode("rlc","a");
3946 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3947 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3948 emitcode(";", "genCmp #2");
3949 if (sign && (size == 0))
3951 emitcode(";", "genCmp #3");
3952 emitcode("xrl","a,#0x80");
3953 if (AOP_TYPE(right) == AOP_LIT)
3955 unsigned long lit = (unsigned long)
3956 floatFromVal(AOP(right)->aopu.aop_lit);
3957 emitcode(";", "genCmp #3.1");
3958 emitcode("subb","a,#0x%02x",
3959 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3963 emitcode(";", "genCmp #3.2");
3964 if (AOP_NEEDSACC(right))
3966 emitcode("push", "acc");
3968 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3969 FALSE,FALSE,FALSE));
3970 emitcode("xrl","b,#0x80");
3971 if (AOP_NEEDSACC(right))
3973 emitcode("pop", "acc");
3975 emitcode("subb","a,b");
3982 emitcode(";", "genCmp #4");
3983 if (AOP_NEEDSACC(right))
3986 emitcode(";", "genCmp #4.1");
3987 emitcode("xch", "a, b");
3988 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3989 emitcode("xch", "a, b");
3994 emitcode(";", "genCmp #4.2");
3995 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
3998 emitcode("subb","a,%s",s);
4007 D(emitcode(";","kevHack: flip carry."););
4008 emitcode("cpl", "c");
4011 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4014 /* if the result is used in the next
4015 ifx conditional branch then generate
4016 code a little differently */
4018 genIfxJump (ifx,"c");
4021 /* leave the result in acc */
4025 /*-----------------------------------------------------------------*/
4026 /* genCmpGt :- greater than comparison */
4027 /*-----------------------------------------------------------------*/
4028 static void genCmpGt (iCode *ic, iCode *ifx)
4030 operand *left, *right, *result;
4031 link *letype , *retype;
4034 D(emitcode(";", "genCmpGt "););
4037 right= IC_RIGHT(ic);
4038 result = IC_RESULT(ic);
4040 letype = getSpec(operandType(left));
4041 retype =getSpec(operandType(right));
4042 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4043 /* assign the amsops */
4046 aopOp (left,ic,FALSE, TRUE);
4047 aopOp (right,ic,FALSE, FALSE);
4048 aopOp (result,ic,TRUE, FALSE);
4051 genCmp(right, left, result, ifx, sign);
4053 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4054 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4055 freeAsmop(result,NULL,ic,TRUE);
4058 /*-----------------------------------------------------------------*/
4059 /* genCmpLt - less than comparisons */
4060 /*-----------------------------------------------------------------*/
4061 static void genCmpLt (iCode *ic, iCode *ifx)
4063 operand *left, *right, *result;
4064 link *letype , *retype;
4067 D(emitcode(";", "genCmpLt "););
4070 right= IC_RIGHT(ic);
4071 result = IC_RESULT(ic);
4073 letype = getSpec(operandType(left));
4074 retype =getSpec(operandType(right));
4075 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4077 /* assign the amsops */
4080 aopOp (left,ic,FALSE, FALSE);
4081 aopOp (right,ic,FALSE, TRUE);
4082 aopOp (result,ic,TRUE, FALSE);
4085 genCmp(left, right, result, ifx, sign);
4087 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4088 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4089 freeAsmop(result,NULL,ic,TRUE);
4092 /*-----------------------------------------------------------------*/
4093 /* gencjneshort - compare and jump if not equal */
4094 /*-----------------------------------------------------------------*/
4095 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4097 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4099 unsigned long lit = 0L;
4101 D(emitcode(";", "gencjneshort"););
4103 /* if the left side is a literal or
4104 if the right is in a pointer register and left
4106 if ((AOP_TYPE(left) == AOP_LIT) ||
4107 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4113 if(AOP_TYPE(right) == AOP_LIT)
4114 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4116 if (opIsGptr(left) || opIsGptr(right))
4118 /* We are comparing a generic pointer to something.
4119 * Exclude the generic type byte from the comparison.
4122 D(emitcode(";", "cjneshort: generic ptr special case.");)
4126 /* if the right side is a literal then anything goes */
4127 if (AOP_TYPE(right) == AOP_LIT &&
4128 AOP_TYPE(left) != AOP_DIR ) {
4130 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4132 emitcode("cjne","a,%s,%05d$",
4133 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4139 /* if the right side is in a register or in direct space or
4140 if the left is a pointer register & right is not */
4141 else if (AOP_TYPE(right) == AOP_REG ||
4142 AOP_TYPE(right) == AOP_DIR ||
4143 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4144 (IS_AOP_PREG(left) && !IS_AOP_PREG(right)))
4148 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4149 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4150 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4151 emitcode("jnz","%05d$",lbl->key+100);
4153 emitcode("cjne","a,%s,%05d$",
4154 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4159 /* right is a pointer reg need both a & b */
4161 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4163 emitcode("mov","b,%s",l);
4164 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4165 emitcode("cjne","a,b,%05d$",lbl->key+100);
4171 /*-----------------------------------------------------------------*/
4172 /* gencjne - compare and jump if not equal */
4173 /*-----------------------------------------------------------------*/
4174 static void gencjne(operand *left, operand *right, symbol *lbl)
4176 symbol *tlbl = newiTempLabel(NULL);
4178 D(emitcode(";", "gencjne"););
4180 gencjneshort(left, right, lbl);
4182 emitcode("mov","a,%s",one);
4183 emitcode("sjmp","%05d$",tlbl->key+100);
4184 emitcode("","%05d$:",lbl->key+100);
4185 emitcode("clr","a");
4186 emitcode("","%05d$:",tlbl->key+100);
4189 /*-----------------------------------------------------------------*/
4190 /* genCmpEq - generates code for equal to */
4191 /*-----------------------------------------------------------------*/
4192 static void genCmpEq (iCode *ic, iCode *ifx)
4194 operand *left, *right, *result;
4196 D(emitcode(";", "genCmpEq "););
4201 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4202 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4203 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4206 /* if literal, literal on the right or
4207 if the right is in a pointer register and left
4209 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4210 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4211 operand *t = IC_RIGHT(ic);
4212 IC_RIGHT(ic) = IC_LEFT(ic);
4216 if(ifx && !AOP_SIZE(result)){
4218 /* if they are both bit variables */
4219 if (AOP_TYPE(left) == AOP_CRY &&
4220 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4221 if(AOP_TYPE(right) == AOP_LIT){
4222 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4224 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4225 emitcode("cpl","c");
4226 } else if(lit == 1L) {
4227 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4229 emitcode("clr","c");
4231 /* AOP_TYPE(right) == AOP_CRY */
4233 symbol *lbl = newiTempLabel(NULL);
4234 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4235 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4236 emitcode("cpl","c");
4237 emitcode("","%05d$:",(lbl->key+100));
4239 /* if true label then we jump if condition
4241 tlbl = newiTempLabel(NULL);
4242 if ( IC_TRUE(ifx) ) {
4243 emitcode("jnc","%05d$",tlbl->key+100);
4244 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4246 emitcode("jc","%05d$",tlbl->key+100);
4247 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4249 emitcode("","%05d$:",tlbl->key+100);
4251 tlbl = newiTempLabel(NULL);
4252 gencjneshort(left, right, tlbl);
4253 if ( IC_TRUE(ifx) ) {
4254 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4255 emitcode("","%05d$:",tlbl->key+100);
4257 symbol *lbl = newiTempLabel(NULL);
4258 emitcode("sjmp","%05d$",lbl->key+100);
4259 emitcode("","%05d$:",tlbl->key+100);
4260 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4261 emitcode("","%05d$:",lbl->key+100);
4264 /* mark the icode as generated */
4269 /* if they are both bit variables */
4270 if (AOP_TYPE(left) == AOP_CRY &&
4271 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4272 if(AOP_TYPE(right) == AOP_LIT){
4273 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4275 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4276 emitcode("cpl","c");
4277 } else if(lit == 1L) {
4278 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4280 emitcode("clr","c");
4282 /* AOP_TYPE(right) == AOP_CRY */
4284 symbol *lbl = newiTempLabel(NULL);
4285 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4286 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4287 emitcode("cpl","c");
4288 emitcode("","%05d$:",(lbl->key+100));
4291 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4296 genIfxJump (ifx,"c");
4299 /* if the result is used in an arithmetic operation
4300 then put the result in place */
4303 gencjne(left,right,newiTempLabel(NULL));
4304 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4305 aopPut(AOP(result),"a",0);
4309 genIfxJump (ifx,"a");
4312 /* if the result is used in an arithmetic operation
4313 then put the result in place */
4314 if (AOP_TYPE(result) != AOP_CRY)
4316 /* leave the result in acc */
4320 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4321 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4322 freeAsmop(result,NULL,ic,TRUE);
4325 /*-----------------------------------------------------------------*/
4326 /* ifxForOp - returns the icode containing the ifx for operand */
4327 /*-----------------------------------------------------------------*/
4328 static iCode *ifxForOp ( operand *op, iCode *ic )
4330 /* if true symbol then needs to be assigned */
4331 if (IS_TRUE_SYMOP(op))
4334 /* if this has register type condition and
4335 the next instruction is ifx with the same operand
4336 and live to of the operand is upto the ifx only then */
4338 ic->next->op == IFX &&
4339 IC_COND(ic->next)->key == op->key &&
4340 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4345 /*-----------------------------------------------------------------*/
4346 /* genAndOp - for && operation */
4347 /*-----------------------------------------------------------------*/
4348 static void genAndOp (iCode *ic)
4350 operand *left,*right, *result;
4353 D(emitcode(";", "genAndOp "););
4355 /* note here that && operations that are in an
4356 if statement are taken away by backPatchLabels
4357 only those used in arthmetic operations remain */
4361 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4362 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4363 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4366 /* if both are bit variables */
4367 if (AOP_TYPE(left) == AOP_CRY &&
4368 AOP_TYPE(right) == AOP_CRY ) {
4369 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4370 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4373 tlbl = newiTempLabel(NULL);
4375 emitcode("jz","%05d$",tlbl->key+100);
4377 emitcode("","%05d$:",tlbl->key+100);
4381 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4382 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4383 freeAsmop(result,NULL,ic,TRUE);
4387 /*-----------------------------------------------------------------*/
4388 /* genOrOp - for || operation */
4389 /*-----------------------------------------------------------------*/
4390 static void genOrOp (iCode *ic)
4392 operand *left,*right, *result;
4395 D(emitcode(";", "genOrOp "););
4397 /* note here that || operations that are in an
4398 if statement are taken away by backPatchLabels
4399 only those used in arthmetic operations remain */
4403 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4404 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4405 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4408 /* if both are bit variables */
4409 if (AOP_TYPE(left) == AOP_CRY &&
4410 AOP_TYPE(right) == AOP_CRY ) {
4411 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4412 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4415 tlbl = newiTempLabel(NULL);
4417 emitcode("jnz","%05d$",tlbl->key+100);
4419 emitcode("","%05d$:",tlbl->key+100);
4423 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4424 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4425 freeAsmop(result,NULL,ic,TRUE);
4428 /*-----------------------------------------------------------------*/
4429 /* isLiteralBit - test if lit == 2^n */
4430 /*-----------------------------------------------------------------*/
4431 static int isLiteralBit(unsigned long lit)
4433 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4434 0x100L,0x200L,0x400L,0x800L,
4435 0x1000L,0x2000L,0x4000L,0x8000L,
4436 0x10000L,0x20000L,0x40000L,0x80000L,
4437 0x100000L,0x200000L,0x400000L,0x800000L,
4438 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4439 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4442 for(idx = 0; idx < 32; idx++)
4448 /*-----------------------------------------------------------------*/
4449 /* continueIfTrue - */
4450 /*-----------------------------------------------------------------*/
4451 static void continueIfTrue (iCode *ic)
4454 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4458 /*-----------------------------------------------------------------*/
4460 /*-----------------------------------------------------------------*/
4461 static void jumpIfTrue (iCode *ic)
4464 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4468 /*-----------------------------------------------------------------*/
4469 /* jmpTrueOrFalse - */
4470 /*-----------------------------------------------------------------*/
4471 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4473 // ugly but optimized by peephole
4475 symbol *nlbl = newiTempLabel(NULL);
4476 emitcode("sjmp","%05d$",nlbl->key+100);
4477 emitcode("","%05d$:",tlbl->key+100);
4478 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4479 emitcode("","%05d$:",nlbl->key+100);
4482 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4483 emitcode("","%05d$:",tlbl->key+100);
4488 /*-----------------------------------------------------------------*/
4489 /* genAnd - code for and */
4490 /*-----------------------------------------------------------------*/
4491 static void genAnd (iCode *ic, iCode *ifx)
4493 operand *left, *right, *result;
4495 unsigned long lit = 0L;
4499 D(emitcode(";", "genAnd "););
4504 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4505 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4506 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4510 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4512 AOP_TYPE(left), AOP_TYPE(right));
4513 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4515 AOP_SIZE(left), AOP_SIZE(right));
4518 /* if left is a literal & right is not then exchange them */
4519 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4520 AOP_NEEDSACC(left)) {
4521 operand *tmp = right ;
4526 /* if result = right then exchange them */
4527 if(sameRegs(AOP(result),AOP(right))){
4528 operand *tmp = right ;
4533 /* if right is bit then exchange them */
4534 if (AOP_TYPE(right) == AOP_CRY &&
4535 AOP_TYPE(left) != AOP_CRY){
4536 operand *tmp = right ;
4540 if(AOP_TYPE(right) == AOP_LIT)
4541 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4543 size = AOP_SIZE(result);
4546 // result = bit & yy;
4547 if (AOP_TYPE(left) == AOP_CRY){
4548 // c = bit & literal;
4549 if(AOP_TYPE(right) == AOP_LIT){
4551 if(size && sameRegs(AOP(result),AOP(left)))
4554 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4557 if(size && (AOP_TYPE(result) == AOP_CRY)){
4558 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4561 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4565 emitcode("clr","c");
4568 if (AOP_TYPE(right) == AOP_CRY){
4570 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4571 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4574 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4576 emitcode("rrc","a");
4577 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4585 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4586 genIfxJump(ifx, "c");
4590 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4591 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4592 if((AOP_TYPE(right) == AOP_LIT) &&
4593 (AOP_TYPE(result) == AOP_CRY) &&
4594 (AOP_TYPE(left) != AOP_CRY)){
4595 int posbit = isLiteralBit(lit);
4599 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4602 emitcode("mov","c,acc.%d",posbit&0x07);
4606 sprintf(buffer,"acc.%d",posbit&0x07);
4607 genIfxJump(ifx, buffer);
4612 symbol *tlbl = newiTempLabel(NULL);
4613 int sizel = AOP_SIZE(left);
4615 emitcode("setb","c");
4617 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4618 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4620 if((posbit = isLiteralBit(bytelit)) != 0)
4621 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4623 if(bytelit != 0x0FFL)
4624 emitcode("anl","a,%s",
4625 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4626 emitcode("jnz","%05d$",tlbl->key+100);
4631 // bit = left & literal
4633 emitcode("clr","c");
4634 emitcode("","%05d$:",tlbl->key+100);
4636 // if(left & literal)
4639 jmpTrueOrFalse(ifx, tlbl);
4647 /* if left is same as result */
4648 if(sameRegs(AOP(result),AOP(left))){
4649 for(;size--; offset++) {
4650 if(AOP_TYPE(right) == AOP_LIT){
4651 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4655 aopPut(AOP(result),zero,offset);
4657 if (IS_AOP_PREG(result)) {
4658 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4659 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4660 aopPut(AOP(result),"a",offset);
4662 emitcode("anl","%s,%s",
4663 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4664 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4666 if (AOP_TYPE(left) == AOP_ACC)
4667 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4669 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4670 if (IS_AOP_PREG(result)) {
4671 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4672 aopPut(AOP(result),"a",offset);
4675 emitcode("anl","%s,a",
4676 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4681 // left & result in different registers
4682 if(AOP_TYPE(result) == AOP_CRY){
4684 // if(size), result in bit
4685 // if(!size && ifx), conditional oper: if(left & right)
4686 symbol *tlbl = newiTempLabel(NULL);
4687 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4689 emitcode("setb","c");
4691 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4692 emitcode("anl","a,%s",
4693 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4694 emitcode("jnz","%05d$",tlbl->key+100);
4699 emitcode("","%05d$:",tlbl->key+100);
4702 jmpTrueOrFalse(ifx, tlbl);
4704 for(;(size--);offset++) {
4706 // result = left & right
4707 if(AOP_TYPE(right) == AOP_LIT){
4708 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4710 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4713 } else if(bytelit == 0){
4714 aopPut(AOP(result),zero,offset);
4718 // faster than result <- left, anl result,right
4719 // and better if result is SFR
4720 if (AOP_TYPE(left) == AOP_ACC)
4721 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4723 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4724 emitcode("anl","a,%s",
4725 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4727 aopPut(AOP(result),"a",offset);
4733 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4734 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4735 freeAsmop(result,NULL,ic,TRUE);
4738 /*-----------------------------------------------------------------*/
4739 /* genOr - code for or */
4740 /*-----------------------------------------------------------------*/
4741 static void genOr (iCode *ic, iCode *ifx)
4743 operand *left, *right, *result;
4745 unsigned long lit = 0L;
4747 D(emitcode(";", "genOr "););
4752 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4753 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4754 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4758 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4760 AOP_TYPE(left), AOP_TYPE(right));
4761 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4763 AOP_SIZE(left), AOP_SIZE(right));
4766 /* if left is a literal & right is not then exchange them */
4767 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4768 AOP_NEEDSACC(left)) {
4769 operand *tmp = right ;
4774 /* if result = right then exchange them */
4775 if(sameRegs(AOP(result),AOP(right))){
4776 operand *tmp = right ;
4781 /* if right is bit then exchange them */
4782 if (AOP_TYPE(right) == AOP_CRY &&
4783 AOP_TYPE(left) != AOP_CRY){
4784 operand *tmp = right ;
4788 if(AOP_TYPE(right) == AOP_LIT)
4789 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4791 size = AOP_SIZE(result);
4795 if (AOP_TYPE(left) == AOP_CRY){
4796 if(AOP_TYPE(right) == AOP_LIT){
4797 // c = bit & literal;
4799 // lit != 0 => result = 1
4800 if(AOP_TYPE(result) == AOP_CRY){
4802 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4804 continueIfTrue(ifx);
4807 emitcode("setb","c");
4809 // lit == 0 => result = left
4810 if(size && sameRegs(AOP(result),AOP(left)))
4812 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4815 if (AOP_TYPE(right) == AOP_CRY){
4817 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4818 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4822 symbol *tlbl = newiTempLabel(NULL);
4823 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4824 emitcode("setb","c");
4825 emitcode("jb","%s,%05d$",
4826 AOP(left)->aopu.aop_dir,tlbl->key+100);
4828 emitcode("jnz","%05d$",tlbl->key+100);
4829 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4830 jmpTrueOrFalse(ifx, tlbl);
4834 emitcode("","%05d$:",tlbl->key+100);
4843 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4844 genIfxJump(ifx, "c");
4848 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4849 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4850 if((AOP_TYPE(right) == AOP_LIT) &&
4851 (AOP_TYPE(result) == AOP_CRY) &&
4852 (AOP_TYPE(left) != AOP_CRY)){
4856 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4858 continueIfTrue(ifx);
4861 // lit = 0, result = boolean(left)
4863 emitcode("setb","c");
4866 symbol *tlbl = newiTempLabel(NULL);
4867 emitcode("jnz","%05d$",tlbl->key+100);
4869 emitcode("","%05d$:",tlbl->key+100);
4871 genIfxJump (ifx,"a");
4879 /* if left is same as result */
4880 if(sameRegs(AOP(result),AOP(left))){
4881 for(;size--; offset++) {
4882 if(AOP_TYPE(right) == AOP_LIT){
4883 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4886 if (IS_AOP_PREG(left)) {
4887 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4888 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4889 aopPut(AOP(result),"a",offset);
4891 emitcode("orl","%s,%s",
4892 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4893 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4895 if (AOP_TYPE(left) == AOP_ACC)
4896 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4898 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4899 if (IS_AOP_PREG(left)) {
4900 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4901 aopPut(AOP(result),"a",offset);
4903 emitcode("orl","%s,a",
4904 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4909 // left & result in different registers
4910 if(AOP_TYPE(result) == AOP_CRY){
4912 // if(size), result in bit
4913 // if(!size && ifx), conditional oper: if(left | right)
4914 symbol *tlbl = newiTempLabel(NULL);
4915 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4917 emitcode("setb","c");
4919 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4920 emitcode("orl","a,%s",
4921 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4922 emitcode("jnz","%05d$",tlbl->key+100);
4927 emitcode("","%05d$:",tlbl->key+100);
4930 jmpTrueOrFalse(ifx, tlbl);
4931 } else for(;(size--);offset++){
4933 // result = left & right
4934 if(AOP_TYPE(right) == AOP_LIT){
4935 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4937 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4942 // faster than result <- left, anl result,right
4943 // and better if result is SFR
4944 if (AOP_TYPE(left) == AOP_ACC)
4945 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4947 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4948 emitcode("orl","a,%s",
4949 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4951 aopPut(AOP(result),"a",offset);
4956 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4957 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4958 freeAsmop(result,NULL,ic,TRUE);
4961 /*-----------------------------------------------------------------*/
4962 /* genXor - code for xclusive or */
4963 /*-----------------------------------------------------------------*/
4964 static void genXor (iCode *ic, iCode *ifx)
4966 operand *left, *right, *result;
4968 unsigned long lit = 0L;
4970 D(emitcode(";", "genXor "););
4975 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4976 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4977 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4981 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4983 AOP_TYPE(left), AOP_TYPE(right));
4984 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4986 AOP_SIZE(left), AOP_SIZE(right));
4989 /* if left is a literal & right is not ||
4990 if left needs acc & right does not */
4991 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4992 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4993 operand *tmp = right ;
4998 /* if result = right then exchange them */
4999 if(sameRegs(AOP(result),AOP(right))){
5000 operand *tmp = right ;
5005 /* if right is bit then exchange them */
5006 if (AOP_TYPE(right) == AOP_CRY &&
5007 AOP_TYPE(left) != AOP_CRY){
5008 operand *tmp = right ;
5012 if(AOP_TYPE(right) == AOP_LIT)
5013 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5015 size = AOP_SIZE(result);
5019 if (AOP_TYPE(left) == AOP_CRY){
5020 if(AOP_TYPE(right) == AOP_LIT){
5021 // c = bit & literal;
5023 // lit>>1 != 0 => result = 1
5024 if(AOP_TYPE(result) == AOP_CRY){
5026 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5028 continueIfTrue(ifx);
5031 emitcode("setb","c");
5035 // lit == 0, result = left
5036 if(size && sameRegs(AOP(result),AOP(left)))
5038 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5040 // lit == 1, result = not(left)
5041 if(size && sameRegs(AOP(result),AOP(left))){
5042 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5045 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5046 emitcode("cpl","c");
5053 symbol *tlbl = newiTempLabel(NULL);
5054 if (AOP_TYPE(right) == AOP_CRY){
5056 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5059 int sizer = AOP_SIZE(right);
5061 // if val>>1 != 0, result = 1
5062 emitcode("setb","c");
5064 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5066 // test the msb of the lsb
5067 emitcode("anl","a,#0xfe");
5068 emitcode("jnz","%05d$",tlbl->key+100);
5072 emitcode("rrc","a");
5074 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5075 emitcode("cpl","c");
5076 emitcode("","%05d$:",(tlbl->key+100));
5083 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5084 genIfxJump(ifx, "c");
5088 if(sameRegs(AOP(result),AOP(left))){
5089 /* if left is same as result */
5090 for(;size--; offset++) {
5091 if(AOP_TYPE(right) == AOP_LIT){
5092 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5095 if (IS_AOP_PREG(left)) {
5096 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5097 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5098 aopPut(AOP(result),"a",offset);
5100 emitcode("xrl","%s,%s",
5101 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5102 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5104 if (AOP_TYPE(left) == AOP_ACC)
5105 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5107 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5108 if (IS_AOP_PREG(left)) {
5109 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5110 aopPut(AOP(result),"a",offset);
5112 emitcode("xrl","%s,a",
5113 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5118 // left & result in different registers
5119 if(AOP_TYPE(result) == AOP_CRY){
5121 // if(size), result in bit
5122 // if(!size && ifx), conditional oper: if(left ^ right)
5123 symbol *tlbl = newiTempLabel(NULL);
5124 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5126 emitcode("setb","c");
5128 if((AOP_TYPE(right) == AOP_LIT) &&
5129 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5130 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5132 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5133 emitcode("xrl","a,%s",
5134 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5136 emitcode("jnz","%05d$",tlbl->key+100);
5141 emitcode("","%05d$:",tlbl->key+100);
5144 jmpTrueOrFalse(ifx, tlbl);
5145 } else for(;(size--);offset++){
5147 // result = left & right
5148 if(AOP_TYPE(right) == AOP_LIT){
5149 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
5151 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5156 // faster than result <- left, anl result,right
5157 // and better if result is SFR
5158 if (AOP_TYPE(left) == AOP_ACC)
5159 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5161 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5162 emitcode("xrl","a,%s",
5163 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5165 aopPut(AOP(result),"a",offset);
5170 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5171 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5172 freeAsmop(result,NULL,ic,TRUE);
5175 /*-----------------------------------------------------------------*/
5176 /* genInline - write the inline code out */
5177 /*-----------------------------------------------------------------*/
5178 static void genInline (iCode *ic)
5180 char buffer[MAX_INLINEASM];
5184 D(emitcode(";", "genInline "););
5186 _G.inLine += (!options.asmpeep);
5187 strcpy(buffer,IC_INLINE(ic));
5189 /* emit each line as a code */
5208 /* emitcode("",buffer); */
5209 _G.inLine -= (!options.asmpeep);
5212 /*-----------------------------------------------------------------*/
5213 /* genRRC - rotate right with carry */
5214 /*-----------------------------------------------------------------*/
5215 static void genRRC (iCode *ic)
5217 operand *left , *result ;
5218 int size, offset = 0;
5221 D(emitcode(";", "genRRC "););
5223 /* rotate right with carry */
5225 result=IC_RESULT(ic);
5226 aopOp (left,ic,FALSE, FALSE);
5227 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5229 /* move it to the result */
5230 size = AOP_SIZE(result);
5234 _startLazyDPSEvaluation();
5236 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5238 emitcode("rrc","a");
5239 if (AOP_SIZE(result) > 1)
5240 aopPut(AOP(result),"a",offset--);
5242 _endLazyDPSEvaluation();
5244 /* now we need to put the carry into the
5245 highest order byte of the result */
5246 if (AOP_SIZE(result) > 1) {
5247 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5250 emitcode("mov","acc.7,c");
5251 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5252 freeAsmop(left,NULL,ic,TRUE);
5253 freeAsmop(result,NULL,ic,TRUE);
5256 /*-----------------------------------------------------------------*/
5257 /* genRLC - generate code for rotate left with carry */
5258 /*-----------------------------------------------------------------*/
5259 static void genRLC (iCode *ic)
5261 operand *left , *result ;
5262 int size, offset = 0;
5265 D(emitcode(";", "genRLC "););
5267 /* rotate right with carry */
5269 result=IC_RESULT(ic);
5270 aopOp (left,ic,FALSE, FALSE);
5271 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5273 /* move it to the result */
5274 size = AOP_SIZE(result);
5277 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5279 emitcode("add","a,acc");
5280 if (AOP_SIZE(result) > 1)
5282 aopPut(AOP(result),"a",offset++);
5285 _startLazyDPSEvaluation();
5287 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5289 emitcode("rlc","a");
5290 if (AOP_SIZE(result) > 1)
5291 aopPut(AOP(result),"a",offset++);
5293 _endLazyDPSEvaluation();
5295 /* now we need to put the carry into the
5296 highest order byte of the result */
5297 if (AOP_SIZE(result) > 1) {
5298 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5301 emitcode("mov","acc.0,c");
5302 aopPut(AOP(result),"a",0);
5303 freeAsmop(left,NULL,ic,TRUE);
5304 freeAsmop(result,NULL,ic,TRUE);
5307 /*-----------------------------------------------------------------*/
5308 /* genGetHbit - generates code get highest order bit */
5309 /*-----------------------------------------------------------------*/
5310 static void genGetHbit (iCode *ic)
5312 operand *left, *result;
5314 result=IC_RESULT(ic);
5315 aopOp (left,ic,FALSE, FALSE);
5316 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5318 D(emitcode(";", "genGetHbit "););
5320 /* get the highest order byte into a */
5321 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5322 if(AOP_TYPE(result) == AOP_CRY){
5323 emitcode("rlc","a");
5328 emitcode("anl","a,#0x01");
5333 freeAsmop(left,NULL,ic,TRUE);
5334 freeAsmop(result,NULL,ic,TRUE);
5337 /*-----------------------------------------------------------------*/
5338 /* AccRol - rotate left accumulator by known count */
5339 /*-----------------------------------------------------------------*/
5340 static void AccRol (int shCount)
5342 shCount &= 0x0007; // shCount : 0..7
5354 emitcode("swap","a");
5358 emitcode("swap","a");
5361 emitcode("swap","a");
5374 /*-----------------------------------------------------------------*/
5375 /* AccLsh - left shift accumulator by known count */
5376 /*-----------------------------------------------------------------*/
5377 static void AccLsh (int shCount)
5381 emitcode("add","a,acc");
5384 emitcode("add","a,acc");
5385 emitcode("add","a,acc");
5387 /* rotate left accumulator */
5389 /* and kill the lower order bits */
5390 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5395 /*-----------------------------------------------------------------*/
5396 /* AccRsh - right shift accumulator by known count */
5397 /*-----------------------------------------------------------------*/
5398 static void AccRsh (int shCount)
5403 emitcode("rrc","a");
5405 /* rotate right accumulator */
5406 AccRol(8 - shCount);
5407 /* and kill the higher order bits */
5408 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5413 /*-----------------------------------------------------------------*/
5414 /* AccSRsh - signed right shift accumulator by known count */
5415 /*-----------------------------------------------------------------*/
5416 static void AccSRsh (int shCount)
5421 emitcode("mov","c,acc.7");
5422 emitcode("rrc","a");
5423 } else if(shCount == 2){
5424 emitcode("mov","c,acc.7");
5425 emitcode("rrc","a");
5426 emitcode("mov","c,acc.7");
5427 emitcode("rrc","a");
5429 tlbl = newiTempLabel(NULL);
5430 /* rotate right accumulator */
5431 AccRol(8 - shCount);
5432 /* and kill the higher order bits */
5433 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5434 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5435 emitcode("orl","a,#0x%02x",
5436 (unsigned char)~SRMask[shCount]);
5437 emitcode("","%05d$:",tlbl->key+100);
5442 /*-----------------------------------------------------------------*/
5443 /* shiftR1Left2Result - shift right one byte from left to result */
5444 /*-----------------------------------------------------------------*/
5445 static void shiftR1Left2Result (operand *left, int offl,
5446 operand *result, int offr,
5447 int shCount, int sign)
5449 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5450 /* shift right accumulator */
5455 aopPut(AOP(result),"a",offr);
5458 /*-----------------------------------------------------------------*/
5459 /* shiftL1Left2Result - shift left one byte from left to result */
5460 /*-----------------------------------------------------------------*/
5461 static void shiftL1Left2Result (operand *left, int offl,
5462 operand *result, int offr, int shCount)
5465 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5467 /* shift left accumulator */
5469 aopPut(AOP(result),"a",offr);
5472 /*-----------------------------------------------------------------*/
5473 /* movLeft2Result - move byte from left to result */
5474 /*-----------------------------------------------------------------*/
5475 static void movLeft2Result (operand *left, int offl,
5476 operand *result, int offr, int sign)
5479 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5480 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5482 if (*l == '@' && (IS_AOP_PREG(result))) {
5483 emitcode("mov","a,%s",l);
5484 aopPut(AOP(result),"a",offr);
5487 aopPut(AOP(result),l,offr);
5489 /* MSB sign in acc.7 ! */
5490 if(getDataSize(left) == offl+1){
5491 emitcode("mov","a,%s",l);
5492 aopPut(AOP(result),"a",offr);
5499 /*-----------------------------------------------------------------*/
5500 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5501 /*-----------------------------------------------------------------*/
5502 static void AccAXRrl1 (char *x)
5504 emitcode("rrc","a");
5505 emitcode("xch","a,%s", x);
5506 emitcode("rrc","a");
5507 emitcode("xch","a,%s", x);
5510 /*-----------------------------------------------------------------*/
5511 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5512 /*-----------------------------------------------------------------*/
5513 static void AccAXLrl1 (char *x)
5515 emitcode("xch","a,%s",x);
5516 emitcode("rlc","a");
5517 emitcode("xch","a,%s",x);
5518 emitcode("rlc","a");
5521 /*-----------------------------------------------------------------*/
5522 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5523 /*-----------------------------------------------------------------*/
5524 static void AccAXLsh1 (char *x)
5526 emitcode("xch","a,%s",x);
5527 emitcode("add","a,acc");
5528 emitcode("xch","a,%s",x);
5529 emitcode("rlc","a");
5532 /*-----------------------------------------------------------------*/
5533 /* AccAXLsh - left shift a:x by known count (0..7) */
5534 /*-----------------------------------------------------------------*/
5535 static void AccAXLsh (char *x, int shCount)
5549 case 5 : // AAAAABBB:CCCCCDDD
5550 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5551 emitcode("anl","a,#0x%02x",
5552 SLMask[shCount]); // BBB00000:CCCCCDDD
5553 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5554 AccRol(shCount); // DDDCCCCC:BBB00000
5555 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5556 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5557 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5558 emitcode("anl","a,#0x%02x",
5559 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5560 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5561 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5563 case 6 : // AAAAAABB:CCCCCCDD
5564 emitcode("anl","a,#0x%02x",
5565 SRMask[shCount]); // 000000BB:CCCCCCDD
5566 emitcode("mov","c,acc.0"); // c = B
5567 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5568 AccAXRrl1(x); // BCCCCCCD:D000000B
5569 AccAXRrl1(x); // BBCCCCCC:DD000000
5571 case 7 : // a:x <<= 7
5572 emitcode("anl","a,#0x%02x",
5573 SRMask[shCount]); // 0000000B:CCCCCCCD
5574 emitcode("mov","c,acc.0"); // c = B
5575 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5576 AccAXRrl1(x); // BCCCCCCC:D0000000
5583 /*-----------------------------------------------------------------*/
5584 /* AccAXRsh - right shift a:x known count (0..7) */
5585 /*-----------------------------------------------------------------*/
5586 static void AccAXRsh (char *x, int shCount)
5593 AccAXRrl1(x); // 0->a:x
5597 AccAXRrl1(x); // 0->a:x
5599 AccAXRrl1(x); // 0->a:x
5603 case 5 : // AAAAABBB:CCCCCDDD = a:x
5604 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5605 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5606 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5607 emitcode("anl","a,#0x%02x",
5608 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5609 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5610 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5611 emitcode("anl","a,#0x%02x",
5612 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5613 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5614 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5615 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5617 case 6 : // AABBBBBB:CCDDDDDD
5618 emitcode("mov","c,acc.7");
5619 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5620 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5621 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5622 emitcode("anl","a,#0x%02x",
5623 SRMask[shCount]); // 000000AA:BBBBBBCC
5625 case 7 : // ABBBBBBB:CDDDDDDD
5626 emitcode("mov","c,acc.7"); // c = A
5627 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5628 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5629 emitcode("anl","a,#0x%02x",
5630 SRMask[shCount]); // 0000000A:BBBBBBBC
5637 /*-----------------------------------------------------------------*/
5638 /* AccAXRshS - right shift signed a:x known count (0..7) */
5639 /*-----------------------------------------------------------------*/
5640 static void AccAXRshS (char *x, int shCount)
5647 emitcode("mov","c,acc.7");
5648 AccAXRrl1(x); // s->a:x
5651 emitcode("mov","c,acc.7");
5652 AccAXRrl1(x); // s->a:x
5653 emitcode("mov","c,acc.7");
5654 AccAXRrl1(x); // s->a:x
5658 case 5 : // AAAAABBB:CCCCCDDD = a:x
5659 tlbl = newiTempLabel(NULL);
5660 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5661 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5662 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5663 emitcode("anl","a,#0x%02x",
5664 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5665 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5666 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5667 emitcode("anl","a,#0x%02x",
5668 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5669 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5670 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5671 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5672 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5673 emitcode("orl","a,#0x%02x",
5674 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5675 emitcode("","%05d$:",tlbl->key+100);
5676 break; // SSSSAAAA:BBBCCCCC
5677 case 6 : // AABBBBBB:CCDDDDDD
5678 tlbl = newiTempLabel(NULL);
5679 emitcode("mov","c,acc.7");
5680 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5681 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5682 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5683 emitcode("anl","a,#0x%02x",
5684 SRMask[shCount]); // 000000AA:BBBBBBCC
5685 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5686 emitcode("orl","a,#0x%02x",
5687 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5688 emitcode("","%05d$:",tlbl->key+100);
5690 case 7 : // ABBBBBBB:CDDDDDDD
5691 tlbl = newiTempLabel(NULL);
5692 emitcode("mov","c,acc.7"); // c = A
5693 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5694 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5695 emitcode("anl","a,#0x%02x",
5696 SRMask[shCount]); // 0000000A:BBBBBBBC
5697 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5698 emitcode("orl","a,#0x%02x",
5699 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5700 emitcode("","%05d$:",tlbl->key+100);
5707 /*-----------------------------------------------------------------*/
5708 /* shiftL2Left2Result - shift left two bytes from left to result */
5709 /*-----------------------------------------------------------------*/
5710 static void shiftL2Left2Result (operand *left, int offl,
5711 operand *result, int offr, int shCount)
5713 if(sameRegs(AOP(result), AOP(left)) &&
5714 ((offl + MSB16) == offr)){
5715 /* don't crash result[offr] */
5716 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5717 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5719 movLeft2Result(left,offl, result, offr, 0);
5720 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5722 /* ax << shCount (x = lsb(result))*/
5723 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5724 aopPut(AOP(result),"a",offr+MSB16);
5728 /*-----------------------------------------------------------------*/
5729 /* shiftR2Left2Result - shift right two bytes from left to result */
5730 /*-----------------------------------------------------------------*/
5731 static void shiftR2Left2Result (operand *left, int offl,
5732 operand *result, int offr,
5733 int shCount, int sign)
5735 if(sameRegs(AOP(result), AOP(left)) &&
5736 ((offl + MSB16) == offr)){
5737 /* don't crash result[offr] */
5738 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5739 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5741 movLeft2Result(left,offl, result, offr, 0);
5742 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5744 /* a:x >> shCount (x = lsb(result))*/
5746 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5748 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5749 if(getDataSize(result) > 1)
5750 aopPut(AOP(result),"a",offr+MSB16);
5753 /*-----------------------------------------------------------------*/
5754 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5755 /*-----------------------------------------------------------------*/
5756 static void shiftLLeftOrResult (operand *left, int offl,
5757 operand *result, int offr, int shCount)
5759 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5760 /* shift left accumulator */
5762 /* or with result */
5763 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5764 /* back to result */
5765 aopPut(AOP(result),"a",offr);
5768 /*-----------------------------------------------------------------*/
5769 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5770 /*-----------------------------------------------------------------*/
5771 static void shiftRLeftOrResult (operand *left, int offl,
5772 operand *result, int offr, int shCount)
5774 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5775 /* shift right accumulator */
5777 /* or with result */
5778 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5779 /* back to result */
5780 aopPut(AOP(result),"a",offr);
5783 /*-----------------------------------------------------------------*/
5784 /* genlshOne - left shift a one byte quantity by known count */
5785 /*-----------------------------------------------------------------*/
5786 static void genlshOne (operand *result, operand *left, int shCount)
5788 D(emitcode(";", "genlshOne "););
5789 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5792 /*-----------------------------------------------------------------*/
5793 /* genlshTwo - left shift two bytes by known amount != 0 */
5794 /*-----------------------------------------------------------------*/
5795 static void genlshTwo (operand *result,operand *left, int shCount)
5799 D(emitcode(";", "genlshTwo "););
5801 size = getDataSize(result);
5803 /* if shCount >= 8 */
5809 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5811 movLeft2Result(left, LSB, result, MSB16, 0);
5813 aopPut(AOP(result),zero,LSB);
5816 /* 1 <= shCount <= 7 */
5819 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5821 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5825 /*-----------------------------------------------------------------*/
5826 /* shiftLLong - shift left one long from left to result */
5827 /* offl = LSB or MSB16 */
5828 /*-----------------------------------------------------------------*/
5829 static void shiftLLong (operand *left, operand *result, int offr )
5832 int size = AOP_SIZE(result);
5834 if(size >= LSB+offr){
5835 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5837 emitcode("add","a,acc");
5838 if (sameRegs(AOP(left),AOP(result)) &&
5839 size >= MSB16+offr && offr != LSB )
5840 emitcode("xch","a,%s",
5841 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5843 aopPut(AOP(result),"a",LSB+offr);
5846 if(size >= MSB16+offr){
5847 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5848 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5851 emitcode("rlc","a");
5852 if (sameRegs(AOP(left),AOP(result)) &&
5853 size >= MSB24+offr && offr != LSB)
5854 emitcode("xch","a,%s",
5855 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5857 aopPut(AOP(result),"a",MSB16+offr);
5860 if(size >= MSB24+offr){
5861 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5862 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5865 emitcode("rlc","a");
5866 if (sameRegs(AOP(left),AOP(result)) &&
5867 size >= MSB32+offr && offr != LSB )
5868 emitcode("xch","a,%s",
5869 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5871 aopPut(AOP(result),"a",MSB24+offr);
5874 if(size > MSB32+offr){
5875 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5876 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5879 emitcode("rlc","a");
5880 aopPut(AOP(result),"a",MSB32+offr);
5883 aopPut(AOP(result),zero,LSB);
5886 /*-----------------------------------------------------------------*/
5887 /* genlshFour - shift four byte by a known amount != 0 */
5888 /*-----------------------------------------------------------------*/
5889 static void genlshFour (operand *result, operand *left, int shCount)
5893 D(emitcode(";", "genlshFour "););
5895 size = AOP_SIZE(result);
5897 /* if shifting more that 3 bytes */
5898 if (shCount >= 24 ) {
5901 /* lowest order of left goes to the highest
5902 order of the destination */
5903 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5905 movLeft2Result(left, LSB, result, MSB32, 0);
5906 aopPut(AOP(result),zero,LSB);
5907 aopPut(AOP(result),zero,MSB16);
5908 aopPut(AOP(result),zero,MSB32);
5912 /* more than two bytes */
5913 else if ( shCount >= 16 ) {
5914 /* lower order two bytes goes to higher order two bytes */
5916 /* if some more remaining */
5918 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5920 movLeft2Result(left, MSB16, result, MSB32, 0);
5921 movLeft2Result(left, LSB, result, MSB24, 0);
5923 aopPut(AOP(result),zero,MSB16);
5924 aopPut(AOP(result),zero,LSB);
5928 /* if more than 1 byte */
5929 else if ( shCount >= 8 ) {
5930 /* lower order three bytes goes to higher order three bytes */
5934 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5936 movLeft2Result(left, LSB, result, MSB16, 0);
5938 else{ /* size = 4 */
5940 movLeft2Result(left, MSB24, result, MSB32, 0);
5941 movLeft2Result(left, MSB16, result, MSB24, 0);
5942 movLeft2Result(left, LSB, result, MSB16, 0);
5943 aopPut(AOP(result),zero,LSB);
5945 else if(shCount == 1)
5946 shiftLLong(left, result, MSB16);
5948 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5949 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5950 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5951 aopPut(AOP(result),zero,LSB);
5956 /* 1 <= shCount <= 7 */
5957 else if(shCount <= 2){
5958 shiftLLong(left, result, LSB);
5960 shiftLLong(result, result, LSB);
5962 /* 3 <= shCount <= 7, optimize */
5964 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5965 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5966 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5970 /*-----------------------------------------------------------------*/
5971 /* genLeftShiftLiteral - left shifting by known count */
5972 /*-----------------------------------------------------------------*/
5973 static void genLeftShiftLiteral (operand *left,
5978 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5981 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5983 freeAsmop(right,NULL,ic,TRUE);
5985 aopOp(left,ic,FALSE, FALSE);
5986 aopOp(result,ic,FALSE, TRUE);
5988 size = getSize(operandType(result));
5991 emitcode("; shift left ","result %d, left %d",size,
5995 /* I suppose that the left size >= result size */
5998 movLeft2Result(left, size, result, size, 0);
6002 else if(shCount >= (size * 8))
6004 aopPut(AOP(result),zero,size);
6008 genlshOne (result,left,shCount);
6012 case 3: /* bug: this is for generic pointers, I bet. */
6013 genlshTwo (result,left,shCount);
6017 genlshFour (result,left,shCount);
6021 freeAsmop(left,NULL,ic,TRUE);
6022 freeAsmop(result,NULL,ic,TRUE);
6025 /*-----------------------------------------------------------------*/
6026 /* genLeftShift - generates code for left shifting */
6027 /*-----------------------------------------------------------------*/
6028 static void genLeftShift (iCode *ic)
6030 operand *left,*right, *result;
6033 symbol *tlbl , *tlbl1;
6035 D(emitcode(";", "genLeftShift "););
6037 right = IC_RIGHT(ic);
6039 result = IC_RESULT(ic);
6041 aopOp(right,ic,FALSE, FALSE);
6044 /* if the shift count is known then do it
6045 as efficiently as possible */
6046 if (AOP_TYPE(right) == AOP_LIT) {
6047 genLeftShiftLiteral (left,right,result,ic);
6052 /* shift count is unknown then we have to form
6053 a loop get the loop count in B : Note: we take
6054 only the lower order byte since shifting
6055 more that 32 bits make no sense anyway, ( the
6056 largest size of an object can be only 32 bits ) */
6058 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6059 emitcode("inc","b");
6060 freeAsmop (right,NULL,ic,TRUE);
6061 aopOp(left,ic,FALSE, FALSE);
6062 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6064 /* now move the left to the result if they are not the
6066 if (!sameRegs(AOP(left),AOP(result)) &&
6067 AOP_SIZE(result) > 1) {
6069 size = AOP_SIZE(result);
6071 _startLazyDPSEvaluation();
6073 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6074 if (*l == '@' && (IS_AOP_PREG(result))) {
6076 emitcode("mov","a,%s",l);
6077 aopPut(AOP(result),"a",offset);
6079 aopPut(AOP(result),l,offset);
6082 _endLazyDPSEvaluation();
6085 tlbl = newiTempLabel(NULL);
6086 size = AOP_SIZE(result);
6088 tlbl1 = newiTempLabel(NULL);
6090 /* if it is only one byte then */
6092 symbol *tlbl1 = newiTempLabel(NULL);
6094 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6096 emitcode("sjmp","%05d$",tlbl1->key+100);
6097 emitcode("","%05d$:",tlbl->key+100);
6098 emitcode("add","a,acc");
6099 emitcode("","%05d$:",tlbl1->key+100);
6100 emitcode("djnz","b,%05d$",tlbl->key+100);
6101 aopPut(AOP(result),"a",0);
6105 reAdjustPreg(AOP(result));
6107 emitcode("sjmp","%05d$",tlbl1->key+100);
6108 emitcode("","%05d$:",tlbl->key+100);
6109 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6111 emitcode("add","a,acc");
6112 aopPut(AOP(result),"a",offset++);
6113 _startLazyDPSEvaluation();
6115 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6117 emitcode("rlc","a");
6118 aopPut(AOP(result),"a",offset++);
6120 _endLazyDPSEvaluation();
6121 reAdjustPreg(AOP(result));
6123 emitcode("","%05d$:",tlbl1->key+100);
6124 emitcode("djnz","b,%05d$",tlbl->key+100);
6126 freeAsmop(left,NULL,ic,TRUE);
6127 freeAsmop(result,NULL,ic,TRUE);
6130 /*-----------------------------------------------------------------*/
6131 /* genrshOne - right shift a one byte quantity by known count */
6132 /*-----------------------------------------------------------------*/
6133 static void genrshOne (operand *result, operand *left,
6134 int shCount, int sign)
6136 D(emitcode(";", "genrshOne"););
6137 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6140 /*-----------------------------------------------------------------*/
6141 /* genrshTwo - right shift two bytes by known amount != 0 */
6142 /*-----------------------------------------------------------------*/
6143 static void genrshTwo (operand *result,operand *left,
6144 int shCount, int sign)
6146 D(emitcode(";", "genrshTwo"););
6148 /* if shCount >= 8 */
6152 shiftR1Left2Result(left, MSB16, result, LSB,
6155 movLeft2Result(left, MSB16, result, LSB, sign);
6156 addSign(result, MSB16, sign);
6159 /* 1 <= shCount <= 7 */
6161 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6164 /*-----------------------------------------------------------------*/
6165 /* shiftRLong - shift right one long from left to result */
6166 /* offl = LSB or MSB16 */
6167 /*-----------------------------------------------------------------*/
6168 static void shiftRLong (operand *left, int offl,
6169 operand *result, int sign)
6172 emitcode("clr","c");
6173 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6175 emitcode("mov","c,acc.7");
6176 emitcode("rrc","a");
6177 aopPut(AOP(result),"a",MSB32-offl);
6179 /* add sign of "a" */
6180 addSign(result, MSB32, sign);
6182 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6183 emitcode("rrc","a");
6184 aopPut(AOP(result),"a",MSB24-offl);
6186 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6187 emitcode("rrc","a");
6188 aopPut(AOP(result),"a",MSB16-offl);
6191 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6192 emitcode("rrc","a");
6193 aopPut(AOP(result),"a",LSB);
6197 /*-----------------------------------------------------------------*/
6198 /* genrshFour - shift four byte by a known amount != 0 */
6199 /*-----------------------------------------------------------------*/
6200 static void genrshFour (operand *result, operand *left,
6201 int shCount, int sign)
6203 D(emitcode(";", "genrshFour"););
6205 /* if shifting more that 3 bytes */
6206 if(shCount >= 24 ) {
6209 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6211 movLeft2Result(left, MSB32, result, LSB, sign);
6212 addSign(result, MSB16, sign);
6214 else if(shCount >= 16){
6217 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6219 movLeft2Result(left, MSB24, result, LSB, 0);
6220 movLeft2Result(left, MSB32, result, MSB16, sign);
6222 addSign(result, MSB24, sign);
6224 else if(shCount >= 8){
6227 shiftRLong(left, MSB16, result, sign);
6228 else if(shCount == 0){
6229 movLeft2Result(left, MSB16, result, LSB, 0);
6230 movLeft2Result(left, MSB24, result, MSB16, 0);
6231 movLeft2Result(left, MSB32, result, MSB24, sign);
6232 addSign(result, MSB32, sign);
6235 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6236 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6237 /* the last shift is signed */
6238 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6239 addSign(result, MSB32, sign);
6242 else{ /* 1 <= shCount <= 7 */
6244 shiftRLong(left, LSB, result, sign);
6246 shiftRLong(result, LSB, result, sign);
6249 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6250 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6251 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6256 /*-----------------------------------------------------------------*/
6257 /* genRightShiftLiteral - right shifting by known count */
6258 /*-----------------------------------------------------------------*/
6259 static void genRightShiftLiteral (operand *left,
6265 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6268 D(emitcode(";", "genRightShiftLiteral"););
6270 freeAsmop(right,NULL,ic,TRUE);
6272 aopOp(left,ic,FALSE, FALSE);
6273 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6276 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6280 size = getDataSize(left);
6281 /* test the LEFT size !!! */
6283 /* I suppose that the left size >= result size */
6285 size = getDataSize(result);
6287 movLeft2Result(left, size, result, size, 0);
6290 else if(shCount >= (size * 8)){
6292 /* get sign in acc.7 */
6293 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6294 addSign(result, LSB, sign);
6298 genrshOne (result,left,shCount,sign);
6302 genrshTwo (result,left,shCount,sign);
6306 genrshFour (result,left,shCount,sign);
6312 freeAsmop(left,NULL,ic,TRUE);
6313 freeAsmop(result,NULL,ic,TRUE);
6317 /*-----------------------------------------------------------------*/
6318 /* genSignedRightShift - right shift of signed number */
6319 /*-----------------------------------------------------------------*/
6320 static void genSignedRightShift (iCode *ic)
6322 operand *right, *left, *result;
6325 symbol *tlbl, *tlbl1 ;
6327 D(emitcode(";", "genSignedRightShift "););
6329 /* we do it the hard way put the shift count in b
6330 and loop thru preserving the sign */
6332 right = IC_RIGHT(ic);
6334 result = IC_RESULT(ic);
6336 aopOp(right,ic,FALSE, FALSE);
6339 if ( AOP_TYPE(right) == AOP_LIT) {
6340 genRightShiftLiteral (left,right,result,ic,1);
6344 /* shift count is unknown then we have to form
6345 a loop get the loop count in B : Note: we take
6346 only the lower order byte since shifting
6347 more that 32 bits make no sense anyway, ( the
6348 largest size of an object can be only 32 bits ) */
6350 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6351 emitcode("inc","b");
6352 freeAsmop (right,NULL,ic,TRUE);
6353 aopOp(left,ic,FALSE, FALSE);
6354 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6356 /* now move the left to the result if they are not the
6358 if (!sameRegs(AOP(left),AOP(result)) &&
6359 AOP_SIZE(result) > 1) {
6361 size = AOP_SIZE(result);
6363 _startLazyDPSEvaluation();
6365 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6366 if (*l == '@' && IS_AOP_PREG(result)) {
6368 emitcode("mov","a,%s",l);
6369 aopPut(AOP(result),"a",offset);
6371 aopPut(AOP(result),l,offset);
6374 _endLazyDPSEvaluation();
6377 /* mov the highest order bit to OVR */
6378 tlbl = newiTempLabel(NULL);
6379 tlbl1= newiTempLabel(NULL);
6381 size = AOP_SIZE(result);
6383 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6384 emitcode("rlc","a");
6385 emitcode("mov","ov,c");
6386 /* if it is only one byte then */
6388 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6390 emitcode("sjmp","%05d$",tlbl1->key+100);
6391 emitcode("","%05d$:",tlbl->key+100);
6392 emitcode("mov","c,ov");
6393 emitcode("rrc","a");
6394 emitcode("","%05d$:",tlbl1->key+100);
6395 emitcode("djnz","b,%05d$",tlbl->key+100);
6396 aopPut(AOP(result),"a",0);
6400 reAdjustPreg(AOP(result));
6401 emitcode("sjmp","%05d$",tlbl1->key+100);
6402 emitcode("","%05d$:",tlbl->key+100);
6403 emitcode("mov","c,ov");
6404 _startLazyDPSEvaluation();
6406 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6408 emitcode("rrc","a");
6409 aopPut(AOP(result),"a",offset--);
6411 _endLazyDPSEvaluation();
6412 reAdjustPreg(AOP(result));
6413 emitcode("","%05d$:",tlbl1->key+100);
6414 emitcode("djnz","b,%05d$",tlbl->key+100);
6417 freeAsmop(left,NULL,ic,TRUE);
6418 freeAsmop(result,NULL,ic,TRUE);
6421 /*-----------------------------------------------------------------*/
6422 /* genRightShift - generate code for right shifting */
6423 /*-----------------------------------------------------------------*/
6424 static void genRightShift (iCode *ic)
6426 operand *right, *left, *result;
6430 symbol *tlbl, *tlbl1 ;
6432 D(emitcode(";", "genRightShift "););
6434 /* if signed then we do it the hard way preserve the
6435 sign bit moving it inwards */
6436 retype = getSpec(operandType(IC_RESULT(ic)));
6438 if (!SPEC_USIGN(retype)) {
6439 genSignedRightShift (ic);
6443 /* signed & unsigned types are treated the same : i.e. the
6444 signed is NOT propagated inwards : quoting from the
6445 ANSI - standard : "for E1 >> E2, is equivalent to division
6446 by 2**E2 if unsigned or if it has a non-negative value,
6447 otherwise the result is implementation defined ", MY definition
6448 is that the sign does not get propagated */
6450 right = IC_RIGHT(ic);
6452 result = IC_RESULT(ic);
6454 aopOp(right,ic,FALSE, FALSE);
6457 /* if the shift count is known then do it
6458 as efficiently as possible */
6459 if (AOP_TYPE(right) == AOP_LIT) {
6460 genRightShiftLiteral (left,right,result,ic, 0);
6465 /* shift count is unknown then we have to form
6466 a loop get the loop count in B : Note: we take
6467 only the lower order byte since shifting
6468 more that 32 bits make no sense anyway, ( the
6469 largest size of an object can be only 32 bits ) */
6471 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6472 emitcode("inc","b");
6473 freeAsmop (right,NULL,ic,TRUE);
6474 aopOp(left,ic,FALSE, FALSE);
6475 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6477 /* now move the left to the result if they are not the
6479 if (!sameRegs(AOP(left),AOP(result)) &&
6480 AOP_SIZE(result) > 1) {
6482 size = AOP_SIZE(result);
6484 _startLazyDPSEvaluation();
6486 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6487 if (*l == '@' && IS_AOP_PREG(result)) {
6489 emitcode("mov","a,%s",l);
6490 aopPut(AOP(result),"a",offset);
6492 aopPut(AOP(result),l,offset);
6495 _endLazyDPSEvaluation();
6498 tlbl = newiTempLabel(NULL);
6499 tlbl1= newiTempLabel(NULL);
6500 size = AOP_SIZE(result);
6503 /* if it is only one byte then */
6505 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6507 emitcode("sjmp","%05d$",tlbl1->key+100);
6508 emitcode("","%05d$:",tlbl->key+100);
6510 emitcode("rrc","a");
6511 emitcode("","%05d$:",tlbl1->key+100);
6512 emitcode("djnz","b,%05d$",tlbl->key+100);
6513 aopPut(AOP(result),"a",0);
6517 reAdjustPreg(AOP(result));
6518 emitcode("sjmp","%05d$",tlbl1->key+100);
6519 emitcode("","%05d$:",tlbl->key+100);
6521 _startLazyDPSEvaluation();
6523 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6525 emitcode("rrc","a");
6526 aopPut(AOP(result),"a",offset--);
6528 _endLazyDPSEvaluation();
6529 reAdjustPreg(AOP(result));
6531 emitcode("","%05d$:",tlbl1->key+100);
6532 emitcode("djnz","b,%05d$",tlbl->key+100);
6535 freeAsmop(left,NULL,ic,TRUE);
6536 freeAsmop(result,NULL,ic,TRUE);
6539 /*-----------------------------------------------------------------*/
6540 /* genUnpackBits - generates code for unpacking bits */
6541 /*-----------------------------------------------------------------*/
6542 static void genUnpackBits (operand *result, char *rname, int ptype)
6549 D(emitcode(";", "genUnpackBits "););
6551 etype = getSpec(operandType(result));
6553 /* read the first byte */
6558 emitcode("mov","a,@%s",rname);
6562 emitcode("movx","a,@%s",rname);
6566 emitcode("movx","a,@dptr");
6570 emitcode("clr","a");
6571 emitcode("movc","a","@a+dptr");
6575 emitcode("lcall","__gptrget");
6579 /* if we have bitdisplacement then it fits */
6580 /* into this byte completely or if length is */
6581 /* less than a byte */
6582 if ((shCnt = SPEC_BSTR(etype)) ||
6583 (SPEC_BLEN(etype) <= 8)) {
6585 /* shift right acc */
6588 emitcode("anl","a,#0x%02x",
6589 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6590 aopPut(AOP(result),"a",offset);
6594 /* bit field did not fit in a byte */
6595 rlen = SPEC_BLEN(etype) - 8;
6596 aopPut(AOP(result),"a",offset++);
6603 emitcode("inc","%s",rname);
6604 emitcode("mov","a,@%s",rname);
6608 emitcode("inc","%s",rname);
6609 emitcode("movx","a,@%s",rname);
6613 emitcode("inc","dptr");
6614 emitcode("movx","a,@dptr");
6618 emitcode("clr","a");
6619 emitcode("inc","dptr");
6620 emitcode("movc","a","@a+dptr");
6624 emitcode("inc","dptr");
6625 emitcode("lcall","__gptrget");
6630 /* if we are done */
6634 aopPut(AOP(result),"a",offset++);
6639 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6640 aopPut(AOP(result),"a",offset);
6647 /*-----------------------------------------------------------------*/
6648 /* genDataPointerGet - generates code when ptr offset is known */
6649 /*-----------------------------------------------------------------*/
6650 static void genDataPointerGet (operand *left,
6656 int size , offset = 0;
6657 aopOp(result,ic,TRUE, FALSE);
6659 /* get the string representation of the name */
6660 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6661 size = AOP_SIZE(result);
6662 _startLazyDPSEvaluation();
6665 sprintf(buffer,"(%s + %d)",l+1,offset);
6667 sprintf(buffer,"%s",l+1);
6668 aopPut(AOP(result),buffer,offset++);
6670 _endLazyDPSEvaluation();
6672 freeAsmop(left,NULL,ic,TRUE);
6673 freeAsmop(result,NULL,ic,TRUE);
6676 /*-----------------------------------------------------------------*/
6677 /* genNearPointerGet - emitcode for near pointer fetch */
6678 /*-----------------------------------------------------------------*/
6679 static void genNearPointerGet (operand *left,
6686 link *rtype, *retype;
6687 link *ltype = operandType(left);
6690 rtype = operandType(result);
6691 retype= getSpec(rtype);
6693 aopOp(left,ic,FALSE, FALSE);
6695 /* if left is rematerialisable and
6696 result is not bit variable type and
6697 the left is pointer to data space i.e
6698 lower 128 bytes of space */
6699 if (AOP_TYPE(left) == AOP_IMMD &&
6700 !IS_BITVAR(retype) &&
6701 DCL_TYPE(ltype) == POINTER) {
6702 genDataPointerGet (left,result,ic);
6706 /* if the value is already in a pointer register
6707 then don't need anything more */
6708 if (!AOP_INPREG(AOP(left))) {
6709 /* otherwise get a free pointer register */
6711 preg = getFreePtr(ic,&aop,FALSE);
6712 emitcode("mov","%s,%s",
6714 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6715 rname = preg->name ;
6717 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6719 freeAsmop(left,NULL,ic,TRUE);
6720 aopOp (result,ic,FALSE, FALSE);
6722 /* if bitfield then unpack the bits */
6723 if (IS_BITVAR(retype))
6724 genUnpackBits (result,rname,POINTER);
6726 /* we have can just get the values */
6727 int size = AOP_SIZE(result);
6731 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6733 emitcode("mov","a,@%s",rname);
6734 aopPut(AOP(result),"a",offset);
6736 sprintf(buffer,"@%s",rname);
6737 aopPut(AOP(result),buffer,offset);
6741 emitcode("inc","%s",rname);
6745 /* now some housekeeping stuff */
6747 /* we had to allocate for this iCode */
6748 freeAsmop(NULL,aop,ic,TRUE);
6750 /* we did not allocate which means left
6751 already in a pointer register, then
6752 if size > 0 && this could be used again
6753 we have to point it back to where it
6755 if (AOP_SIZE(result) > 1 &&
6756 !OP_SYMBOL(left)->remat &&
6757 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6759 int size = AOP_SIZE(result) - 1;
6761 emitcode("dec","%s",rname);
6766 freeAsmop(result,NULL,ic,TRUE);
6770 /*-----------------------------------------------------------------*/
6771 /* genPagedPointerGet - emitcode for paged pointer fetch */
6772 /*-----------------------------------------------------------------*/
6773 static void genPagedPointerGet (operand *left,
6780 link *rtype, *retype;
6782 rtype = operandType(result);
6783 retype= getSpec(rtype);
6785 aopOp(left,ic,FALSE, FALSE);
6787 /* if the value is already in a pointer register
6788 then don't need anything more */
6789 if (!AOP_INPREG(AOP(left))) {
6790 /* otherwise get a free pointer register */
6792 preg = getFreePtr(ic,&aop,FALSE);
6793 emitcode("mov","%s,%s",
6795 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6796 rname = preg->name ;
6798 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6800 freeAsmop(left,NULL,ic,TRUE);
6801 aopOp (result,ic,FALSE, FALSE);
6803 /* if bitfield then unpack the bits */
6804 if (IS_BITVAR(retype))
6805 genUnpackBits (result,rname,PPOINTER);
6807 /* we have can just get the values */
6808 int size = AOP_SIZE(result);
6813 emitcode("movx","a,@%s",rname);
6814 aopPut(AOP(result),"a",offset);
6819 emitcode("inc","%s",rname);
6823 /* now some housekeeping stuff */
6825 /* we had to allocate for this iCode */
6826 freeAsmop(NULL,aop,ic,TRUE);
6828 /* we did not allocate which means left
6829 already in a pointer register, then
6830 if size > 0 && this could be used again
6831 we have to point it back to where it
6833 if (AOP_SIZE(result) > 1 &&
6834 !OP_SYMBOL(left)->remat &&
6835 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6837 int size = AOP_SIZE(result) - 1;
6839 emitcode("dec","%s",rname);
6844 freeAsmop(result,NULL,ic,TRUE);
6849 /*-----------------------------------------------------------------*/
6850 /* genFarPointerGet - gget value from far space */
6851 /*-----------------------------------------------------------------*/
6852 static void genFarPointerGet (operand *left,
6853 operand *result, iCode *ic)
6856 link *retype = getSpec(operandType(result));
6858 D(emitcode(";", "genFarPointerGet"););
6860 aopOp(left,ic,FALSE, FALSE);
6862 /* if the operand is already in dptr
6863 then we do nothing else we move the value to dptr */
6864 if (AOP_TYPE(left) != AOP_STR) {
6865 /* if this is remateriazable */
6866 if (AOP_TYPE(left) == AOP_IMMD)
6868 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6872 /* we need to get it byte by byte */
6873 _startLazyDPSEvaluation();
6874 if (AOP_TYPE(left) != AOP_DPTR)
6876 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6877 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6878 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6882 /* We need to generate a load to DPTR indirect through DPTR. */
6883 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6884 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6885 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6886 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6887 emitcode("pop", "dph");
6888 emitcode("pop", "dpl");
6890 _endLazyDPSEvaluation();
6893 /* so dptr know contains the address */
6894 freeAsmop(left,NULL,ic,TRUE);
6895 aopOp(result,ic,FALSE, TRUE);
6897 /* if bit then unpack */
6898 if (IS_BITVAR(retype))
6899 genUnpackBits(result,"dptr",FPOINTER);
6901 size = AOP_SIZE(result);
6904 _startLazyDPSEvaluation();
6910 emitcode("movx","a,@dptr");
6912 emitcode("inc","dptr");
6914 aopPut(AOP(result),"a",offset++);
6916 _endLazyDPSEvaluation();
6919 freeAsmop(result,NULL,ic,TRUE);
6922 /*-----------------------------------------------------------------*/
6923 /* emitcodePointerGet - gget value from code space */
6924 /*-----------------------------------------------------------------*/
6925 static void emitcodePointerGet (operand *left,
6926 operand *result, iCode *ic)
6929 link *retype = getSpec(operandType(result));
6931 aopOp(left,ic,FALSE, FALSE);
6933 /* if the operand is already in dptr
6934 then we do nothing else we move the value to dptr */
6935 if (AOP_TYPE(left) != AOP_STR) {
6936 /* if this is remateriazable */
6937 if (AOP_TYPE(left) == AOP_IMMD)
6938 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6939 else { /* we need to get it byte by byte */
6940 _startLazyDPSEvaluation();
6941 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6942 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6943 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6944 _endLazyDPSEvaluation();
6947 /* so dptr know contains the address */
6948 freeAsmop(left,NULL,ic,TRUE);
6949 aopOp(result,ic,FALSE, TRUE);
6951 /* if bit then unpack */
6952 if (IS_BITVAR(retype))
6953 genUnpackBits(result,"dptr",CPOINTER);
6955 size = AOP_SIZE(result);
6958 _startLazyDPSEvaluation();
6964 emitcode("clr","a");
6965 emitcode("movc","a,@a+dptr");
6967 emitcode("inc","dptr");
6968 aopPut(AOP(result),"a",offset++);
6970 _endLazyDPSEvaluation();
6973 freeAsmop(result,NULL,ic,TRUE);
6976 /*-----------------------------------------------------------------*/
6977 /* genGenPointerGet - gget value from generic pointer space */
6978 /*-----------------------------------------------------------------*/
6979 static void genGenPointerGet (operand *left,
6980 operand *result, iCode *ic)
6983 link *retype = getSpec(operandType(result));
6985 aopOp(left,ic,FALSE, TRUE);
6987 /* if the operand is already in dptr
6988 then we do nothing else we move the value to dptr */
6989 if (AOP_TYPE(left) != AOP_STR) {
6990 /* if this is remateriazable */
6991 if (AOP_TYPE(left) == AOP_IMMD) {
6992 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6993 emitcode("mov","b,#%d",pointerCode(retype));
6995 else { /* we need to get it byte by byte */
6996 _startLazyDPSEvaluation();
6997 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6998 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6999 if (options.model == MODEL_FLAT24)
7001 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7002 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7006 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7008 _endLazyDPSEvaluation();
7011 /* so dptr know contains the address */
7012 freeAsmop(left,NULL,ic,TRUE);
7013 aopOp(result,ic,FALSE, TRUE);
7015 /* if bit then unpack */
7016 if (IS_BITVAR(retype))
7017 genUnpackBits(result,"dptr",GPOINTER);
7019 size = AOP_SIZE(result);
7023 emitcode("lcall","__gptrget");
7024 aopPut(AOP(result),"a",offset++);
7026 emitcode("inc","dptr");
7030 freeAsmop(result,NULL,ic,TRUE);
7033 /*-----------------------------------------------------------------*/
7034 /* genPointerGet - generate code for pointer get */
7035 /*-----------------------------------------------------------------*/
7036 static void genPointerGet (iCode *ic)
7038 operand *left, *result ;
7042 D(emitcode(";", "genPointerGet "););
7045 result = IC_RESULT(ic) ;
7047 /* depending on the type of pointer we need to
7048 move it to the correct pointer register */
7049 type = operandType(left);
7050 etype = getSpec(type);
7051 /* if left is of type of pointer then it is simple */
7052 if (IS_PTR(type) && !IS_FUNC(type->next))
7053 p_type = DCL_TYPE(type);
7055 /* we have to go by the storage class */
7056 p_type = PTR_TYPE(SPEC_OCLS(etype));
7058 /* if (SPEC_OCLS(etype)->codesp ) { */
7059 /* p_type = CPOINTER ; */
7062 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7063 /* p_type = FPOINTER ; */
7065 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7066 /* p_type = PPOINTER; */
7068 /* if (SPEC_OCLS(etype) == idata ) */
7069 /* p_type = IPOINTER; */
7071 /* p_type = POINTER ; */
7074 /* now that we have the pointer type we assign
7075 the pointer values */
7080 genNearPointerGet (left,result,ic);
7084 genPagedPointerGet(left,result,ic);
7088 genFarPointerGet (left,result,ic);
7092 emitcodePointerGet (left,result,ic);
7096 genGenPointerGet (left,result,ic);
7102 /*-----------------------------------------------------------------*/
7103 /* genPackBits - generates code for packed bit storage */
7104 /*-----------------------------------------------------------------*/
7105 static void genPackBits (link *etype ,
7107 char *rname, int p_type)
7115 blen = SPEC_BLEN(etype);
7116 bstr = SPEC_BSTR(etype);
7118 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7121 /* if the bit lenth is less than or */
7122 /* it exactly fits a byte then */
7123 if (SPEC_BLEN(etype) <= 8 ) {
7124 shCount = SPEC_BSTR(etype) ;
7126 /* shift left acc */
7129 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7134 emitcode ("mov","b,a");
7135 emitcode("mov","a,@%s",rname);
7139 emitcode ("mov","b,a");
7140 emitcode("movx","a,@dptr");
7144 emitcode ("push","b");
7145 emitcode ("push","acc");
7146 emitcode ("lcall","__gptrget");
7147 emitcode ("pop","b");
7151 emitcode ("anl","a,#0x%02x",(unsigned char)
7152 ((unsigned char)(0xFF << (blen+bstr)) |
7153 (unsigned char)(0xFF >> (8-bstr)) ) );
7154 emitcode ("orl","a,b");
7155 if (p_type == GPOINTER)
7156 emitcode("pop","b");
7162 emitcode("mov","@%s,a",rname);
7166 emitcode("movx","@dptr,a");
7170 emitcode("lcall","__gptrput");
7175 if ( SPEC_BLEN(etype) <= 8 )
7178 emitcode("inc","%s",rname);
7179 rLen = SPEC_BLEN(etype) ;
7181 /* now generate for lengths greater than one byte */
7184 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7194 emitcode("mov","@%s,a",rname);
7196 emitcode("mov","@%s,%s",rname,l);
7201 emitcode("movx","@dptr,a");
7206 emitcode("lcall","__gptrput");
7209 emitcode ("inc","%s",rname);
7214 /* last last was not complete */
7216 /* save the byte & read byte */
7219 emitcode ("mov","b,a");
7220 emitcode("mov","a,@%s",rname);
7224 emitcode ("mov","b,a");
7225 emitcode("movx","a,@dptr");
7229 emitcode ("push","b");
7230 emitcode ("push","acc");
7231 emitcode ("lcall","__gptrget");
7232 emitcode ("pop","b");
7236 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7237 emitcode ("orl","a,b");
7240 if (p_type == GPOINTER)
7241 emitcode("pop","b");
7246 emitcode("mov","@%s,a",rname);
7250 emitcode("movx","@dptr,a");
7254 emitcode("lcall","__gptrput");
7258 /*-----------------------------------------------------------------*/
7259 /* genDataPointerSet - remat pointer to data space */
7260 /*-----------------------------------------------------------------*/
7261 static void genDataPointerSet(operand *right,
7265 int size, offset = 0 ;
7266 char *l, buffer[256];
7268 aopOp(right,ic,FALSE, FALSE);
7270 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7271 size = AOP_SIZE(right);
7274 sprintf(buffer,"(%s + %d)",l+1,offset);
7276 sprintf(buffer,"%s",l+1);
7277 emitcode("mov","%s,%s",buffer,
7278 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7281 freeAsmop(right,NULL,ic,TRUE);
7282 freeAsmop(result,NULL,ic,TRUE);
7285 /*-----------------------------------------------------------------*/
7286 /* genNearPointerSet - emitcode for near pointer put */
7287 /*-----------------------------------------------------------------*/
7288 static void genNearPointerSet (operand *right,
7296 link *ptype = operandType(result);
7298 retype= getSpec(operandType(right));
7300 aopOp(result,ic,FALSE, FALSE);
7302 /* if the result is rematerializable &
7303 in data space & not a bit variable */
7304 if (AOP_TYPE(result) == AOP_IMMD &&
7305 DCL_TYPE(ptype) == POINTER &&
7306 !IS_BITVAR(retype)) {
7307 genDataPointerSet (right,result,ic);
7311 /* if the value is already in a pointer register
7312 then don't need anything more */
7313 if (!AOP_INPREG(AOP(result))) {
7314 /* otherwise get a free pointer register */
7316 preg = getFreePtr(ic,&aop,FALSE);
7317 emitcode("mov","%s,%s",
7319 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7320 rname = preg->name ;
7322 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7324 freeAsmop(result,NULL,ic,TRUE);
7325 aopOp (right,ic,FALSE, FALSE);
7327 /* if bitfield then unpack the bits */
7328 if (IS_BITVAR(retype))
7329 genPackBits (retype,right,rname,POINTER);
7331 /* we have can just get the values */
7332 int size = AOP_SIZE(right);
7336 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7339 emitcode("mov","@%s,a",rname);
7341 emitcode("mov","@%s,%s",rname,l);
7343 emitcode("inc","%s",rname);
7348 /* now some housekeeping stuff */
7350 /* we had to allocate for this iCode */
7351 freeAsmop(NULL,aop,ic,TRUE);
7353 /* we did not allocate which means left
7354 already in a pointer register, then
7355 if size > 0 && this could be used again
7356 we have to point it back to where it
7358 if (AOP_SIZE(right) > 1 &&
7359 !OP_SYMBOL(result)->remat &&
7360 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7362 int size = AOP_SIZE(right) - 1;
7364 emitcode("dec","%s",rname);
7369 freeAsmop(right,NULL,ic,TRUE);
7374 /*-----------------------------------------------------------------*/
7375 /* genPagedPointerSet - emitcode for Paged pointer put */
7376 /*-----------------------------------------------------------------*/
7377 static void genPagedPointerSet (operand *right,
7386 retype= getSpec(operandType(right));
7388 aopOp(result,ic,FALSE, FALSE);
7390 /* if the value is already in a pointer register
7391 then don't need anything more */
7392 if (!AOP_INPREG(AOP(result))) {
7393 /* otherwise get a free pointer register */
7395 preg = getFreePtr(ic,&aop,FALSE);
7396 emitcode("mov","%s,%s",
7398 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7399 rname = preg->name ;
7401 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7403 freeAsmop(result,NULL,ic,TRUE);
7404 aopOp (right,ic,FALSE, FALSE);
7406 /* if bitfield then unpack the bits */
7407 if (IS_BITVAR(retype))
7408 genPackBits (retype,right,rname,PPOINTER);
7410 /* we have can just get the values */
7411 int size = AOP_SIZE(right);
7415 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7418 emitcode("movx","@%s,a",rname);
7421 emitcode("inc","%s",rname);
7427 /* now some housekeeping stuff */
7429 /* we had to allocate for this iCode */
7430 freeAsmop(NULL,aop,ic,TRUE);
7432 /* we did not allocate which means left
7433 already in a pointer register, then
7434 if size > 0 && this could be used again
7435 we have to point it back to where it
7437 if (AOP_SIZE(right) > 1 &&
7438 !OP_SYMBOL(result)->remat &&
7439 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7441 int size = AOP_SIZE(right) - 1;
7443 emitcode("dec","%s",rname);
7448 freeAsmop(right,NULL,ic,TRUE);
7453 /*-----------------------------------------------------------------*/
7454 /* genFarPointerSet - set value from far space */
7455 /*-----------------------------------------------------------------*/
7456 static void genFarPointerSet (operand *right,
7457 operand *result, iCode *ic)
7460 link *retype = getSpec(operandType(right));
7462 aopOp(result,ic,FALSE, FALSE);
7464 /* if the operand is already in dptr
7465 then we do nothing else we move the value to dptr */
7466 if (AOP_TYPE(result) != AOP_STR) {
7467 /* if this is remateriazable */
7468 if (AOP_TYPE(result) == AOP_IMMD)
7469 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7472 /* we need to get it byte by byte */
7473 _startLazyDPSEvaluation();
7474 if (AOP_TYPE(result) != AOP_DPTR)
7476 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7477 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7478 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7482 /* We need to generate a load to DPTR indirect through DPTR. */
7483 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7484 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7485 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7486 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7487 emitcode("pop", "dph");
7488 emitcode("pop", "dpl");
7490 _endLazyDPSEvaluation();
7493 /* so dptr know contains the address */
7494 freeAsmop(result,NULL,ic,TRUE);
7495 aopOp(right,ic,FALSE, TRUE);
7497 /* if bit then unpack */
7498 if (IS_BITVAR(retype))
7499 genPackBits(retype,right,"dptr",FPOINTER);
7501 size = AOP_SIZE(right);
7504 _startLazyDPSEvaluation();
7506 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7512 emitcode("movx","@dptr,a");
7514 emitcode("inc","dptr");
7516 _endLazyDPSEvaluation();
7519 freeAsmop(right,NULL,ic,TRUE);
7522 /*-----------------------------------------------------------------*/
7523 /* genGenPointerSet - set value from generic pointer space */
7524 /*-----------------------------------------------------------------*/
7525 static void genGenPointerSet (operand *right,
7526 operand *result, iCode *ic)
7529 link *retype = getSpec(operandType(right));
7531 aopOp(result,ic,FALSE, TRUE);
7533 /* if the operand is already in dptr
7534 then we do nothing else we move the value to dptr */
7535 if (AOP_TYPE(result) != AOP_STR) {
7536 _startLazyDPSEvaluation();
7537 /* if this is remateriazable */
7538 if (AOP_TYPE(result) == AOP_IMMD) {
7539 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7540 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7542 else { /* we need to get it byte by byte */
7543 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7544 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7545 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7546 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7548 _endLazyDPSEvaluation();
7550 /* so dptr know contains the address */
7551 freeAsmop(result,NULL,ic,TRUE);
7552 aopOp(right,ic,FALSE, TRUE);
7554 /* if bit then unpack */
7555 if (IS_BITVAR(retype))
7556 genPackBits(retype,right,"dptr",GPOINTER);
7558 size = AOP_SIZE(right);
7561 _startLazyDPSEvaluation();
7563 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7569 emitcode("lcall","__gptrput");
7571 emitcode("inc","dptr");
7573 _endLazyDPSEvaluation();
7576 freeAsmop(right,NULL,ic,TRUE);
7579 /*-----------------------------------------------------------------*/
7580 /* genPointerSet - stores the value into a pointer location */
7581 /*-----------------------------------------------------------------*/
7582 static void genPointerSet (iCode *ic)
7584 operand *right, *result ;
7588 D(emitcode(";", "genPointerSet "););
7590 right = IC_RIGHT(ic);
7591 result = IC_RESULT(ic) ;
7593 /* depending on the type of pointer we need to
7594 move it to the correct pointer register */
7595 type = operandType(result);
7596 etype = getSpec(type);
7597 /* if left is of type of pointer then it is simple */
7598 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7599 p_type = DCL_TYPE(type);
7602 /* we have to go by the storage class */
7603 p_type = PTR_TYPE(SPEC_OCLS(etype));
7605 /* if (SPEC_OCLS(etype)->codesp ) { */
7606 /* p_type = CPOINTER ; */
7609 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7610 /* p_type = FPOINTER ; */
7612 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7613 /* p_type = PPOINTER ; */
7615 /* if (SPEC_OCLS(etype) == idata ) */
7616 /* p_type = IPOINTER ; */
7618 /* p_type = POINTER ; */
7621 /* now that we have the pointer type we assign
7622 the pointer values */
7627 genNearPointerSet (right,result,ic);
7631 genPagedPointerSet (right,result,ic);
7635 genFarPointerSet (right,result,ic);
7639 genGenPointerSet (right,result,ic);
7645 /*-----------------------------------------------------------------*/
7646 /* genIfx - generate code for Ifx statement */
7647 /*-----------------------------------------------------------------*/
7648 static void genIfx (iCode *ic, iCode *popIc)
7650 operand *cond = IC_COND(ic);
7653 D(emitcode(";", "genIfx "););
7655 aopOp(cond,ic,FALSE, FALSE);
7657 /* get the value into acc */
7658 if (AOP_TYPE(cond) != AOP_CRY)
7662 /* the result is now in the accumulator */
7663 freeAsmop(cond,NULL,ic,TRUE);
7665 /* if there was something to be popped then do it */
7669 /* if the condition is a bit variable */
7670 if (isbit && IS_ITEMP(cond) &&
7672 genIfxJump(ic,SPIL_LOC(cond)->rname);
7674 if (isbit && !IS_ITEMP(cond))
7675 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7682 /*-----------------------------------------------------------------*/
7683 /* genAddrOf - generates code for address of */
7684 /*-----------------------------------------------------------------*/
7685 static void genAddrOf (iCode *ic)
7687 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7690 D(emitcode(";", "genAddrOf "););
7692 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7694 /* if the operand is on the stack then we
7695 need to get the stack offset of this
7698 /* if it has an offset then we need to compute
7701 emitcode("mov","a,_bp");
7702 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7703 aopPut(AOP(IC_RESULT(ic)),"a",0);
7705 /* we can just move _bp */
7706 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7708 /* fill the result with zero */
7709 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7712 if (options.stack10bit && size < (FPTRSIZE - 1))
7715 "*** warning: pointer to stack var truncated.\n");
7722 if (options.stack10bit && offset == 2)
7724 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7728 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7735 /* object not on stack then we need the name */
7736 size = AOP_SIZE(IC_RESULT(ic));
7740 char s[SDCC_NAME_MAX];
7742 sprintf(s,"#(%s >> %d)",
7746 sprintf(s,"#%s",sym->rname);
7747 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7751 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7755 /*-----------------------------------------------------------------*/
7756 /* genFarFarAssign - assignment when both are in far space */
7757 /*-----------------------------------------------------------------*/
7758 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7760 int size = AOP_SIZE(right);
7767 /* This is a net loss for size == 1, but a big gain
7770 D(emitcode(";", "genFarFarAssign (improved)"););
7772 aopOp(result,ic,TRUE, TRUE);
7774 _startLazyDPSEvaluation();
7778 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7782 _endLazyDPSEvaluation();
7783 freeAsmop(result,NULL,ic,FALSE);
7784 freeAsmop(right,NULL,ic,FALSE);
7789 D(emitcode(";", "genFarFarAssign "););
7791 /* first push the right side on to the stack */
7792 _startLazyDPSEvaluation();
7794 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7796 emitcode ("push","acc");
7799 freeAsmop(right,NULL,ic,FALSE);
7800 /* now assign DPTR to result */
7801 aopOp(result,ic,FALSE, FALSE);
7802 size = AOP_SIZE(result);
7804 emitcode ("pop","acc");
7805 aopPut(AOP(result),"a",--offset);
7807 freeAsmop(result,NULL,ic,FALSE);
7808 _endLazyDPSEvaluation();
7812 /*-----------------------------------------------------------------*/
7813 /* genAssign - generate code for assignment */
7814 /*-----------------------------------------------------------------*/
7815 static void genAssign (iCode *ic)
7817 operand *result, *right;
7819 unsigned long lit = 0L;
7821 D(emitcode(";", "genAssign "););
7823 result = IC_RESULT(ic);
7824 right = IC_RIGHT(ic) ;
7826 /* if they are the same */
7827 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7830 aopOp(right,ic,FALSE, FALSE);
7832 emitcode(";", "genAssign: resultIsFar = %s",
7833 isOperandInFarSpace(result) ?
7836 /* special case both in far space */
7837 if ((AOP_TYPE(right) == AOP_DPTR ||
7838 AOP_TYPE(right) == AOP_DPTR2) &&
7839 /* IS_TRUE_SYMOP(result) && */
7840 isOperandInFarSpace(result)) {
7842 genFarFarAssign (result,right,ic);
7846 aopOp(result,ic,TRUE, FALSE);
7848 /* if they are the same registers */
7849 if (sameRegs(AOP(right),AOP(result)))
7852 /* if the result is a bit */
7853 if (AOP_TYPE(result) == AOP_CRY) {
7855 /* if the right size is a literal then
7856 we know what the value is */
7857 if (AOP_TYPE(right) == AOP_LIT) {
7858 if (((int) operandLitValue(right)))
7859 aopPut(AOP(result),one,0);
7861 aopPut(AOP(result),zero,0);
7865 /* the right is also a bit variable */
7866 if (AOP_TYPE(right) == AOP_CRY) {
7867 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7868 aopPut(AOP(result),"c",0);
7874 aopPut(AOP(result),"a",0);
7878 /* bit variables done */
7880 size = AOP_SIZE(result);
7882 if(AOP_TYPE(right) == AOP_LIT)
7883 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7886 (AOP_TYPE(result) != AOP_REG) &&
7887 (AOP_TYPE(right) == AOP_LIT) &&
7888 !IS_FLOAT(operandType(right))
7889 #ifndef LAZY_DPS_OPT
7895 D(emitcode(";", "Kevin's better literal load code"););
7896 _startLazyDPSEvaluation();
7897 while (size && ((unsigned int)(lit >> (offset*8)) != 0))
7900 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
7905 /* And now fill the rest with zeros. */
7908 emitcode("clr","a");
7912 aopPut(AOP(result), "a", offset++);
7914 _endLazyDPSEvaluation();
7916 emitcode("clr","a");
7918 _startLazyDPSEvaluation();
7921 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7922 aopPut(AOP(result),"a",size);
7925 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
7928 _endLazyDPSEvaluation();
7933 _startLazyDPSEvaluation();
7937 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7941 _endLazyDPSEvaluation();
7945 freeAsmop (right,NULL,ic,FALSE);
7946 freeAsmop (result,NULL,ic,TRUE);
7949 /*-----------------------------------------------------------------*/
7950 /* genJumpTab - generates code for jump table */
7951 /*-----------------------------------------------------------------*/
7952 static void genJumpTab (iCode *ic)
7957 D(emitcode(";", "genJumpTab "););
7959 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7960 /* get the condition into accumulator */
7961 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
7963 /* multiply by four! */
7964 emitcode("add","a,acc");
7965 emitcode("add","a,acc");
7966 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7968 jtab = newiTempLabel(NULL);
7969 emitcode("mov","dptr,#%05d$",jtab->key+100);
7970 emitcode("jmp","@a+dptr");
7971 emitcode("","%05d$:",jtab->key+100);
7972 /* now generate the jump labels */
7973 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7974 jtab = setNextItem(IC_JTLABELS(ic)))
7975 emitcode("ljmp","%05d$",jtab->key+100);
7979 /*-----------------------------------------------------------------*/
7980 /* genCast - gen code for casting */
7981 /*-----------------------------------------------------------------*/
7982 static void genCast (iCode *ic)
7984 operand *result = IC_RESULT(ic);
7985 link *ctype = operandType(IC_LEFT(ic));
7986 link *rtype = operandType(IC_RIGHT(ic));
7987 operand *right = IC_RIGHT(ic);
7990 D(emitcode(";", "genCast "););
7992 /* if they are equivalent then do nothing */
7993 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7996 aopOp(right,ic,FALSE, FALSE) ;
7997 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7999 /* if the result is a bit */
8000 if (AOP_TYPE(result) == AOP_CRY) {
8001 /* if the right size is a literal then
8002 we know what the value is */
8003 if (AOP_TYPE(right) == AOP_LIT) {
8004 if (((int) operandLitValue(right)))
8005 aopPut(AOP(result),one,0);
8007 aopPut(AOP(result),zero,0);
8012 /* the right is also a bit variable */
8013 if (AOP_TYPE(right) == AOP_CRY) {
8014 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8015 aopPut(AOP(result),"c",0);
8021 aopPut(AOP(result),"a",0);
8025 /* if they are the same size : or less */
8026 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8028 /* if they are in the same place */
8029 if (sameRegs(AOP(right),AOP(result)))
8032 /* if they in different places then copy */
8033 size = AOP_SIZE(result);
8035 _startLazyDPSEvaluation();
8038 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8042 _endLazyDPSEvaluation();
8047 /* if the result is of type pointer */
8048 if (IS_PTR(ctype)) {
8051 link *type = operandType(right);
8053 /* pointer to generic pointer */
8054 if (IS_GENPTR(ctype)) {
8059 p_type = DCL_TYPE(type);
8063 #if OLD_CAST_BEHAVIOR
8064 /* KV: we are converting a non-pointer type to
8065 * a generic pointer. This (ifdef'd out) code
8066 * says that the resulting generic pointer
8067 * should have the same class as the storage
8068 * location of the non-pointer variable.
8070 * For example, converting an int (which happens
8071 * to be stored in DATA space) to a pointer results
8072 * in a DATA generic pointer; if the original int
8073 * in XDATA space, so will be the resulting pointer.
8075 * I don't like that behavior, and thus this change:
8076 * all such conversions will be forced to XDATA and
8077 * throw a warning. If you want some non-XDATA
8078 * type, or you want to suppress the warning, you
8079 * must go through an intermediate cast, like so:
8081 * char _generic *gp = (char _xdata *)(intVar);
8083 link *etype = getSpec(type);
8085 /* we have to go by the storage class */
8086 if (SPEC_OCLS(etype) != generic)
8088 p_type = PTR_TYPE(SPEC_OCLS(etype));
8093 /* Converting unknown class (i.e. register variable)
8094 * to generic pointer. This is not good, but
8095 * we'll make a guess (and throw a warning).
8098 werror(W_INT_TO_GEN_PTR_CAST);
8102 /* the first two bytes are known */
8103 size = GPTRSIZE - 1;
8105 _startLazyDPSEvaluation();
8108 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8112 _endLazyDPSEvaluation();
8114 /* the last byte depending on type */
8131 /* this should never happen */
8132 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8133 "got unknown pointer type");
8136 aopPut(AOP(result),l, GPTRSIZE - 1);
8140 /* just copy the pointers */
8141 size = AOP_SIZE(result);
8143 _startLazyDPSEvaluation();
8146 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8150 _endLazyDPSEvaluation();
8154 /* so we now know that the size of destination is greater
8155 than the size of the source */
8156 /* we move to result for the size of source */
8157 size = AOP_SIZE(right);
8159 _startLazyDPSEvaluation();
8162 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8166 _endLazyDPSEvaluation();
8168 /* now depending on the sign of the source && destination */
8169 size = AOP_SIZE(result) - AOP_SIZE(right);
8170 /* if unsigned or not an integral type */
8171 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
8173 aopPut(AOP(result),zero,offset++);
8175 /* we need to extend the sign :{ */
8176 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8179 emitcode("rlc","a");
8180 emitcode("subb","a,acc");
8182 aopPut(AOP(result),"a",offset++);
8185 /* we are done hurray !!!! */
8188 freeAsmop(right,NULL,ic,TRUE);
8189 freeAsmop(result,NULL,ic,TRUE);
8193 /*-----------------------------------------------------------------*/
8194 /* genDjnz - generate decrement & jump if not zero instrucion */
8195 /*-----------------------------------------------------------------*/
8196 static int genDjnz (iCode *ic, iCode *ifx)
8202 /* if the if condition has a false label
8203 then we cannot save */
8207 /* if the minus is not of the form
8209 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8210 !IS_OP_LITERAL(IC_RIGHT(ic)))
8213 if (operandLitValue(IC_RIGHT(ic)) != 1)
8216 /* if the size of this greater than one then no
8218 if (getSize(operandType(IC_RESULT(ic))) > 1)
8221 /* otherwise we can save BIG */
8222 lbl = newiTempLabel(NULL);
8223 lbl1= newiTempLabel(NULL);
8225 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8227 if (IS_AOP_PREG(IC_RESULT(ic))) {
8228 emitcode("dec","%s",
8229 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8230 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8231 emitcode("jnz","%05d$",lbl->key+100);
8233 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8236 emitcode ("sjmp","%05d$",lbl1->key+100);
8237 emitcode ("","%05d$:",lbl->key+100);
8238 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8239 emitcode ("","%05d$:",lbl1->key+100);
8241 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8246 /*-----------------------------------------------------------------*/
8247 /* genReceive - generate code for a receive iCode */
8248 /*-----------------------------------------------------------------*/
8249 static void genReceive (iCode *ic)
8252 D(emitcode(";", "genReceive "););
8254 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8255 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8256 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8257 int size = getSize(operandType(IC_RESULT(ic)));
8258 int offset = fReturnSize_390 - size;
8260 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8261 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8264 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8265 size = AOP_SIZE(IC_RESULT(ic));
8268 emitcode ("pop","acc");
8269 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8274 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8276 assignResultValue(IC_RESULT(ic));
8279 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8282 /*-----------------------------------------------------------------*/
8283 /* gen390Code - generate code for 8051 based controllers */
8284 /*-----------------------------------------------------------------*/
8285 void gen390Code (iCode *lic)
8290 lineHead = lineCurr = NULL;
8292 /* print the allocation information */
8294 printAllocInfo( currFunc, codeOutFile);
8295 /* if debug information required */
8296 /* if (options.debug && currFunc) { */
8298 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8300 if (IS_STATIC(currFunc->etype))
8301 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8303 emitcode("","G$%s$0$0 ==.",currFunc->name);
8306 /* stack pointer name */
8307 if (options.useXstack)
8313 for (ic = lic ; ic ; ic = ic->next ) {
8315 if ( cln != ic->lineno ) {
8316 if ( options.debug ) {
8318 emitcode("","C$%s$%d$%d$%d ==.",
8319 ic->filename,ic->lineno,
8320 ic->level,ic->block);
8323 emitcode(";","%s %d",ic->filename,ic->lineno);
8326 /* if the result is marked as
8327 spilt and rematerializable or code for
8328 this has already been generated then
8330 if (resultRemat(ic) || ic->generated )
8333 /* depending on the operation */
8352 /* IPOP happens only when trying to restore a
8353 spilt live range, if there is an ifx statement
8354 following this pop then the if statement might
8355 be using some of the registers being popped which
8356 would destory the contents of the register so
8357 we need to check for this condition and handle it */
8359 ic->next->op == IFX &&
8360 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8361 genIfx (ic->next,ic);
8379 genEndFunction (ic);
8399 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8416 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8420 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8427 /* note these two are xlated by algebraic equivalence
8428 during parsing SDCC.y */
8429 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8430 "got '>=' or '<=' shouldn't have come here");
8434 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8446 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8450 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8454 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8481 case GET_VALUE_AT_ADDRESS:
8486 if (POINTER_SET(ic))
8513 addSet(&_G.sendSet,ic);
8518 /* piCode(ic,stdout); */
8524 /* now we are ready to call the
8525 peep hole optimizer */
8526 if (!options.nopeep)
8527 peepHole (&lineHead);
8529 /* now do the actual printing */
8530 printLine (lineHead,codeOutFile);