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));
1577 _startLazyDPSEvaluation();
1579 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1580 if (!strcmp(l,"a")) {
1583 emitcode("cpl","a");
1584 emitcode("addc", "a,#0");
1588 emitcode("clr","a");
1589 emitcode("subb","a,%s",l);
1591 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1593 _endLazyDPSEvaluation();
1595 /* if any remaining bytes in the result */
1596 /* we just need to propagate the sign */
1597 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1598 emitcode("rlc","a");
1599 emitcode("subb","a,acc");
1601 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1605 /* release the aops */
1606 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1607 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1610 /*-----------------------------------------------------------------*/
1611 /* saveRegisters - will look for a call and save the registers */
1612 /*-----------------------------------------------------------------*/
1613 static void saveRegisters(iCode *lic)
1621 for (ic = lic ; ic ; ic = ic->next)
1622 if (ic->op == CALL || ic->op == PCALL)
1626 fprintf(stderr,"found parameter push with no function call\n");
1630 /* if the registers have been saved already then
1632 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1635 /* find the registers in use at this time
1636 and push them away to safety */
1637 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1641 if (options.useXstack) {
1642 if (bitVectBitValue(rsave,R0_IDX))
1643 emitcode("mov","b,r0");
1644 emitcode("mov","r0,%s",spname);
1645 for (i = 0 ; i < ds390_nRegs ; i++) {
1646 if (bitVectBitValue(rsave,i)) {
1648 emitcode("mov","a,b");
1650 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1651 emitcode("movx","@r0,a");
1652 emitcode("inc","r0");
1655 emitcode("mov","%s,r0",spname);
1656 if (bitVectBitValue(rsave,R0_IDX))
1657 emitcode("mov","r0,b");
1659 for (i = 0 ; i < ds390_nRegs ; i++) {
1660 if (bitVectBitValue(rsave,i))
1661 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1664 detype = getSpec(operandType(IC_LEFT(ic)));
1666 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1667 IS_ISR(currFunc->etype) &&
1670 saverbank(SPEC_BANK(detype),ic,TRUE);
1673 /*-----------------------------------------------------------------*/
1674 /* unsaveRegisters - pop the pushed registers */
1675 /*-----------------------------------------------------------------*/
1676 static void unsaveRegisters (iCode *ic)
1680 /* find the registers in use at this time
1681 and push them away to safety */
1682 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1685 if (options.useXstack) {
1686 emitcode("mov","r0,%s",spname);
1687 for (i = ds390_nRegs ; i >= 0 ; i--) {
1688 if (bitVectBitValue(rsave,i)) {
1689 emitcode("dec","r0");
1690 emitcode("movx","a,@r0");
1692 emitcode("mov","b,a");
1694 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1698 emitcode("mov","%s,r0",spname);
1699 if (bitVectBitValue(rsave,R0_IDX))
1700 emitcode("mov","r0,b");
1702 for (i = ds390_nRegs ; i >= 0 ; i--) {
1703 if (bitVectBitValue(rsave,i))
1704 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1710 /*-----------------------------------------------------------------*/
1712 /*-----------------------------------------------------------------*/
1713 static void pushSide(operand * oper, int size)
1716 _startLazyDPSEvaluation();
1718 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1719 if (AOP_TYPE(oper) != AOP_REG &&
1720 AOP_TYPE(oper) != AOP_DIR &&
1722 emitcode("mov","a,%s",l);
1723 emitcode("push","acc");
1725 emitcode("push","%s",l);
1727 _endLazyDPSEvaluation();
1730 /*-----------------------------------------------------------------*/
1731 /* assignResultValue - */
1732 /*-----------------------------------------------------------------*/
1733 static void assignResultValue(operand * oper)
1736 int size = AOP_SIZE(oper);
1738 _startLazyDPSEvaluation();
1740 aopPut(AOP(oper),fReturn[offset],offset);
1743 _endLazyDPSEvaluation();
1747 /*-----------------------------------------------------------------*/
1748 /* genXpush - pushes onto the external stack */
1749 /*-----------------------------------------------------------------*/
1750 static void genXpush (iCode *ic)
1752 asmop *aop = newAsmop(0);
1754 int size,offset = 0;
1756 D(emitcode(";", "genXpush "););
1758 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1759 r = getFreePtr(ic,&aop,FALSE);
1762 emitcode("mov","%s,_spx",r->name);
1764 size = AOP_SIZE(IC_LEFT(ic));
1765 _startLazyDPSEvaluation();
1768 char *l = aopGet(AOP(IC_LEFT(ic)),
1769 offset++,FALSE,FALSE,TRUE);
1771 emitcode("movx","@%s,a",r->name);
1772 emitcode("inc","%s",r->name);
1775 _endLazyDPSEvaluation();
1778 emitcode("mov","_spx,%s",r->name);
1780 freeAsmop(NULL,aop,ic,TRUE);
1781 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1784 /*-----------------------------------------------------------------*/
1785 /* genIpush - genrate code for pushing this gets a little complex */
1786 /*-----------------------------------------------------------------*/
1787 static void genIpush (iCode *ic)
1789 int size, offset = 0 ;
1792 D(emitcode(";", "genIpush "););
1795 /* if this is not a parm push : ie. it is spill push
1796 and spill push is always done on the local stack */
1797 if (!ic->parmPush) {
1799 /* and the item is spilt then do nothing */
1800 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1803 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1804 size = AOP_SIZE(IC_LEFT(ic));
1805 /* push it on the stack */
1806 _startLazyDPSEvaluation();
1808 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1813 emitcode("push","%s",l);
1815 _endLazyDPSEvaluation();
1819 /* this is a paramter push: in this case we call
1820 the routine to find the call and save those
1821 registers that need to be saved */
1824 /* if use external stack then call the external
1825 stack pushing routine */
1826 if (options.useXstack) {
1831 /* then do the push */
1832 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1834 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1835 size = AOP_SIZE(IC_LEFT(ic));
1837 _startLazyDPSEvaluation();
1839 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1840 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1841 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1843 emitcode("mov","a,%s",l);
1844 emitcode("push","acc");
1846 emitcode("push","%s",l);
1848 _endLazyDPSEvaluation();
1850 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1853 /*-----------------------------------------------------------------*/
1854 /* genIpop - recover the registers: can happen only for spilling */
1855 /*-----------------------------------------------------------------*/
1856 static void genIpop (iCode *ic)
1860 D(emitcode(";", "genIpop "););
1863 /* if the temp was not pushed then */
1864 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1867 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1868 size = AOP_SIZE(IC_LEFT(ic));
1870 _startLazyDPSEvaluation();
1873 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1876 _endLazyDPSEvaluation();
1878 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1881 /*-----------------------------------------------------------------*/
1882 /* unsaverbank - restores the resgister bank from stack */
1883 /*-----------------------------------------------------------------*/
1884 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1891 if (options.useXstack) {
1893 r = getFreePtr(ic,&aop,FALSE);
1896 emitcode("mov","%s,_spx",r->name);
1897 emitcode("movx","a,@%s",r->name);
1898 emitcode("mov","psw,a");
1899 emitcode("dec","%s",r->name);
1902 emitcode ("pop","psw");
1905 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1906 if (options.useXstack) {
1907 emitcode("movx","a,@%s",r->name);
1908 emitcode("mov","(%s+%d),a",
1909 regs390[i].base,8*bank+regs390[i].offset);
1910 emitcode("dec","%s",r->name);
1913 emitcode("pop","(%s+%d)",
1914 regs390[i].base,8*bank+regs390[i].offset);
1917 if (options.useXstack) {
1919 emitcode("mov","_spx,%s",r->name);
1920 freeAsmop(NULL,aop,ic,TRUE);
1925 /*-----------------------------------------------------------------*/
1926 /* saverbank - saves an entire register bank on the stack */
1927 /*-----------------------------------------------------------------*/
1928 static void saverbank (int bank, iCode *ic, bool pushPsw)
1934 if (options.useXstack) {
1937 r = getFreePtr(ic,&aop,FALSE);
1938 emitcode("mov","%s,_spx",r->name);
1942 for (i = 0 ; i < ds390_nRegs ;i++) {
1943 if (options.useXstack) {
1944 emitcode("inc","%s",r->name);
1945 emitcode("mov","a,(%s+%d)",
1946 regs390[i].base,8*bank+regs390[i].offset);
1947 emitcode("movx","@%s,a",r->name);
1949 emitcode("push","(%s+%d)",
1950 regs390[i].base,8*bank+regs390[i].offset);
1954 if (options.useXstack) {
1955 emitcode("mov","a,psw");
1956 emitcode("movx","@%s,a",r->name);
1957 emitcode("inc","%s",r->name);
1958 emitcode("mov","_spx,%s",r->name);
1959 freeAsmop (NULL,aop,ic,TRUE);
1962 emitcode("push","psw");
1964 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1970 /*-----------------------------------------------------------------*/
1971 /* genCall - generates a call statement */
1972 /*-----------------------------------------------------------------*/
1973 static void genCall (iCode *ic)
1977 D(emitcode(";", "genCall "););
1979 /* if caller saves & we have not saved then */
1983 /* if we are calling a function that is not using
1984 the same register bank then we need to save the
1985 destination registers on the stack */
1986 detype = getSpec(operandType(IC_LEFT(ic)));
1988 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1989 IS_ISR(currFunc->etype) &&
1992 saverbank(SPEC_BANK(detype),ic,TRUE);
1994 /* if send set is not empty the assign */
1998 for (sic = setFirstItem(_G.sendSet) ; sic ;
1999 sic = setNextItem(_G.sendSet))
2001 int size, offset = 0;
2003 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
2004 size = AOP_SIZE(IC_LEFT(sic));
2006 _startLazyDPSEvaluation();
2008 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2009 FALSE, FALSE, TRUE);
2010 if (strcmp(l,fReturn[offset]))
2011 emitcode("mov","%s,%s",
2016 _endLazyDPSEvaluation();
2017 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2022 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2023 OP_SYMBOL(IC_LEFT(ic))->rname :
2024 OP_SYMBOL(IC_LEFT(ic))->name));
2026 /* if we need assign a result value */
2027 if ((IS_ITEMP(IC_RESULT(ic)) &&
2028 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2029 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2030 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2033 /* Not really related to LAZY_DPS_OPT, but don't want
2034 * another testing flag right now...
2036 #define FAR_RETURN_OPT
2037 #ifdef FAR_RETURN_OPT
2038 if (isOperandInFarSpace(IC_RESULT(ic))
2039 && getSize(operandType(IC_RESULT(ic))) <= 2)
2041 int size = getSize(operandType(IC_RESULT(ic)));
2043 /* Special case for 1 or 2 byte return in far space. */
2044 emitcode(";", "Kevin function call abuse #1");
2049 emitcode("mov", "b,%s", fReturn[1]);
2052 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2053 aopPut(AOP(IC_RESULT(ic)),"a",0);
2057 aopPut(AOP(IC_RESULT(ic)),"b",1);
2059 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2065 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2068 assignResultValue(IC_RESULT(ic));
2070 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2073 if (!isOperandInFarSpace(IC_RESULT(ic)))
2076 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2079 assignResultValue(IC_RESULT(ic));
2081 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2085 /* Result is in far space, and requires DPTR to access
2086 * it. Push the result onto the stack and restore from
2089 int size = getSize(operandType(IC_RESULT(ic)));
2090 int offset = size - 1;
2093 emitcode(";", "Kevin function call abuse #1");
2095 /* first push the right side on to the stack */
2096 /* NB: this relies on the fact that "a" is the last
2097 * register in fReturn. If it were not, the MOVA
2098 * would potentially clobber a returned byte in A.
2101 l = fReturn[offset--];
2103 emitcode ("push","acc");
2106 /* now assign DPTR to result */
2107 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2108 size = AOP_SIZE(IC_RESULT(ic));
2109 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
2111 emitcode ("pop","acc");
2112 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
2114 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2119 /* adjust the stack for parameters if
2121 if (IC_LEFT(ic)->parmBytes) {
2123 if (IC_LEFT(ic)->parmBytes > 3) {
2124 emitcode("mov","a,%s",spname);
2125 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2126 emitcode("mov","%s,a",spname);
2128 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2129 emitcode("dec","%s",spname);
2133 /* if register bank was saved then pop them */
2135 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2137 /* if we hade saved some registers then unsave them */
2138 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2139 unsaveRegisters (ic);
2144 /*-----------------------------------------------------------------*/
2145 /* genPcall - generates a call by pointer statement */
2146 /*-----------------------------------------------------------------*/
2147 static void genPcall (iCode *ic)
2150 symbol *rlbl = newiTempLabel(NULL);
2152 D(emitcode(";", "genPcall "););
2155 /* if caller saves & we have not saved then */
2159 /* if we are calling a function that is not using
2160 the same register bank then we need to save the
2161 destination registers on the stack */
2162 detype = getSpec(operandType(IC_LEFT(ic)));
2164 IS_ISR(currFunc->etype) &&
2165 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2166 saverbank(SPEC_BANK(detype),ic,TRUE);
2169 /* push the return address on to the stack */
2170 emitcode("mov","a,#%05d$",(rlbl->key+100));
2171 emitcode("push","acc");
2172 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2173 emitcode("push","acc");
2175 if (options.model == MODEL_FLAT24)
2177 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2178 emitcode("push","acc");
2181 /* now push the calling address */
2182 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2184 pushSide(IC_LEFT(ic), FPTRSIZE);
2186 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2188 /* if send set is not empty the assign */
2192 for (sic = setFirstItem(_G.sendSet) ; sic ;
2193 sic = setNextItem(_G.sendSet))
2195 int size, offset = 0;
2197 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2198 size = AOP_SIZE(IC_LEFT(sic));
2199 _startLazyDPSEvaluation();
2202 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2204 if (strcmp(l,fReturn[offset]))
2206 emitcode("mov","%s,%s",
2212 _endLazyDPSEvaluation();
2213 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2219 emitcode("","%05d$:",(rlbl->key+100));
2222 /* if we need assign a result value */
2223 if ((IS_ITEMP(IC_RESULT(ic)) &&
2224 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2225 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2226 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2229 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2232 assignResultValue(IC_RESULT(ic));
2234 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2237 /* adjust the stack for parameters if
2239 if (IC_LEFT(ic)->parmBytes) {
2241 if (IC_LEFT(ic)->parmBytes > 3) {
2242 emitcode("mov","a,%s",spname);
2243 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2244 emitcode("mov","%s,a",spname);
2246 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2247 emitcode("dec","%s",spname);
2251 /* if register bank was saved then unsave them */
2253 (SPEC_BANK(currFunc->etype) !=
2255 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2257 /* if we hade saved some registers then
2260 unsaveRegisters (ic);
2264 /*-----------------------------------------------------------------*/
2265 /* resultRemat - result is rematerializable */
2266 /*-----------------------------------------------------------------*/
2267 static int resultRemat (iCode *ic)
2269 if (SKIP_IC(ic) || ic->op == IFX)
2272 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2273 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2274 if (sym->remat && !POINTER_SET(ic))
2282 #define STRCASECMP stricmp
2284 #define STRCASECMP strcasecmp
2287 /*-----------------------------------------------------------------*/
2288 /* inExcludeList - return 1 if the string is in exclude Reg list */
2289 /*-----------------------------------------------------------------*/
2290 static bool inExcludeList(char *s)
2294 if (options.excludeRegs[i] &&
2295 STRCASECMP(options.excludeRegs[i],"none") == 0)
2298 for ( i = 0 ; options.excludeRegs[i]; i++) {
2299 if (options.excludeRegs[i] &&
2300 STRCASECMP(s,options.excludeRegs[i]) == 0)
2306 /*-----------------------------------------------------------------*/
2307 /* genFunction - generated code for function entry */
2308 /*-----------------------------------------------------------------*/
2309 static void genFunction (iCode *ic)
2314 D(emitcode(";", "genFunction "););
2317 /* create the function header */
2318 emitcode(";","-----------------------------------------");
2319 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2320 emitcode(";","-----------------------------------------");
2322 emitcode("","%s:",sym->rname);
2323 fetype = getSpec(operandType(IC_LEFT(ic)));
2325 /* if critical function then turn interrupts off */
2326 if (SPEC_CRTCL(fetype))
2327 emitcode("clr","ea");
2329 /* here we need to generate the equates for the
2330 register bank if required */
2331 if (SPEC_BANK(fetype) != rbank) {
2334 rbank = SPEC_BANK(fetype);
2335 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2336 if (strcmp(regs390[i].base,"0") == 0)
2337 emitcode("","%s = 0x%02x",
2339 8*rbank+regs390[i].offset);
2341 emitcode ("","%s = %s + 0x%02x",
2344 8*rbank+regs390[i].offset);
2348 /* if this is an interrupt service routine then
2349 save acc, b, dpl, dph */
2350 if (IS_ISR(sym->etype)) {
2352 if (!inExcludeList("acc"))
2353 emitcode ("push","acc");
2354 if (!inExcludeList("b"))
2355 emitcode ("push","b");
2356 if (!inExcludeList("dpl"))
2357 emitcode ("push","dpl");
2358 if (!inExcludeList("dph"))
2359 emitcode ("push","dph");
2360 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2362 emitcode ("push", "dpx");
2363 /* Make sure we're using standard DPTR */
2364 emitcode ("push", "dps");
2365 emitcode ("mov", "dps, #0x00");
2366 if (options.stack10bit)
2368 /* This ISR could conceivably use DPTR2. Better save it. */
2369 emitcode ("push", "dpl1");
2370 emitcode ("push", "dph1");
2371 emitcode ("push", "dpx1");
2372 emitcode ("push", "ap");
2375 /* if this isr has no bank i.e. is going to
2376 run with bank 0 , then we need to save more
2378 if (!SPEC_BANK(sym->etype)) {
2380 /* if this function does not call any other
2381 function then we can be economical and
2382 save only those registers that are used */
2383 if (! sym->hasFcall) {
2386 /* if any registers used */
2387 if (sym->regsUsed) {
2388 /* save the registers used */
2389 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2390 if (bitVectBitValue(sym->regsUsed,i) ||
2391 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2392 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2397 /* this function has a function call cannot
2398 determines register usage so we will have the
2400 saverbank(0,ic,FALSE);
2404 /* if callee-save to be used for this function
2405 then save the registers being used in this function */
2406 if (sym->calleeSave) {
2409 /* if any registers used */
2410 if (sym->regsUsed) {
2411 /* save the registers used */
2412 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2413 if (bitVectBitValue(sym->regsUsed,i) ||
2414 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2415 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2423 /* set the register bank to the desired value */
2424 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2425 emitcode("push","psw");
2426 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2429 if (IS_RENT(sym->etype) || options.stackAuto) {
2431 if (options.useXstack) {
2432 emitcode("mov","r0,%s",spname);
2433 emitcode("mov","a,_bp");
2434 emitcode("movx","@r0,a");
2435 emitcode("inc","%s",spname);
2439 /* set up the stack */
2440 emitcode ("push","_bp"); /* save the callers stack */
2442 emitcode ("mov","_bp,%s",spname);
2445 /* adjust the stack for the function */
2450 werror(W_STACK_OVERFLOW,sym->name);
2452 if (i > 3 && sym->recvSize < 4) {
2454 emitcode ("mov","a,sp");
2455 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2456 emitcode ("mov","sp,a");
2461 emitcode("inc","sp");
2466 emitcode ("mov","a,_spx");
2467 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2468 emitcode ("mov","_spx,a");
2473 /*-----------------------------------------------------------------*/
2474 /* genEndFunction - generates epilogue for functions */
2475 /*-----------------------------------------------------------------*/
2476 static void genEndFunction (iCode *ic)
2478 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2480 D(emitcode(";", "genEndFunction "););
2482 if (IS_RENT(sym->etype) || options.stackAuto)
2484 emitcode ("mov","%s,_bp",spname);
2487 /* if use external stack but some variables were
2488 added to the local stack then decrement the
2490 if (options.useXstack && sym->stack) {
2491 emitcode("mov","a,sp");
2492 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2493 emitcode("mov","sp,a");
2497 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2498 if (options.useXstack) {
2499 emitcode("mov","r0,%s",spname);
2500 emitcode("movx","a,@r0");
2501 emitcode("mov","_bp,a");
2502 emitcode("dec","%s",spname);
2506 emitcode ("pop","_bp");
2510 /* restore the register bank */
2511 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2512 emitcode ("pop","psw");
2514 if (IS_ISR(sym->etype)) {
2516 /* now we need to restore the registers */
2517 /* if this isr has no bank i.e. is going to
2518 run with bank 0 , then we need to save more
2520 if (!SPEC_BANK(sym->etype)) {
2522 /* if this function does not call any other
2523 function then we can be economical and
2524 save only those registers that are used */
2525 if (! sym->hasFcall) {
2528 /* if any registers used */
2529 if (sym->regsUsed) {
2530 /* save the registers used */
2531 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2532 if (bitVectBitValue(sym->regsUsed,i) ||
2533 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2534 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2539 /* this function has a function call cannot
2540 determines register usage so we will have the
2542 unsaverbank(0,ic,FALSE);
2546 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2548 if (options.stack10bit)
2550 emitcode ("pop", "ap");
2551 emitcode ("pop", "dpx1");
2552 emitcode ("pop", "dph1");
2553 emitcode ("pop", "dpl1");
2555 emitcode ("pop", "dps");
2556 emitcode ("pop", "dpx");
2558 if (!inExcludeList("dph"))
2559 emitcode ("pop","dph");
2560 if (!inExcludeList("dpl"))
2561 emitcode ("pop","dpl");
2562 if (!inExcludeList("b"))
2563 emitcode ("pop","b");
2564 if (!inExcludeList("acc"))
2565 emitcode ("pop","acc");
2567 if (SPEC_CRTCL(sym->etype))
2568 emitcode("setb","ea");
2570 /* if debug then send end of function */
2571 /* if (options.debug && currFunc) { */
2574 emitcode("","C$%s$%d$%d$%d ==.",
2575 ic->filename,currFunc->lastLine,
2576 ic->level,ic->block);
2577 if (IS_STATIC(currFunc->etype))
2578 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2580 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2584 emitcode ("reti","");
2587 if (SPEC_CRTCL(sym->etype))
2588 emitcode("setb","ea");
2590 if (sym->calleeSave) {
2593 /* if any registers used */
2594 if (sym->regsUsed) {
2595 /* save the registers used */
2596 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2597 if (bitVectBitValue(sym->regsUsed,i) ||
2598 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2599 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2605 /* if debug then send end of function */
2608 emitcode("","C$%s$%d$%d$%d ==.",
2609 ic->filename,currFunc->lastLine,
2610 ic->level,ic->block);
2611 if (IS_STATIC(currFunc->etype))
2612 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2614 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2618 emitcode ("ret","");
2623 /*-----------------------------------------------------------------*/
2624 /* genRet - generate code for return statement */
2625 /*-----------------------------------------------------------------*/
2626 static void genRet (iCode *ic)
2628 int size,offset = 0 , pushed = 0;
2630 D(emitcode(";", "genRet "););
2632 /* if we have no return value then
2633 just generate the "ret" */
2637 /* we have something to return then
2638 move the return value into place */
2639 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2640 size = AOP_SIZE(IC_LEFT(ic));
2642 _startLazyDPSEvaluation();
2645 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2646 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2648 emitcode("push","%s",l);
2651 l = aopGet(AOP(IC_LEFT(ic)),offset,
2653 if (strcmp(fReturn[offset],l))
2654 emitcode("mov","%s,%s",fReturn[offset++],l);
2657 _endLazyDPSEvaluation();
2662 if (strcmp(fReturn[pushed],"a"))
2663 emitcode("pop",fReturn[pushed]);
2665 emitcode("pop","acc");
2668 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2671 /* generate a jump to the return label
2672 if the next is not the return statement */
2673 if (!(ic->next && ic->next->op == LABEL &&
2674 IC_LABEL(ic->next) == returnLabel))
2676 emitcode("ljmp","%05d$",(returnLabel->key+100));
2680 /*-----------------------------------------------------------------*/
2681 /* genLabel - generates a label */
2682 /*-----------------------------------------------------------------*/
2683 static void genLabel (iCode *ic)
2685 /* special case never generate */
2686 if (IC_LABEL(ic) == entryLabel)
2689 D(emitcode(";", "genLabel "););
2691 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2694 /*-----------------------------------------------------------------*/
2695 /* genGoto - generates a ljmp */
2696 /*-----------------------------------------------------------------*/
2697 static void genGoto (iCode *ic)
2699 D(emitcode(";", "genGoto "););
2700 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2703 /*-----------------------------------------------------------------*/
2704 /* findLabelBackwards: walks back through the iCode chain looking */
2705 /* for the given label. Returns number of iCode instructions */
2706 /* between that label and given ic. */
2707 /* Returns zero if label not found. */
2708 /*-----------------------------------------------------------------*/
2709 static int findLabelBackwards(iCode *ic, int key)
2718 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2720 /* printf("findLabelBackwards = %d\n", count); */
2728 /*-----------------------------------------------------------------*/
2729 /* genPlusIncr :- does addition with increment if possible */
2730 /*-----------------------------------------------------------------*/
2731 static bool genPlusIncr (iCode *ic)
2733 unsigned int icount ;
2734 unsigned int size = getDataSize(IC_RESULT(ic));
2736 /* will try to generate an increment */
2737 /* if the right side is not a literal
2739 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2742 /* if the literal value of the right hand side
2743 is greater than 4 then it is not worth it */
2744 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2747 /* if increment 16 bits in register */
2749 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2750 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2751 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2758 /* If the next instruction is a goto and the goto target
2759 * is <= 5 instructions previous to this, we can generate
2760 * jumps straight to that target.
2762 if (ic->next && ic->next->op == GOTO
2763 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2764 && labelRange <= 5 )
2766 emitcode(";", "tail increment optimized (range %d)", labelRange);
2767 tlbl = IC_LABEL(ic->next);
2772 tlbl = newiTempLabel(NULL);
2775 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2776 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2777 IS_AOP_PREG(IC_RESULT(ic)))
2778 emitcode("cjne","%s,#0x00,%05d$"
2779 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2782 emitcode("clr","a");
2783 emitcode("cjne","a,%s,%05d$"
2784 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2788 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2791 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2792 IS_AOP_PREG(IC_RESULT(ic)))
2793 emitcode("cjne","%s,#0x00,%05d$"
2794 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2797 emitcode("cjne","a,%s,%05d$"
2798 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2801 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2805 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2806 IS_AOP_PREG(IC_RESULT(ic)))
2807 emitcode("cjne","%s,#0x00,%05d$"
2808 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2811 emitcode("cjne","a,%s,%05d$"
2812 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2815 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2820 emitcode("","%05d$:",tlbl->key+100);
2825 /* if the sizes are greater than 1 then we cannot */
2826 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2827 AOP_SIZE(IC_LEFT(ic)) > 1 )
2830 /* we can if the aops of the left & result match or
2831 if they are in registers and the registers are the
2834 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2835 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2836 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2839 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2840 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2841 aopPut(AOP(IC_RESULT(ic)),"a",0);
2844 _startLazyDPSEvaluation();
2847 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2849 _endLazyDPSEvaluation();
2858 /*-----------------------------------------------------------------*/
2859 /* outBitAcc - output a bit in acc */
2860 /*-----------------------------------------------------------------*/
2861 static void outBitAcc(operand *result)
2863 symbol *tlbl = newiTempLabel(NULL);
2864 /* if the result is a bit */
2865 if (AOP_TYPE(result) == AOP_CRY){
2866 aopPut(AOP(result),"a",0);
2869 emitcode("jz","%05d$",tlbl->key+100);
2870 emitcode("mov","a,%s",one);
2871 emitcode("","%05d$:",tlbl->key+100);
2876 /*-----------------------------------------------------------------*/
2877 /* genPlusBits - generates code for addition of two bits */
2878 /*-----------------------------------------------------------------*/
2879 static void genPlusBits (iCode *ic)
2881 D(emitcode(";", "genPlusBits "););
2882 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2883 symbol *lbl = newiTempLabel(NULL);
2884 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2885 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2886 emitcode("cpl","c");
2887 emitcode("","%05d$:",(lbl->key+100));
2888 outBitC(IC_RESULT(ic));
2891 emitcode("clr","a");
2892 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2893 emitcode("rlc","a");
2894 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2895 emitcode("addc","a,#0x00");
2896 outAcc(IC_RESULT(ic));
2900 static void adjustArithmeticResult(iCode *ic)
2902 if (opIsGptr(IC_RESULT(ic)) &&
2903 opIsGptr(IC_LEFT(ic)) &&
2904 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2906 aopPut(AOP(IC_RESULT(ic)),
2907 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2911 if (opIsGptr(IC_RESULT(ic)) &&
2912 opIsGptr(IC_RIGHT(ic)) &&
2913 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2915 aopPut(AOP(IC_RESULT(ic)),
2916 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2920 if (opIsGptr(IC_RESULT(ic)) &&
2921 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2922 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2923 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2924 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2926 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2927 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2931 #define AOP_OP_3(ic) \
2932 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2933 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2934 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2935 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2936 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2938 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2940 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2943 #define AOP_SET_LOCALS(ic) \
2944 left = IC_LEFT(ic); \
2945 right = IC_RIGHT(ic); \
2946 result = IC_RESULT(ic);
2948 /*-----------------------------------------------------------------*/
2949 /* genPlus - generates code for addition */
2950 /*-----------------------------------------------------------------*/
2951 static void genPlus (iCode *ic)
2953 int size, offset = 0;
2954 bool pushResult = FALSE;
2957 D(emitcode(";", "genPlus "););
2959 /* special cases :- */
2962 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2963 aopOp (IC_LEFT(ic),ic,FALSE,
2964 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
2966 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2967 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2969 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2970 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2976 aopOp (IC_RESULT(ic),ic,TRUE,
2977 ((AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)
2978 || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR)));
2980 /* if literal, literal on the right or
2981 if left requires ACC or right is already
2983 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2984 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2985 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2986 operand *t = IC_RIGHT(ic);
2987 IC_RIGHT(ic) = IC_LEFT(ic);
2991 /* if both left & right are in bit
2993 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2994 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2999 /* if left in bit space & right literal */
3000 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3001 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3002 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3003 /* if result in bit space */
3004 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3005 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
3006 emitcode("cpl","c");
3007 outBitC(IC_RESULT(ic));
3009 size = getDataSize(IC_RESULT(ic));
3010 _startLazyDPSEvaluation();
3012 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3013 emitcode("addc","a,#00");
3014 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3016 _endLazyDPSEvaluation();
3021 /* if I can do an increment instead
3022 of add then GOOD for ME */
3023 if (genPlusIncr (ic) == TRUE)
3027 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3029 _startLazyDPSEvaluation();
3032 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3034 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3036 emitcode("add","a,%s",
3037 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3039 emitcode("addc","a,%s",
3040 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3042 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3044 emitcode("add","a,%s",
3045 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3047 emitcode("addc","a,%s",
3048 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3052 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3056 emitcode("push", "acc");
3060 _endLazyDPSEvaluation();
3064 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3066 size = getDataSize(IC_LEFT(ic));
3067 rSize = getDataSize(IC_RESULT(ic));
3069 /* If the pushed data is bigger than the result,
3070 * simply discard unused bytes. Icky, but works.
3072 * Should we throw a warning here? We're losing data...
3074 while (size > rSize)
3076 D(emitcode(";", "discarding unused result byte."););
3077 emitcode("pop", "acc");
3083 emitcode("clr", "a");
3084 /* Conversly, we haven't pushed enough here.
3085 * just zero-pad, and all is well.
3087 while (size < rSize)
3089 emitcode("push", "acc");
3095 _startLazyDPSEvaluation();
3098 emitcode("pop", "acc");
3099 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3101 _endLazyDPSEvaluation();
3104 adjustArithmeticResult(ic);
3107 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3108 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3109 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3112 /*-----------------------------------------------------------------*/
3113 /* genMinusDec :- does subtraction with deccrement if possible */
3114 /*-----------------------------------------------------------------*/
3115 static bool genMinusDec (iCode *ic)
3117 unsigned int icount ;
3118 unsigned int size = getDataSize(IC_RESULT(ic));
3120 /* will try to generate an increment */
3121 /* if the right side is not a literal
3123 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3126 /* if the literal value of the right hand side
3127 is greater than 4 then it is not worth it */
3128 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3131 /* if decrement 16 bits in register */
3132 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3133 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3134 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3141 /* If the next instruction is a goto and the goto target
3142 * is <= 5 instructions previous to this, we can generate
3143 * jumps straight to that target.
3145 if (ic->next && ic->next->op == GOTO
3146 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3147 && labelRange <= 5 )
3149 emitcode(";", "tail decrement optimized (range %d)", labelRange);
3150 tlbl = IC_LABEL(ic->next);
3155 tlbl = newiTempLabel(NULL);
3159 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3160 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3161 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3162 IS_AOP_PREG(IC_RESULT(ic)))
3163 emitcode("cjne","%s,#0xff,%05d$"
3164 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3167 emitcode("mov","a,#0xff");
3168 emitcode("cjne","a,%s,%05d$"
3169 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3172 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3175 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3176 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3177 IS_AOP_PREG(IC_RESULT(ic)))
3178 emitcode("cjne","%s,#0xff,%05d$"
3179 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3182 emitcode("cjne","a,%s,%05d$"
3183 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3186 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3190 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3191 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3192 IS_AOP_PREG(IC_RESULT(ic)))
3193 emitcode("cjne","%s,#0xff,%05d$"
3194 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3197 emitcode("cjne","a,%s,%05d$"
3198 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3201 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3205 emitcode("","%05d$:",tlbl->key+100);
3210 /* if the sizes are greater than 1 then we cannot */
3211 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3212 AOP_SIZE(IC_LEFT(ic)) > 1 )
3215 /* we can if the aops of the left & result match or
3216 if they are in registers and the registers are the
3219 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3220 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3221 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3223 _startLazyDPSEvaluation();
3226 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3228 _endLazyDPSEvaluation();
3236 /*-----------------------------------------------------------------*/
3237 /* addSign - complete with sign */
3238 /*-----------------------------------------------------------------*/
3239 static void addSign(operand *result, int offset, int sign)
3241 int size = (getDataSize(result) - offset);
3244 emitcode("rlc","a");
3245 emitcode("subb","a,acc");
3247 aopPut(AOP(result),"a",offset++);
3250 aopPut(AOP(result),zero,offset++);
3254 /*-----------------------------------------------------------------*/
3255 /* genMinusBits - generates code for subtraction of two bits */
3256 /*-----------------------------------------------------------------*/
3257 static void genMinusBits (iCode *ic)
3259 symbol *lbl = newiTempLabel(NULL);
3261 D(emitcode(";", "genMinusBits "););
3263 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3264 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3265 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3266 emitcode("cpl","c");
3267 emitcode("","%05d$:",(lbl->key+100));
3268 outBitC(IC_RESULT(ic));
3271 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3272 emitcode("subb","a,acc");
3273 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3274 emitcode("inc","a");
3275 emitcode("","%05d$:",(lbl->key+100));
3276 aopPut(AOP(IC_RESULT(ic)),"a",0);
3277 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3281 /*-----------------------------------------------------------------*/
3282 /* genMinus - generates code for subtraction */
3283 /*-----------------------------------------------------------------*/
3284 static void genMinus (iCode *ic)
3286 int size, offset = 0;
3288 unsigned long lit = 0L;
3289 bool pushResult = FALSE;
3291 D(emitcode(";", "genMinus "););
3293 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3294 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3295 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3296 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3302 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3304 /* special cases :- */
3305 /* if both left & right are in bit space */
3306 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3307 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3312 /* if I can do an decrement instead
3313 of subtract then GOOD for ME */
3314 if (genMinusDec (ic) == TRUE)
3319 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3321 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3325 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3330 /* if literal, add a,#-lit, else normal subb */
3331 _startLazyDPSEvaluation();
3333 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3334 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3335 emitcode("subb","a,%s",
3336 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3338 /* first add without previous c */
3340 emitcode("add","a,#0x%02x",
3341 (unsigned int)(lit & 0x0FFL));
3343 emitcode("addc","a,#0x%02x",
3344 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3349 emitcode("push", "acc");
3353 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3357 _endLazyDPSEvaluation();
3361 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3363 size = getDataSize(IC_LEFT(ic));
3364 rSize = getDataSize(IC_RESULT(ic));
3366 /* If the pushed data is bigger than the result,
3367 * simply discard unused bytes. Icky, but works.
3369 * Should we throw a warning here? We're losing data...
3371 while (size > getDataSize(IC_RESULT(ic)))
3373 emitcode(";", "discarding unused result byte.");
3374 emitcode("pop", "acc");
3380 emitcode("clr", "a");
3381 /* Conversly, we haven't pushed enough here.
3382 * just zero-pad, and all is well.
3384 while (size < rSize)
3386 emitcode("push", "acc");
3394 emitcode("pop", "acc");
3395 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3399 adjustArithmeticResult(ic);
3402 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3403 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3404 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3408 /*-----------------------------------------------------------------*/
3409 /* genMultbits :- multiplication of bits */
3410 /*-----------------------------------------------------------------*/
3411 static void genMultbits (operand *left,
3415 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3416 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3421 /*-----------------------------------------------------------------*/
3422 /* genMultOneByte : 8 bit multiplication & division */
3423 /*-----------------------------------------------------------------*/
3424 static void genMultOneByte (operand *left,
3428 link *opetype = operandType(result);
3433 /* (if two literals, the value is computed before) */
3434 /* if one literal, literal on the right */
3435 if (AOP_TYPE(left) == AOP_LIT){
3441 size = AOP_SIZE(result);
3442 /* signed or unsigned */
3443 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3444 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3446 emitcode("mul","ab");
3447 /* if result size = 1, mul signed = mul unsigned */
3448 aopPut(AOP(result),"a",0);
3450 if (SPEC_USIGN(opetype)){
3451 aopPut(AOP(result),"b",1);
3453 /* for filling the MSBs */
3454 emitcode("clr","a");
3457 emitcode("mov","a,b");
3459 /* adjust the MSB if left or right neg */
3461 /* if one literal */
3462 if (AOP_TYPE(right) == AOP_LIT){
3463 /* AND literal negative */
3464 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3465 /* adjust MSB (c==0 after mul) */
3466 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3470 lbl = newiTempLabel(NULL);
3471 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3472 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3473 emitcode("","%05d$:",(lbl->key+100));
3474 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3475 lbl = newiTempLabel(NULL);
3476 emitcode("jc","%05d$",(lbl->key+100));
3477 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3478 emitcode("","%05d$:",(lbl->key+100));
3481 lbl = newiTempLabel(NULL);
3482 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3483 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3484 emitcode("","%05d$:",(lbl->key+100));
3485 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3486 lbl = newiTempLabel(NULL);
3487 emitcode("jc","%05d$",(lbl->key+100));
3488 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3489 emitcode("","%05d$:",(lbl->key+100));
3491 aopPut(AOP(result),"a",1);
3494 emitcode("rlc","a");
3495 emitcode("subb","a,acc");
3502 aopPut(AOP(result),"a",offset++);
3506 /*-----------------------------------------------------------------*/
3507 /* genMult - generates code for multiplication */
3508 /*-----------------------------------------------------------------*/
3509 static void genMult (iCode *ic)
3511 operand *left = IC_LEFT(ic);
3512 operand *right = IC_RIGHT(ic);
3513 operand *result= IC_RESULT(ic);
3515 D(emitcode(";", "genMult "););
3517 /* assign the amsops */
3520 aopOp (left,ic,FALSE, FALSE);
3521 aopOp (right,ic,FALSE, TRUE);
3522 aopOp (result,ic,TRUE, FALSE);
3525 /* special cases first */
3527 if (AOP_TYPE(left) == AOP_CRY &&
3528 AOP_TYPE(right)== AOP_CRY) {
3529 genMultbits(left,right,result);
3533 /* if both are of size == 1 */
3534 if (AOP_SIZE(left) == 1 &&
3535 AOP_SIZE(right) == 1 ) {
3536 genMultOneByte(left,right,result);
3540 /* should have been converted to function call */
3544 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3545 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3546 freeAsmop(result,NULL,ic,TRUE);
3549 /*-----------------------------------------------------------------*/
3550 /* genDivbits :- division of bits */
3551 /*-----------------------------------------------------------------*/
3552 static void genDivbits (operand *left,
3559 /* the result must be bit */
3560 LOAD_AB_FOR_DIV(left, right, l);
3561 emitcode("div","ab");
3562 emitcode("rrc","a");
3563 aopPut(AOP(result),"c",0);
3566 /*-----------------------------------------------------------------*/
3567 /* genDivOneByte : 8 bit division */
3568 /*-----------------------------------------------------------------*/
3569 static void genDivOneByte (operand *left,
3573 link *opetype = operandType(result);
3578 size = AOP_SIZE(result) - 1;
3580 /* signed or unsigned */
3581 if (SPEC_USIGN(opetype)) {
3582 /* unsigned is easy */
3583 LOAD_AB_FOR_DIV(left, right, l);
3584 emitcode("div","ab");
3585 aopPut(AOP(result),"a",0);
3587 aopPut(AOP(result),zero,offset++);
3591 /* signed is a little bit more difficult */
3593 /* save the signs of the operands */
3594 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3596 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3597 emitcode("push","acc"); /* save it on the stack */
3599 /* now sign adjust for both left & right */
3600 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3602 lbl = newiTempLabel(NULL);
3603 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3604 emitcode("cpl","a");
3605 emitcode("inc","a");
3606 emitcode("","%05d$:",(lbl->key+100));
3607 emitcode("mov","b,a");
3609 /* sign adjust left side */
3610 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3613 lbl = newiTempLabel(NULL);
3614 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3615 emitcode("cpl","a");
3616 emitcode("inc","a");
3617 emitcode("","%05d$:",(lbl->key+100));
3619 /* now the division */
3620 emitcode("nop", "; workaround for DS80C390 div bug.");
3621 emitcode("div","ab");
3622 /* we are interested in the lower order
3624 emitcode("mov","b,a");
3625 lbl = newiTempLabel(NULL);
3626 emitcode("pop","acc");
3627 /* if there was an over flow we don't
3628 adjust the sign of the result */
3629 emitcode("jb","ov,%05d$",(lbl->key+100));
3630 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3632 emitcode("clr","a");
3633 emitcode("subb","a,b");
3634 emitcode("mov","b,a");
3635 emitcode("","%05d$:",(lbl->key+100));
3637 /* now we are done */
3638 aopPut(AOP(result),"b",0);
3640 emitcode("mov","c,b.7");
3641 emitcode("subb","a,acc");
3644 aopPut(AOP(result),"a",offset++);
3648 /*-----------------------------------------------------------------*/
3649 /* genDiv - generates code for division */
3650 /*-----------------------------------------------------------------*/
3651 static void genDiv (iCode *ic)
3653 operand *left = IC_LEFT(ic);
3654 operand *right = IC_RIGHT(ic);
3655 operand *result= IC_RESULT(ic);
3657 D(emitcode(";", "genDiv "););
3659 /* assign the amsops */
3662 aopOp (left,ic,FALSE, FALSE);
3663 aopOp (right,ic,FALSE, TRUE);
3664 aopOp (result,ic,TRUE, FALSE);
3667 /* special cases first */
3669 if (AOP_TYPE(left) == AOP_CRY &&
3670 AOP_TYPE(right)== AOP_CRY) {
3671 genDivbits(left,right,result);
3675 /* if both are of size == 1 */
3676 if (AOP_SIZE(left) == 1 &&
3677 AOP_SIZE(right) == 1 ) {
3678 genDivOneByte(left,right,result);
3682 /* should have been converted to function call */
3685 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3686 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3687 freeAsmop(result,NULL,ic,TRUE);
3690 /*-----------------------------------------------------------------*/
3691 /* genModbits :- modulus of bits */
3692 /*-----------------------------------------------------------------*/
3693 static void genModbits (operand *left,
3700 /* the result must be bit */
3701 LOAD_AB_FOR_DIV(left, right, l);
3702 emitcode("div","ab");
3703 emitcode("mov","a,b");
3704 emitcode("rrc","a");
3705 aopPut(AOP(result),"c",0);
3708 /*-----------------------------------------------------------------*/
3709 /* genModOneByte : 8 bit modulus */
3710 /*-----------------------------------------------------------------*/
3711 static void genModOneByte (operand *left,
3715 link *opetype = operandType(result);
3719 /* signed or unsigned */
3720 if (SPEC_USIGN(opetype)) {
3721 /* unsigned is easy */
3722 LOAD_AB_FOR_DIV(left, right, l);
3723 emitcode("div","ab");
3724 aopPut(AOP(result),"b",0);
3728 /* signed is a little bit more difficult */
3730 /* save the signs of the operands */
3731 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3734 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3735 emitcode("push","acc"); /* save it on the stack */
3737 /* now sign adjust for both left & right */
3738 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3741 lbl = newiTempLabel(NULL);
3742 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3743 emitcode("cpl","a");
3744 emitcode("inc","a");
3745 emitcode("","%05d$:",(lbl->key+100));
3746 emitcode("mov","b,a");
3748 /* sign adjust left side */
3749 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3752 lbl = newiTempLabel(NULL);
3753 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3754 emitcode("cpl","a");
3755 emitcode("inc","a");
3756 emitcode("","%05d$:",(lbl->key+100));
3758 /* now the multiplication */
3759 emitcode("nop", "; workaround for DS80C390 div bug.");
3760 emitcode("div","ab");
3761 /* we are interested in the lower order
3763 lbl = newiTempLabel(NULL);
3764 emitcode("pop","acc");
3765 /* if there was an over flow we don't
3766 adjust the sign of the result */
3767 emitcode("jb","ov,%05d$",(lbl->key+100));
3768 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3770 emitcode("clr","a");
3771 emitcode("subb","a,b");
3772 emitcode("mov","b,a");
3773 emitcode("","%05d$:",(lbl->key+100));
3775 /* now we are done */
3776 aopPut(AOP(result),"b",0);
3780 /*-----------------------------------------------------------------*/
3781 /* genMod - generates code for division */
3782 /*-----------------------------------------------------------------*/
3783 static void genMod (iCode *ic)
3785 operand *left = IC_LEFT(ic);
3786 operand *right = IC_RIGHT(ic);
3787 operand *result= IC_RESULT(ic);
3789 D(emitcode(";", "genMod "););
3791 /* assign the amsops */
3794 aopOp (left,ic,FALSE, FALSE);
3795 aopOp (right,ic,FALSE, TRUE);
3796 aopOp (result,ic,TRUE, FALSE);
3799 /* special cases first */
3801 if (AOP_TYPE(left) == AOP_CRY &&
3802 AOP_TYPE(right)== AOP_CRY) {
3803 genModbits(left,right,result);
3807 /* if both are of size == 1 */
3808 if (AOP_SIZE(left) == 1 &&
3809 AOP_SIZE(right) == 1 ) {
3810 genModOneByte(left,right,result);
3814 /* should have been converted to function call */
3818 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3819 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3820 freeAsmop(result,NULL,ic,TRUE);
3823 /*-----------------------------------------------------------------*/
3824 /* genIfxJump :- will create a jump depending on the ifx */
3825 /*-----------------------------------------------------------------*/
3826 static void genIfxJump (iCode *ic, char *jval)
3829 symbol *tlbl = newiTempLabel(NULL);
3832 D(emitcode(";", "genIfxJump "););
3834 /* if true label then we jump if condition
3836 if ( IC_TRUE(ic) ) {
3838 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3839 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3842 /* false label is present */
3843 jlbl = IC_FALSE(ic) ;
3844 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3845 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3847 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3848 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3850 emitcode(inst,"%05d$",tlbl->key+100);
3851 emitcode("ljmp","%05d$",jlbl->key+100);
3852 emitcode("","%05d$:",tlbl->key+100);
3854 /* mark the icode as generated */
3858 /*-----------------------------------------------------------------*/
3859 /* genCmp :- greater or less than comparison */
3860 /*-----------------------------------------------------------------*/
3861 static void genCmp (operand *left,operand *right,
3862 operand *result, iCode *ifx, int sign)
3864 int size, offset = 0 ;
3865 unsigned long lit = 0L;
3866 bool swappedOps = FALSE;
3868 D(emitcode(";", "genCmp"););
3871 /* If left if lit and right isn't, swap 'em. */
3872 if (AOP_TYPE(left) == AOP_LIT &&
3873 AOP_TYPE(right) != AOP_LIT)
3875 operand *tmp = left;
3878 D(emitcode(";", "kevin literal hack"););
3879 swappedOps = !swappedOps;
3882 if (AOP_NEEDSACC(right))
3884 if (AOP_NEEDSACC(left))
3886 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3887 "both CMP operands need ACC!");
3892 operand *tmp = left;
3895 D(emitcode(";", "kevin ACC hack"););
3896 swappedOps = !swappedOps;
3901 /* if left & right are bit variables */
3902 if (AOP_TYPE(left) == AOP_CRY &&
3903 AOP_TYPE(right) == AOP_CRY ) {
3904 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3905 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3907 /* subtract right from left if at the
3908 end the carry flag is set then we know that
3909 left is greater than right */
3910 size = max(AOP_SIZE(left),AOP_SIZE(right));
3912 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3913 if((size == 1) && !sign &&
3914 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3915 symbol *lbl = newiTempLabel(NULL);
3916 emitcode("cjne","%s,%s,%05d$",
3917 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3918 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3920 emitcode("","%05d$:",lbl->key+100);
3922 if(AOP_TYPE(right) == AOP_LIT){
3923 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3924 /* optimize if(x < 0) or if(x >= 0) */
3930 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3931 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3932 genIfxJump (ifx,"acc.7");
3936 emitcode("rlc","a");
3944 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3945 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3946 emitcode(";", "genCmp #2");
3947 if (sign && (size == 0))
3949 emitcode(";", "genCmp #3");
3950 emitcode("xrl","a,#0x80");
3951 if (AOP_TYPE(right) == AOP_LIT)
3953 unsigned long lit = (unsigned long)
3954 floatFromVal(AOP(right)->aopu.aop_lit);
3955 emitcode(";", "genCmp #3.1");
3956 emitcode("subb","a,#0x%02x",
3957 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3961 emitcode(";", "genCmp #3.2");
3962 if (AOP_NEEDSACC(right))
3964 emitcode("push", "acc");
3966 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3967 FALSE,FALSE,FALSE));
3968 emitcode("xrl","b,#0x80");
3969 if (AOP_NEEDSACC(right))
3971 emitcode("pop", "acc");
3973 emitcode("subb","a,b");
3980 emitcode(";", "genCmp #4");
3981 if (AOP_NEEDSACC(right))
3984 emitcode(";", "genCmp #4.1");
3985 emitcode("xch", "a, b");
3986 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3987 emitcode("xch", "a, b");
3992 emitcode(";", "genCmp #4.2");
3993 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
3996 emitcode("subb","a,%s",s);
4005 D(emitcode(";","kevHack: flip carry."););
4006 emitcode("cpl", "c");
4009 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4012 /* if the result is used in the next
4013 ifx conditional branch then generate
4014 code a little differently */
4016 genIfxJump (ifx,"c");
4019 /* leave the result in acc */
4023 /*-----------------------------------------------------------------*/
4024 /* genCmpGt :- greater than comparison */
4025 /*-----------------------------------------------------------------*/
4026 static void genCmpGt (iCode *ic, iCode *ifx)
4028 operand *left, *right, *result;
4029 link *letype , *retype;
4032 D(emitcode(";", "genCmpGt "););
4035 right= IC_RIGHT(ic);
4036 result = IC_RESULT(ic);
4038 letype = getSpec(operandType(left));
4039 retype =getSpec(operandType(right));
4040 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4041 /* assign the amsops */
4044 aopOp (left,ic,FALSE, TRUE);
4045 aopOp (right,ic,FALSE, FALSE);
4046 aopOp (result,ic,TRUE, FALSE);
4049 genCmp(right, left, result, ifx, sign);
4051 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4052 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4053 freeAsmop(result,NULL,ic,TRUE);
4056 /*-----------------------------------------------------------------*/
4057 /* genCmpLt - less than comparisons */
4058 /*-----------------------------------------------------------------*/
4059 static void genCmpLt (iCode *ic, iCode *ifx)
4061 operand *left, *right, *result;
4062 link *letype , *retype;
4065 D(emitcode(";", "genCmpLt "););
4068 right= IC_RIGHT(ic);
4069 result = IC_RESULT(ic);
4071 letype = getSpec(operandType(left));
4072 retype =getSpec(operandType(right));
4073 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4075 /* assign the amsops */
4078 aopOp (left,ic,FALSE, FALSE);
4079 aopOp (right,ic,FALSE, TRUE);
4080 aopOp (result,ic,TRUE, FALSE);
4083 genCmp(left, right, result, ifx, sign);
4085 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4086 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4087 freeAsmop(result,NULL,ic,TRUE);
4090 /*-----------------------------------------------------------------*/
4091 /* gencjneshort - compare and jump if not equal */
4092 /*-----------------------------------------------------------------*/
4093 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4095 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4097 unsigned long lit = 0L;
4099 D(emitcode(";", "gencjneshort"););
4101 /* if the left side is a literal or
4102 if the right is in a pointer register and left
4104 if ((AOP_TYPE(left) == AOP_LIT) ||
4105 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4111 if(AOP_TYPE(right) == AOP_LIT)
4112 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4114 if (opIsGptr(left) || opIsGptr(right))
4116 /* We are comparing a generic pointer to something.
4117 * Exclude the generic type byte from the comparison.
4120 D(emitcode(";", "cjneshort: generic ptr special case.");)
4124 /* if the right side is a literal then anything goes */
4125 if (AOP_TYPE(right) == AOP_LIT &&
4126 AOP_TYPE(left) != AOP_DIR ) {
4128 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4130 emitcode("cjne","a,%s,%05d$",
4131 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4137 /* if the right side is in a register or in direct space or
4138 if the left is a pointer register & right is not */
4139 else if (AOP_TYPE(right) == AOP_REG ||
4140 AOP_TYPE(right) == AOP_DIR ||
4141 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4142 (IS_AOP_PREG(left) && !IS_AOP_PREG(right)))
4146 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4147 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4148 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4149 emitcode("jnz","%05d$",lbl->key+100);
4151 emitcode("cjne","a,%s,%05d$",
4152 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4157 /* right is a pointer reg need both a & b */
4159 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4161 emitcode("mov","b,%s",l);
4162 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4163 emitcode("cjne","a,b,%05d$",lbl->key+100);
4169 /*-----------------------------------------------------------------*/
4170 /* gencjne - compare and jump if not equal */
4171 /*-----------------------------------------------------------------*/
4172 static void gencjne(operand *left, operand *right, symbol *lbl)
4174 symbol *tlbl = newiTempLabel(NULL);
4176 D(emitcode(";", "gencjne"););
4178 gencjneshort(left, right, lbl);
4180 emitcode("mov","a,%s",one);
4181 emitcode("sjmp","%05d$",tlbl->key+100);
4182 emitcode("","%05d$:",lbl->key+100);
4183 emitcode("clr","a");
4184 emitcode("","%05d$:",tlbl->key+100);
4187 /*-----------------------------------------------------------------*/
4188 /* genCmpEq - generates code for equal to */
4189 /*-----------------------------------------------------------------*/
4190 static void genCmpEq (iCode *ic, iCode *ifx)
4192 operand *left, *right, *result;
4194 D(emitcode(";", "genCmpEq "););
4199 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4200 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4201 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4204 /* if literal, literal on the right or
4205 if the right is in a pointer register and left
4207 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4208 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4209 operand *t = IC_RIGHT(ic);
4210 IC_RIGHT(ic) = IC_LEFT(ic);
4214 if(ifx && !AOP_SIZE(result)){
4216 /* if they are both bit variables */
4217 if (AOP_TYPE(left) == AOP_CRY &&
4218 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4219 if(AOP_TYPE(right) == AOP_LIT){
4220 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4222 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4223 emitcode("cpl","c");
4224 } else if(lit == 1L) {
4225 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4227 emitcode("clr","c");
4229 /* AOP_TYPE(right) == AOP_CRY */
4231 symbol *lbl = newiTempLabel(NULL);
4232 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4233 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4234 emitcode("cpl","c");
4235 emitcode("","%05d$:",(lbl->key+100));
4237 /* if true label then we jump if condition
4239 tlbl = newiTempLabel(NULL);
4240 if ( IC_TRUE(ifx) ) {
4241 emitcode("jnc","%05d$",tlbl->key+100);
4242 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4244 emitcode("jc","%05d$",tlbl->key+100);
4245 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4247 emitcode("","%05d$:",tlbl->key+100);
4249 tlbl = newiTempLabel(NULL);
4250 gencjneshort(left, right, tlbl);
4251 if ( IC_TRUE(ifx) ) {
4252 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4253 emitcode("","%05d$:",tlbl->key+100);
4255 symbol *lbl = newiTempLabel(NULL);
4256 emitcode("sjmp","%05d$",lbl->key+100);
4257 emitcode("","%05d$:",tlbl->key+100);
4258 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4259 emitcode("","%05d$:",lbl->key+100);
4262 /* mark the icode as generated */
4267 /* if they are both bit variables */
4268 if (AOP_TYPE(left) == AOP_CRY &&
4269 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4270 if(AOP_TYPE(right) == AOP_LIT){
4271 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4273 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4274 emitcode("cpl","c");
4275 } else if(lit == 1L) {
4276 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4278 emitcode("clr","c");
4280 /* AOP_TYPE(right) == AOP_CRY */
4282 symbol *lbl = newiTempLabel(NULL);
4283 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4284 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4285 emitcode("cpl","c");
4286 emitcode("","%05d$:",(lbl->key+100));
4289 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4294 genIfxJump (ifx,"c");
4297 /* if the result is used in an arithmetic operation
4298 then put the result in place */
4301 gencjne(left,right,newiTempLabel(NULL));
4302 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4303 aopPut(AOP(result),"a",0);
4307 genIfxJump (ifx,"a");
4310 /* if the result is used in an arithmetic operation
4311 then put the result in place */
4312 if (AOP_TYPE(result) != AOP_CRY)
4314 /* leave the result in acc */
4318 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4319 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4320 freeAsmop(result,NULL,ic,TRUE);
4323 /*-----------------------------------------------------------------*/
4324 /* ifxForOp - returns the icode containing the ifx for operand */
4325 /*-----------------------------------------------------------------*/
4326 static iCode *ifxForOp ( operand *op, iCode *ic )
4328 /* if true symbol then needs to be assigned */
4329 if (IS_TRUE_SYMOP(op))
4332 /* if this has register type condition and
4333 the next instruction is ifx with the same operand
4334 and live to of the operand is upto the ifx only then */
4336 ic->next->op == IFX &&
4337 IC_COND(ic->next)->key == op->key &&
4338 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4343 /*-----------------------------------------------------------------*/
4344 /* genAndOp - for && operation */
4345 /*-----------------------------------------------------------------*/
4346 static void genAndOp (iCode *ic)
4348 operand *left,*right, *result;
4351 D(emitcode(";", "genAndOp "););
4353 /* note here that && operations that are in an
4354 if statement are taken away by backPatchLabels
4355 only those used in arthmetic operations remain */
4359 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4360 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4361 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4364 /* if both are bit variables */
4365 if (AOP_TYPE(left) == AOP_CRY &&
4366 AOP_TYPE(right) == AOP_CRY ) {
4367 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4368 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4371 tlbl = newiTempLabel(NULL);
4373 emitcode("jz","%05d$",tlbl->key+100);
4375 emitcode("","%05d$:",tlbl->key+100);
4379 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4380 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4381 freeAsmop(result,NULL,ic,TRUE);
4385 /*-----------------------------------------------------------------*/
4386 /* genOrOp - for || operation */
4387 /*-----------------------------------------------------------------*/
4388 static void genOrOp (iCode *ic)
4390 operand *left,*right, *result;
4393 D(emitcode(";", "genOrOp "););
4395 /* note here that || operations that are in an
4396 if statement are taken away by backPatchLabels
4397 only those used in arthmetic operations remain */
4401 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4402 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4403 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4406 /* if both are bit variables */
4407 if (AOP_TYPE(left) == AOP_CRY &&
4408 AOP_TYPE(right) == AOP_CRY ) {
4409 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4410 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4413 tlbl = newiTempLabel(NULL);
4415 emitcode("jnz","%05d$",tlbl->key+100);
4417 emitcode("","%05d$:",tlbl->key+100);
4421 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4422 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4423 freeAsmop(result,NULL,ic,TRUE);
4426 /*-----------------------------------------------------------------*/
4427 /* isLiteralBit - test if lit == 2^n */
4428 /*-----------------------------------------------------------------*/
4429 static int isLiteralBit(unsigned long lit)
4431 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4432 0x100L,0x200L,0x400L,0x800L,
4433 0x1000L,0x2000L,0x4000L,0x8000L,
4434 0x10000L,0x20000L,0x40000L,0x80000L,
4435 0x100000L,0x200000L,0x400000L,0x800000L,
4436 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4437 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4440 for(idx = 0; idx < 32; idx++)
4446 /*-----------------------------------------------------------------*/
4447 /* continueIfTrue - */
4448 /*-----------------------------------------------------------------*/
4449 static void continueIfTrue (iCode *ic)
4452 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4456 /*-----------------------------------------------------------------*/
4458 /*-----------------------------------------------------------------*/
4459 static void jumpIfTrue (iCode *ic)
4462 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4466 /*-----------------------------------------------------------------*/
4467 /* jmpTrueOrFalse - */
4468 /*-----------------------------------------------------------------*/
4469 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4471 // ugly but optimized by peephole
4473 symbol *nlbl = newiTempLabel(NULL);
4474 emitcode("sjmp","%05d$",nlbl->key+100);
4475 emitcode("","%05d$:",tlbl->key+100);
4476 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4477 emitcode("","%05d$:",nlbl->key+100);
4480 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4481 emitcode("","%05d$:",tlbl->key+100);
4486 /*-----------------------------------------------------------------*/
4487 /* genAnd - code for and */
4488 /*-----------------------------------------------------------------*/
4489 static void genAnd (iCode *ic, iCode *ifx)
4491 operand *left, *right, *result;
4493 unsigned long lit = 0L;
4497 D(emitcode(";", "genAnd "););
4502 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4503 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4504 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4508 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4510 AOP_TYPE(left), AOP_TYPE(right));
4511 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4513 AOP_SIZE(left), AOP_SIZE(right));
4516 /* if left is a literal & right is not then exchange them */
4517 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4518 AOP_NEEDSACC(left)) {
4519 operand *tmp = right ;
4524 /* if result = right then exchange them */
4525 if(sameRegs(AOP(result),AOP(right))){
4526 operand *tmp = right ;
4531 /* if right is bit then exchange them */
4532 if (AOP_TYPE(right) == AOP_CRY &&
4533 AOP_TYPE(left) != AOP_CRY){
4534 operand *tmp = right ;
4538 if(AOP_TYPE(right) == AOP_LIT)
4539 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4541 size = AOP_SIZE(result);
4544 // result = bit & yy;
4545 if (AOP_TYPE(left) == AOP_CRY){
4546 // c = bit & literal;
4547 if(AOP_TYPE(right) == AOP_LIT){
4549 if(size && sameRegs(AOP(result),AOP(left)))
4552 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4555 if(size && (AOP_TYPE(result) == AOP_CRY)){
4556 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4559 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4563 emitcode("clr","c");
4566 if (AOP_TYPE(right) == AOP_CRY){
4568 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4569 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4572 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4574 emitcode("rrc","a");
4575 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4583 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4584 genIfxJump(ifx, "c");
4588 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4589 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4590 if((AOP_TYPE(right) == AOP_LIT) &&
4591 (AOP_TYPE(result) == AOP_CRY) &&
4592 (AOP_TYPE(left) != AOP_CRY)){
4593 int posbit = isLiteralBit(lit);
4597 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4600 emitcode("mov","c,acc.%d",posbit&0x07);
4604 sprintf(buffer,"acc.%d",posbit&0x07);
4605 genIfxJump(ifx, buffer);
4610 symbol *tlbl = newiTempLabel(NULL);
4611 int sizel = AOP_SIZE(left);
4613 emitcode("setb","c");
4615 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4616 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4618 if((posbit = isLiteralBit(bytelit)) != 0)
4619 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4621 if(bytelit != 0x0FFL)
4622 emitcode("anl","a,%s",
4623 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4624 emitcode("jnz","%05d$",tlbl->key+100);
4629 // bit = left & literal
4631 emitcode("clr","c");
4632 emitcode("","%05d$:",tlbl->key+100);
4634 // if(left & literal)
4637 jmpTrueOrFalse(ifx, tlbl);
4645 /* if left is same as result */
4646 if(sameRegs(AOP(result),AOP(left))){
4647 for(;size--; offset++) {
4648 if(AOP_TYPE(right) == AOP_LIT){
4649 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4653 aopPut(AOP(result),zero,offset);
4655 if (IS_AOP_PREG(result)) {
4656 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4657 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4658 aopPut(AOP(result),"a",offset);
4660 emitcode("anl","%s,%s",
4661 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4662 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4664 if (AOP_TYPE(left) == AOP_ACC)
4665 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4667 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4668 if (IS_AOP_PREG(result)) {
4669 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4670 aopPut(AOP(result),"a",offset);
4673 emitcode("anl","%s,a",
4674 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4679 // left & result in different registers
4680 if(AOP_TYPE(result) == AOP_CRY){
4682 // if(size), result in bit
4683 // if(!size && ifx), conditional oper: if(left & right)
4684 symbol *tlbl = newiTempLabel(NULL);
4685 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4687 emitcode("setb","c");
4689 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4690 emitcode("anl","a,%s",
4691 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4692 emitcode("jnz","%05d$",tlbl->key+100);
4697 emitcode("","%05d$:",tlbl->key+100);
4700 jmpTrueOrFalse(ifx, tlbl);
4702 for(;(size--);offset++) {
4704 // result = left & right
4705 if(AOP_TYPE(right) == AOP_LIT){
4706 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4708 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4711 } else if(bytelit == 0){
4712 aopPut(AOP(result),zero,offset);
4716 // faster than result <- left, anl result,right
4717 // and better if result is SFR
4718 if (AOP_TYPE(left) == AOP_ACC)
4719 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4721 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4722 emitcode("anl","a,%s",
4723 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4725 aopPut(AOP(result),"a",offset);
4731 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4732 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4733 freeAsmop(result,NULL,ic,TRUE);
4736 /*-----------------------------------------------------------------*/
4737 /* genOr - code for or */
4738 /*-----------------------------------------------------------------*/
4739 static void genOr (iCode *ic, iCode *ifx)
4741 operand *left, *right, *result;
4743 unsigned long lit = 0L;
4745 D(emitcode(";", "genOr "););
4750 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4751 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4752 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4756 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4758 AOP_TYPE(left), AOP_TYPE(right));
4759 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4761 AOP_SIZE(left), AOP_SIZE(right));
4764 /* if left is a literal & right is not then exchange them */
4765 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4766 AOP_NEEDSACC(left)) {
4767 operand *tmp = right ;
4772 /* if result = right then exchange them */
4773 if(sameRegs(AOP(result),AOP(right))){
4774 operand *tmp = right ;
4779 /* if right is bit then exchange them */
4780 if (AOP_TYPE(right) == AOP_CRY &&
4781 AOP_TYPE(left) != AOP_CRY){
4782 operand *tmp = right ;
4786 if(AOP_TYPE(right) == AOP_LIT)
4787 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4789 size = AOP_SIZE(result);
4793 if (AOP_TYPE(left) == AOP_CRY){
4794 if(AOP_TYPE(right) == AOP_LIT){
4795 // c = bit & literal;
4797 // lit != 0 => result = 1
4798 if(AOP_TYPE(result) == AOP_CRY){
4800 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4802 continueIfTrue(ifx);
4805 emitcode("setb","c");
4807 // lit == 0 => result = left
4808 if(size && sameRegs(AOP(result),AOP(left)))
4810 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4813 if (AOP_TYPE(right) == AOP_CRY){
4815 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4816 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4820 symbol *tlbl = newiTempLabel(NULL);
4821 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4822 emitcode("setb","c");
4823 emitcode("jb","%s,%05d$",
4824 AOP(left)->aopu.aop_dir,tlbl->key+100);
4826 emitcode("jnz","%05d$",tlbl->key+100);
4827 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4828 jmpTrueOrFalse(ifx, tlbl);
4832 emitcode("","%05d$:",tlbl->key+100);
4841 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4842 genIfxJump(ifx, "c");
4846 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4847 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4848 if((AOP_TYPE(right) == AOP_LIT) &&
4849 (AOP_TYPE(result) == AOP_CRY) &&
4850 (AOP_TYPE(left) != AOP_CRY)){
4854 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4856 continueIfTrue(ifx);
4859 // lit = 0, result = boolean(left)
4861 emitcode("setb","c");
4864 symbol *tlbl = newiTempLabel(NULL);
4865 emitcode("jnz","%05d$",tlbl->key+100);
4867 emitcode("","%05d$:",tlbl->key+100);
4869 genIfxJump (ifx,"a");
4877 /* if left is same as result */
4878 if(sameRegs(AOP(result),AOP(left))){
4879 for(;size--; offset++) {
4880 if(AOP_TYPE(right) == AOP_LIT){
4881 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4884 if (IS_AOP_PREG(left)) {
4885 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4886 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4887 aopPut(AOP(result),"a",offset);
4889 emitcode("orl","%s,%s",
4890 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4891 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4893 if (AOP_TYPE(left) == AOP_ACC)
4894 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4896 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4897 if (IS_AOP_PREG(left)) {
4898 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4899 aopPut(AOP(result),"a",offset);
4901 emitcode("orl","%s,a",
4902 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4907 // left & result in different registers
4908 if(AOP_TYPE(result) == AOP_CRY){
4910 // if(size), result in bit
4911 // if(!size && ifx), conditional oper: if(left | right)
4912 symbol *tlbl = newiTempLabel(NULL);
4913 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4915 emitcode("setb","c");
4917 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4918 emitcode("orl","a,%s",
4919 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4920 emitcode("jnz","%05d$",tlbl->key+100);
4925 emitcode("","%05d$:",tlbl->key+100);
4928 jmpTrueOrFalse(ifx, tlbl);
4929 } else for(;(size--);offset++){
4931 // result = left & right
4932 if(AOP_TYPE(right) == AOP_LIT){
4933 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4935 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4940 // faster than result <- left, anl result,right
4941 // and better if result is SFR
4942 if (AOP_TYPE(left) == AOP_ACC)
4943 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4945 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4946 emitcode("orl","a,%s",
4947 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4949 aopPut(AOP(result),"a",offset);
4954 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4955 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4956 freeAsmop(result,NULL,ic,TRUE);
4959 /*-----------------------------------------------------------------*/
4960 /* genXor - code for xclusive or */
4961 /*-----------------------------------------------------------------*/
4962 static void genXor (iCode *ic, iCode *ifx)
4964 operand *left, *right, *result;
4966 unsigned long lit = 0L;
4968 D(emitcode(";", "genXor "););
4973 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4974 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4975 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4979 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4981 AOP_TYPE(left), AOP_TYPE(right));
4982 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4984 AOP_SIZE(left), AOP_SIZE(right));
4987 /* if left is a literal & right is not ||
4988 if left needs acc & right does not */
4989 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4990 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4991 operand *tmp = right ;
4996 /* if result = right then exchange them */
4997 if(sameRegs(AOP(result),AOP(right))){
4998 operand *tmp = right ;
5003 /* if right is bit then exchange them */
5004 if (AOP_TYPE(right) == AOP_CRY &&
5005 AOP_TYPE(left) != AOP_CRY){
5006 operand *tmp = right ;
5010 if(AOP_TYPE(right) == AOP_LIT)
5011 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5013 size = AOP_SIZE(result);
5017 if (AOP_TYPE(left) == AOP_CRY){
5018 if(AOP_TYPE(right) == AOP_LIT){
5019 // c = bit & literal;
5021 // lit>>1 != 0 => result = 1
5022 if(AOP_TYPE(result) == AOP_CRY){
5024 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5026 continueIfTrue(ifx);
5029 emitcode("setb","c");
5033 // lit == 0, result = left
5034 if(size && sameRegs(AOP(result),AOP(left)))
5036 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5038 // lit == 1, result = not(left)
5039 if(size && sameRegs(AOP(result),AOP(left))){
5040 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5043 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5044 emitcode("cpl","c");
5051 symbol *tlbl = newiTempLabel(NULL);
5052 if (AOP_TYPE(right) == AOP_CRY){
5054 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5057 int sizer = AOP_SIZE(right);
5059 // if val>>1 != 0, result = 1
5060 emitcode("setb","c");
5062 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5064 // test the msb of the lsb
5065 emitcode("anl","a,#0xfe");
5066 emitcode("jnz","%05d$",tlbl->key+100);
5070 emitcode("rrc","a");
5072 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5073 emitcode("cpl","c");
5074 emitcode("","%05d$:",(tlbl->key+100));
5081 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5082 genIfxJump(ifx, "c");
5086 if(sameRegs(AOP(result),AOP(left))){
5087 /* if left is same as result */
5088 for(;size--; offset++) {
5089 if(AOP_TYPE(right) == AOP_LIT){
5090 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5093 if (IS_AOP_PREG(left)) {
5094 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5095 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5096 aopPut(AOP(result),"a",offset);
5098 emitcode("xrl","%s,%s",
5099 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5100 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5102 if (AOP_TYPE(left) == AOP_ACC)
5103 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5105 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5106 if (IS_AOP_PREG(left)) {
5107 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5108 aopPut(AOP(result),"a",offset);
5110 emitcode("xrl","%s,a",
5111 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5116 // left & result in different registers
5117 if(AOP_TYPE(result) == AOP_CRY){
5119 // if(size), result in bit
5120 // if(!size && ifx), conditional oper: if(left ^ right)
5121 symbol *tlbl = newiTempLabel(NULL);
5122 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5124 emitcode("setb","c");
5126 if((AOP_TYPE(right) == AOP_LIT) &&
5127 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5128 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5130 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5131 emitcode("xrl","a,%s",
5132 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5134 emitcode("jnz","%05d$",tlbl->key+100);
5139 emitcode("","%05d$:",tlbl->key+100);
5142 jmpTrueOrFalse(ifx, tlbl);
5143 } else for(;(size--);offset++){
5145 // result = left & right
5146 if(AOP_TYPE(right) == AOP_LIT){
5147 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
5149 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5154 // faster than result <- left, anl result,right
5155 // and better if result is SFR
5156 if (AOP_TYPE(left) == AOP_ACC)
5157 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5159 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5160 emitcode("xrl","a,%s",
5161 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5163 aopPut(AOP(result),"a",offset);
5168 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5169 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5170 freeAsmop(result,NULL,ic,TRUE);
5173 /*-----------------------------------------------------------------*/
5174 /* genInline - write the inline code out */
5175 /*-----------------------------------------------------------------*/
5176 static void genInline (iCode *ic)
5178 char buffer[MAX_INLINEASM];
5182 D(emitcode(";", "genInline "););
5184 _G.inLine += (!options.asmpeep);
5185 strcpy(buffer,IC_INLINE(ic));
5187 /* emit each line as a code */
5206 /* emitcode("",buffer); */
5207 _G.inLine -= (!options.asmpeep);
5210 /*-----------------------------------------------------------------*/
5211 /* genRRC - rotate right with carry */
5212 /*-----------------------------------------------------------------*/
5213 static void genRRC (iCode *ic)
5215 operand *left , *result ;
5216 int size, offset = 0;
5219 D(emitcode(";", "genRRC "););
5221 /* rotate right with carry */
5223 result=IC_RESULT(ic);
5224 aopOp (left,ic,FALSE, FALSE);
5225 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5227 /* move it to the result */
5228 size = AOP_SIZE(result);
5232 _startLazyDPSEvaluation();
5234 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5236 emitcode("rrc","a");
5237 if (AOP_SIZE(result) > 1)
5238 aopPut(AOP(result),"a",offset--);
5240 _endLazyDPSEvaluation();
5242 /* now we need to put the carry into the
5243 highest order byte of the result */
5244 if (AOP_SIZE(result) > 1) {
5245 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5248 emitcode("mov","acc.7,c");
5249 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5250 freeAsmop(left,NULL,ic,TRUE);
5251 freeAsmop(result,NULL,ic,TRUE);
5254 /*-----------------------------------------------------------------*/
5255 /* genRLC - generate code for rotate left with carry */
5256 /*-----------------------------------------------------------------*/
5257 static void genRLC (iCode *ic)
5259 operand *left , *result ;
5260 int size, offset = 0;
5263 D(emitcode(";", "genRLC "););
5265 /* rotate right with carry */
5267 result=IC_RESULT(ic);
5268 aopOp (left,ic,FALSE, FALSE);
5269 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5271 /* move it to the result */
5272 size = AOP_SIZE(result);
5275 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5277 emitcode("add","a,acc");
5278 if (AOP_SIZE(result) > 1)
5280 aopPut(AOP(result),"a",offset++);
5283 _startLazyDPSEvaluation();
5285 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5287 emitcode("rlc","a");
5288 if (AOP_SIZE(result) > 1)
5289 aopPut(AOP(result),"a",offset++);
5291 _endLazyDPSEvaluation();
5293 /* now we need to put the carry into the
5294 highest order byte of the result */
5295 if (AOP_SIZE(result) > 1) {
5296 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5299 emitcode("mov","acc.0,c");
5300 aopPut(AOP(result),"a",0);
5301 freeAsmop(left,NULL,ic,TRUE);
5302 freeAsmop(result,NULL,ic,TRUE);
5305 /*-----------------------------------------------------------------*/
5306 /* genGetHbit - generates code get highest order bit */
5307 /*-----------------------------------------------------------------*/
5308 static void genGetHbit (iCode *ic)
5310 operand *left, *result;
5312 result=IC_RESULT(ic);
5313 aopOp (left,ic,FALSE, FALSE);
5314 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5316 D(emitcode(";", "genGetHbit "););
5318 /* get the highest order byte into a */
5319 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5320 if(AOP_TYPE(result) == AOP_CRY){
5321 emitcode("rlc","a");
5326 emitcode("anl","a,#0x01");
5331 freeAsmop(left,NULL,ic,TRUE);
5332 freeAsmop(result,NULL,ic,TRUE);
5335 /*-----------------------------------------------------------------*/
5336 /* AccRol - rotate left accumulator by known count */
5337 /*-----------------------------------------------------------------*/
5338 static void AccRol (int shCount)
5340 shCount &= 0x0007; // shCount : 0..7
5352 emitcode("swap","a");
5356 emitcode("swap","a");
5359 emitcode("swap","a");
5372 /*-----------------------------------------------------------------*/
5373 /* AccLsh - left shift accumulator by known count */
5374 /*-----------------------------------------------------------------*/
5375 static void AccLsh (int shCount)
5379 emitcode("add","a,acc");
5382 emitcode("add","a,acc");
5383 emitcode("add","a,acc");
5385 /* rotate left accumulator */
5387 /* and kill the lower order bits */
5388 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5393 /*-----------------------------------------------------------------*/
5394 /* AccRsh - right shift accumulator by known count */
5395 /*-----------------------------------------------------------------*/
5396 static void AccRsh (int shCount)
5401 emitcode("rrc","a");
5403 /* rotate right accumulator */
5404 AccRol(8 - shCount);
5405 /* and kill the higher order bits */
5406 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);
5445 /*-----------------------------------------------------------------*/
5446 /* shiftR1Left2Result - shift right one byte from left to result */
5447 /*-----------------------------------------------------------------*/
5448 static void shiftR1Left2Result (operand *left, int offl,
5449 operand *result, int offr,
5450 int shCount, int sign)
5452 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5453 /* shift right accumulator */
5458 aopPut(AOP(result),"a",offr);
5464 /*-----------------------------------------------------------------*/
5465 /* shiftL1Left2Result - shift left one byte from left to result */
5466 /*-----------------------------------------------------------------*/
5467 static void shiftL1Left2Result (operand *left, int offl,
5468 operand *result, int offr, int shCount)
5471 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5473 /* shift left accumulator */
5475 aopPut(AOP(result),"a",offr);
5481 /*-----------------------------------------------------------------*/
5482 /* movLeft2Result - move byte from left to result */
5483 /*-----------------------------------------------------------------*/
5484 static void movLeft2Result (operand *left, int offl,
5485 operand *result, int offr, int sign)
5488 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5489 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5491 if (*l == '@' && (IS_AOP_PREG(result))) {
5492 emitcode("mov","a,%s",l);
5493 aopPut(AOP(result),"a",offr);
5496 aopPut(AOP(result),l,offr);
5498 /* MSB sign in acc.7 ! */
5499 if(getDataSize(left) == offl+1){
5500 emitcode("mov","a,%s",l);
5501 aopPut(AOP(result),"a",offr);
5511 /*-----------------------------------------------------------------*/
5512 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5513 /*-----------------------------------------------------------------*/
5514 static void AccAXRrl1 (char *x)
5516 emitcode("rrc","a");
5517 emitcode("xch","a,%s", x);
5518 emitcode("rrc","a");
5519 emitcode("xch","a,%s", x);
5525 /*-----------------------------------------------------------------*/
5526 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5527 /*-----------------------------------------------------------------*/
5528 static void AccAXLrl1 (char *x)
5530 emitcode("xch","a,%s",x);
5531 emitcode("rlc","a");
5532 emitcode("xch","a,%s",x);
5533 emitcode("rlc","a");
5539 /*-----------------------------------------------------------------*/
5540 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5541 /*-----------------------------------------------------------------*/
5542 static void AccAXLsh1 (char *x)
5544 emitcode("xch","a,%s",x);
5545 emitcode("add","a,acc");
5546 emitcode("xch","a,%s",x);
5547 emitcode("rlc","a");
5553 /*-----------------------------------------------------------------*/
5554 /* AccAXLsh - left shift a:x by known count (0..7) */
5555 /*-----------------------------------------------------------------*/
5556 static void AccAXLsh (char *x, int shCount)
5570 case 5 : // AAAAABBB:CCCCCDDD
5571 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5572 emitcode("anl","a,#0x%02x",
5573 SLMask[shCount]); // BBB00000:CCCCCDDD
5574 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5575 AccRol(shCount); // DDDCCCCC:BBB00000
5576 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5577 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5578 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5579 emitcode("anl","a,#0x%02x",
5580 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5581 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5582 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5584 case 6 : // AAAAAABB:CCCCCCDD
5585 emitcode("anl","a,#0x%02x",
5586 SRMask[shCount]); // 000000BB:CCCCCCDD
5587 emitcode("mov","c,acc.0"); // c = B
5588 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5589 AccAXRrl1(x); // BCCCCCCD:D000000B
5590 AccAXRrl1(x); // BBCCCCCC:DD000000
5592 case 7 : // a:x <<= 7
5593 emitcode("anl","a,#0x%02x",
5594 SRMask[shCount]); // 0000000B:CCCCCCCD
5595 emitcode("mov","c,acc.0"); // c = B
5596 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5597 AccAXRrl1(x); // BCCCCCCC:D0000000
5607 /*-----------------------------------------------------------------*/
5608 /* AccAXRsh - right shift a:x known count (0..7) */
5609 /*-----------------------------------------------------------------*/
5610 static void AccAXRsh (char *x, int shCount)
5617 AccAXRrl1(x); // 0->a:x
5621 AccAXRrl1(x); // 0->a:x
5623 AccAXRrl1(x); // 0->a:x
5627 case 5 : // AAAAABBB:CCCCCDDD = a:x
5628 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5629 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5630 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5631 emitcode("anl","a,#0x%02x",
5632 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5633 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5634 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5635 emitcode("anl","a,#0x%02x",
5636 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5637 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5638 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5639 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5641 case 6 : // AABBBBBB:CCDDDDDD
5642 emitcode("mov","c,acc.7");
5643 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5644 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5645 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5646 emitcode("anl","a,#0x%02x",
5647 SRMask[shCount]); // 000000AA:BBBBBBCC
5649 case 7 : // ABBBBBBB:CDDDDDDD
5650 emitcode("mov","c,acc.7"); // c = A
5651 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5652 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5653 emitcode("anl","a,#0x%02x",
5654 SRMask[shCount]); // 0000000A:BBBBBBBC
5664 /*-----------------------------------------------------------------*/
5665 /* AccAXRshS - right shift signed a:x known count (0..7) */
5666 /*-----------------------------------------------------------------*/
5667 static void AccAXRshS (char *x, int shCount)
5674 emitcode("mov","c,acc.7");
5675 AccAXRrl1(x); // s->a:x
5678 emitcode("mov","c,acc.7");
5679 AccAXRrl1(x); // s->a:x
5680 emitcode("mov","c,acc.7");
5681 AccAXRrl1(x); // s->a:x
5685 case 5 : // AAAAABBB:CCCCCDDD = a:x
5686 tlbl = newiTempLabel(NULL);
5687 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5688 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5689 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5690 emitcode("anl","a,#0x%02x",
5691 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5692 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5693 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5694 emitcode("anl","a,#0x%02x",
5695 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5696 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5697 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5698 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5699 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5700 emitcode("orl","a,#0x%02x",
5701 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5702 emitcode("","%05d$:",tlbl->key+100);
5703 break; // SSSSAAAA:BBBCCCCC
5704 case 6 : // AABBBBBB:CCDDDDDD
5705 tlbl = newiTempLabel(NULL);
5706 emitcode("mov","c,acc.7");
5707 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5708 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5709 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5710 emitcode("anl","a,#0x%02x",
5711 SRMask[shCount]); // 000000AA:BBBBBBCC
5712 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5713 emitcode("orl","a,#0x%02x",
5714 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5715 emitcode("","%05d$:",tlbl->key+100);
5717 case 7 : // ABBBBBBB:CDDDDDDD
5718 tlbl = newiTempLabel(NULL);
5719 emitcode("mov","c,acc.7"); // c = A
5720 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5721 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5722 emitcode("anl","a,#0x%02x",
5723 SRMask[shCount]); // 0000000A:BBBBBBBC
5724 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5725 emitcode("orl","a,#0x%02x",
5726 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5727 emitcode("","%05d$:",tlbl->key+100);
5737 /*-----------------------------------------------------------------*/
5738 /* shiftL2Left2Result - shift left two bytes from left to result */
5739 /*-----------------------------------------------------------------*/
5740 static void shiftL2Left2Result (operand *left, int offl,
5741 operand *result, int offr, int shCount)
5743 if(sameRegs(AOP(result), AOP(left)) &&
5744 ((offl + MSB16) == offr)){
5745 /* don't crash result[offr] */
5746 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5747 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5749 movLeft2Result(left,offl, result, offr, 0);
5750 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5752 /* ax << shCount (x = lsb(result))*/
5753 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5754 aopPut(AOP(result),"a",offr+MSB16);
5760 /*-----------------------------------------------------------------*/
5761 /* shiftR2Left2Result - shift right two bytes from left to result */
5762 /*-----------------------------------------------------------------*/
5763 static void shiftR2Left2Result (operand *left, int offl,
5764 operand *result, int offr,
5765 int shCount, int sign)
5767 if(sameRegs(AOP(result), AOP(left)) &&
5768 ((offl + MSB16) == offr)){
5769 /* don't crash result[offr] */
5770 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5771 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5773 movLeft2Result(left,offl, result, offr, 0);
5774 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5776 /* a:x >> shCount (x = lsb(result))*/
5778 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5780 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5781 if(getDataSize(result) > 1)
5782 aopPut(AOP(result),"a",offr+MSB16);
5788 /*-----------------------------------------------------------------*/
5789 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5790 /*-----------------------------------------------------------------*/
5791 static void shiftLLeftOrResult (operand *left, int offl,
5792 operand *result, int offr, int shCount)
5794 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5795 /* shift left accumulator */
5797 /* or with result */
5798 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5799 /* back to result */
5800 aopPut(AOP(result),"a",offr);
5806 /*-----------------------------------------------------------------*/
5807 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5808 /*-----------------------------------------------------------------*/
5809 static void shiftRLeftOrResult (operand *left, int offl,
5810 operand *result, int offr, int shCount)
5812 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5813 /* shift right accumulator */
5815 /* or with result */
5816 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5817 /* back to result */
5818 aopPut(AOP(result),"a",offr);
5824 /*-----------------------------------------------------------------*/
5825 /* genlshOne - left shift a one byte quantity by known count */
5826 /*-----------------------------------------------------------------*/
5827 static void genlshOne (operand *result, operand *left, int shCount)
5829 D(emitcode(";", "genlshOne "););
5830 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5836 /*-----------------------------------------------------------------*/
5837 /* genlshTwo - left shift two bytes by known amount != 0 */
5838 /*-----------------------------------------------------------------*/
5839 static void genlshTwo (operand *result,operand *left, int shCount)
5843 D(emitcode(";", "genlshTwo "););
5845 size = getDataSize(result);
5847 /* if shCount >= 8 */
5853 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5855 movLeft2Result(left, LSB, result, MSB16, 0);
5857 aopPut(AOP(result),zero,LSB);
5860 /* 1 <= shCount <= 7 */
5863 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5865 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5872 /*-----------------------------------------------------------------*/
5873 /* shiftLLong - shift left one long from left to result */
5874 /* offl = LSB or MSB16 */
5875 /*-----------------------------------------------------------------*/
5876 static void shiftLLong (operand *left, operand *result, int offr )
5879 int size = AOP_SIZE(result);
5881 if(size >= LSB+offr){
5882 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5884 emitcode("add","a,acc");
5885 if (sameRegs(AOP(left),AOP(result)) &&
5886 size >= MSB16+offr && offr != LSB )
5887 emitcode("xch","a,%s",
5888 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5890 aopPut(AOP(result),"a",LSB+offr);
5893 if(size >= MSB16+offr){
5894 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5895 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5898 emitcode("rlc","a");
5899 if (sameRegs(AOP(left),AOP(result)) &&
5900 size >= MSB24+offr && offr != LSB)
5901 emitcode("xch","a,%s",
5902 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5904 aopPut(AOP(result),"a",MSB16+offr);
5907 if(size >= MSB24+offr){
5908 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5909 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5912 emitcode("rlc","a");
5913 if (sameRegs(AOP(left),AOP(result)) &&
5914 size >= MSB32+offr && offr != LSB )
5915 emitcode("xch","a,%s",
5916 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5918 aopPut(AOP(result),"a",MSB24+offr);
5921 if(size > MSB32+offr){
5922 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5923 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5926 emitcode("rlc","a");
5927 aopPut(AOP(result),"a",MSB32+offr);
5930 aopPut(AOP(result),zero,LSB);
5936 /*-----------------------------------------------------------------*/
5937 /* genlshFour - shift four byte by a known amount != 0 */
5938 /*-----------------------------------------------------------------*/
5939 static void genlshFour (operand *result, operand *left, int shCount)
5943 D(emitcode(";", "genlshFour "););
5945 size = AOP_SIZE(result);
5947 /* if shifting more that 3 bytes */
5948 if (shCount >= 24 ) {
5951 /* lowest order of left goes to the highest
5952 order of the destination */
5953 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5955 movLeft2Result(left, LSB, result, MSB32, 0);
5956 aopPut(AOP(result),zero,LSB);
5957 aopPut(AOP(result),zero,MSB16);
5958 aopPut(AOP(result),zero,MSB32);
5962 /* more than two bytes */
5963 else if ( shCount >= 16 ) {
5964 /* lower order two bytes goes to higher order two bytes */
5966 /* if some more remaining */
5968 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5970 movLeft2Result(left, MSB16, result, MSB32, 0);
5971 movLeft2Result(left, LSB, result, MSB24, 0);
5973 aopPut(AOP(result),zero,MSB16);
5974 aopPut(AOP(result),zero,LSB);
5978 /* if more than 1 byte */
5979 else if ( shCount >= 8 ) {
5980 /* lower order three bytes goes to higher order three bytes */
5984 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5986 movLeft2Result(left, LSB, result, MSB16, 0);
5988 else{ /* size = 4 */
5990 movLeft2Result(left, MSB24, result, MSB32, 0);
5991 movLeft2Result(left, MSB16, result, MSB24, 0);
5992 movLeft2Result(left, LSB, result, MSB16, 0);
5993 aopPut(AOP(result),zero,LSB);
5995 else if(shCount == 1)
5996 shiftLLong(left, result, MSB16);
5998 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5999 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6000 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6001 aopPut(AOP(result),zero,LSB);
6006 /* 1 <= shCount <= 7 */
6007 else if(shCount <= 2){
6008 shiftLLong(left, result, LSB);
6010 shiftLLong(result, result, LSB);
6012 /* 3 <= shCount <= 7, optimize */
6014 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6015 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6016 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6023 /*-----------------------------------------------------------------*/
6024 /* genLeftShiftLiteral - left shifting by known count */
6025 /*-----------------------------------------------------------------*/
6026 static void genLeftShiftLiteral (operand *left,
6031 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6034 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
6036 freeAsmop(right,NULL,ic,TRUE);
6038 aopOp(left,ic,FALSE, FALSE);
6039 aopOp(result,ic,FALSE, TRUE);
6041 size = getSize(operandType(result));
6044 emitcode("; shift left ","result %d, left %d",size,
6048 /* I suppose that the left size >= result size */
6051 movLeft2Result(left, size, result, size, 0);
6055 else if(shCount >= (size * 8))
6057 aopPut(AOP(result),zero,size);
6061 genlshOne (result,left,shCount);
6065 case 3: /* bug: this is for generic pointers, I bet. */
6066 genlshTwo (result,left,shCount);
6070 genlshFour (result,left,shCount);
6074 freeAsmop(left,NULL,ic,TRUE);
6075 freeAsmop(result,NULL,ic,TRUE);
6079 /*-----------------------------------------------------------------*/
6080 /* genLeftShift - generates code for left shifting */
6081 /*-----------------------------------------------------------------*/
6082 static void genLeftShift (iCode *ic)
6084 operand *left,*right, *result;
6087 symbol *tlbl , *tlbl1;
6089 D(emitcode(";", "genLeftShift "););
6091 right = IC_RIGHT(ic);
6093 result = IC_RESULT(ic);
6095 aopOp(right,ic,FALSE, FALSE);
6098 /* if the shift count is known then do it
6099 as efficiently as possible */
6100 if (AOP_TYPE(right) == AOP_LIT) {
6101 genLeftShiftLiteral (left,right,result,ic);
6106 /* shift count is unknown then we have to form
6107 a loop get the loop count in B : Note: we take
6108 only the lower order byte since shifting
6109 more that 32 bits make no sense anyway, ( the
6110 largest size of an object can be only 32 bits ) */
6112 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6113 emitcode("inc","b");
6114 freeAsmop (right,NULL,ic,TRUE);
6115 aopOp(left,ic,FALSE, FALSE);
6116 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6118 /* now move the left to the result if they are not the
6120 if (!sameRegs(AOP(left),AOP(result)) &&
6121 AOP_SIZE(result) > 1) {
6123 size = AOP_SIZE(result);
6125 _startLazyDPSEvaluation();
6127 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6128 if (*l == '@' && (IS_AOP_PREG(result))) {
6130 emitcode("mov","a,%s",l);
6131 aopPut(AOP(result),"a",offset);
6133 aopPut(AOP(result),l,offset);
6136 _endLazyDPSEvaluation();
6139 tlbl = newiTempLabel(NULL);
6140 size = AOP_SIZE(result);
6142 tlbl1 = newiTempLabel(NULL);
6144 /* if it is only one byte then */
6146 symbol *tlbl1 = newiTempLabel(NULL);
6148 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6150 emitcode("sjmp","%05d$",tlbl1->key+100);
6151 emitcode("","%05d$:",tlbl->key+100);
6152 emitcode("add","a,acc");
6153 emitcode("","%05d$:",tlbl1->key+100);
6154 emitcode("djnz","b,%05d$",tlbl->key+100);
6155 aopPut(AOP(result),"a",0);
6159 reAdjustPreg(AOP(result));
6161 emitcode("sjmp","%05d$",tlbl1->key+100);
6162 emitcode("","%05d$:",tlbl->key+100);
6163 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6165 emitcode("add","a,acc");
6166 aopPut(AOP(result),"a",offset++);
6167 _startLazyDPSEvaluation();
6169 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6171 emitcode("rlc","a");
6172 aopPut(AOP(result),"a",offset++);
6174 _endLazyDPSEvaluation();
6175 reAdjustPreg(AOP(result));
6177 emitcode("","%05d$:",tlbl1->key+100);
6178 emitcode("djnz","b,%05d$",tlbl->key+100);
6180 freeAsmop(left,NULL,ic,TRUE);
6181 freeAsmop(result,NULL,ic,TRUE);
6186 /*-----------------------------------------------------------------*/
6187 /* genrshOne - right shift a one byte quantity by known count */
6188 /*-----------------------------------------------------------------*/
6189 static void genrshOne (operand *result, operand *left,
6190 int shCount, int sign)
6192 D(emitcode(";", "genrshOne"););
6193 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6199 /*-----------------------------------------------------------------*/
6200 /* genrshTwo - right shift two bytes by known amount != 0 */
6201 /*-----------------------------------------------------------------*/
6202 static void genrshTwo (operand *result,operand *left,
6203 int shCount, int sign)
6205 D(emitcode(";", "genrshTwo"););
6207 /* if shCount >= 8 */
6211 shiftR1Left2Result(left, MSB16, result, LSB,
6214 movLeft2Result(left, MSB16, result, LSB, sign);
6215 addSign(result, MSB16, sign);
6218 /* 1 <= shCount <= 7 */
6220 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6226 /*-----------------------------------------------------------------*/
6227 /* shiftRLong - shift right one long from left to result */
6228 /* offl = LSB or MSB16 */
6229 /*-----------------------------------------------------------------*/
6230 static void shiftRLong (operand *left, int offl,
6231 operand *result, int sign)
6234 emitcode("clr","c");
6235 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6237 emitcode("mov","c,acc.7");
6238 emitcode("rrc","a");
6239 aopPut(AOP(result),"a",MSB32-offl);
6241 /* add sign of "a" */
6242 addSign(result, MSB32, sign);
6244 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6245 emitcode("rrc","a");
6246 aopPut(AOP(result),"a",MSB24-offl);
6248 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6249 emitcode("rrc","a");
6250 aopPut(AOP(result),"a",MSB16-offl);
6253 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6254 emitcode("rrc","a");
6255 aopPut(AOP(result),"a",LSB);
6262 /*-----------------------------------------------------------------*/
6263 /* genrshFour - shift four byte by a known amount != 0 */
6264 /*-----------------------------------------------------------------*/
6265 static void genrshFour (operand *result, operand *left,
6266 int shCount, int sign)
6268 D(emitcode(";", "genrshFour"););
6270 /* if shifting more that 3 bytes */
6271 if(shCount >= 24 ) {
6274 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6276 movLeft2Result(left, MSB32, result, LSB, sign);
6277 addSign(result, MSB16, sign);
6279 else if(shCount >= 16){
6282 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6284 movLeft2Result(left, MSB24, result, LSB, 0);
6285 movLeft2Result(left, MSB32, result, MSB16, sign);
6287 addSign(result, MSB24, sign);
6289 else if(shCount >= 8){
6292 shiftRLong(left, MSB16, result, sign);
6293 else if(shCount == 0){
6294 movLeft2Result(left, MSB16, result, LSB, 0);
6295 movLeft2Result(left, MSB24, result, MSB16, 0);
6296 movLeft2Result(left, MSB32, result, MSB24, sign);
6297 addSign(result, MSB32, sign);
6300 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6301 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6302 /* the last shift is signed */
6303 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6304 addSign(result, MSB32, sign);
6307 else{ /* 1 <= shCount <= 7 */
6309 shiftRLong(left, LSB, result, sign);
6311 shiftRLong(result, LSB, result, sign);
6314 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6315 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6316 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6324 /*-----------------------------------------------------------------*/
6325 /* genRightShiftLiteral - right shifting by known count */
6326 /*-----------------------------------------------------------------*/
6327 static void genRightShiftLiteral (operand *left,
6333 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6336 D(emitcode(";", "genRightShiftLiteral"););
6338 freeAsmop(right,NULL,ic,TRUE);
6340 aopOp(left,ic,FALSE, FALSE);
6341 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6344 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6348 size = getDataSize(left);
6349 /* test the LEFT size !!! */
6351 /* I suppose that the left size >= result size */
6353 size = getDataSize(result);
6355 movLeft2Result(left, size, result, size, 0);
6358 else if(shCount >= (size * 8)){
6360 /* get sign in acc.7 */
6361 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6362 addSign(result, LSB, sign);
6366 genrshOne (result,left,shCount,sign);
6370 genrshTwo (result,left,shCount,sign);
6374 genrshFour (result,left,shCount,sign);
6380 freeAsmop(left,NULL,ic,TRUE);
6381 freeAsmop(result,NULL,ic,TRUE);
6386 /*-----------------------------------------------------------------*/
6387 /* genSignedRightShift - right shift of signed number */
6388 /*-----------------------------------------------------------------*/
6389 static void genSignedRightShift (iCode *ic)
6391 operand *right, *left, *result;
6394 symbol *tlbl, *tlbl1 ;
6396 D(emitcode(";", "genSignedRightShift "););
6398 /* we do it the hard way put the shift count in b
6399 and loop thru preserving the sign */
6401 right = IC_RIGHT(ic);
6403 result = IC_RESULT(ic);
6405 aopOp(right,ic,FALSE, FALSE);
6408 if ( AOP_TYPE(right) == AOP_LIT) {
6409 genRightShiftLiteral (left,right,result,ic,1);
6413 /* shift count is unknown then we have to form
6414 a loop get the loop count in B : Note: we take
6415 only the lower order byte since shifting
6416 more that 32 bits make no sense anyway, ( the
6417 largest size of an object can be only 32 bits ) */
6419 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6420 emitcode("inc","b");
6421 freeAsmop (right,NULL,ic,TRUE);
6422 aopOp(left,ic,FALSE, FALSE);
6423 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6425 /* now move the left to the result if they are not the
6427 if (!sameRegs(AOP(left),AOP(result)) &&
6428 AOP_SIZE(result) > 1) {
6430 size = AOP_SIZE(result);
6432 _startLazyDPSEvaluation();
6434 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6435 if (*l == '@' && IS_AOP_PREG(result)) {
6437 emitcode("mov","a,%s",l);
6438 aopPut(AOP(result),"a",offset);
6440 aopPut(AOP(result),l,offset);
6443 _endLazyDPSEvaluation();
6446 /* mov the highest order bit to OVR */
6447 tlbl = newiTempLabel(NULL);
6448 tlbl1= newiTempLabel(NULL);
6450 size = AOP_SIZE(result);
6452 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6453 emitcode("rlc","a");
6454 emitcode("mov","ov,c");
6455 /* if it is only one byte then */
6457 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6459 emitcode("sjmp","%05d$",tlbl1->key+100);
6460 emitcode("","%05d$:",tlbl->key+100);
6461 emitcode("mov","c,ov");
6462 emitcode("rrc","a");
6463 emitcode("","%05d$:",tlbl1->key+100);
6464 emitcode("djnz","b,%05d$",tlbl->key+100);
6465 aopPut(AOP(result),"a",0);
6469 reAdjustPreg(AOP(result));
6470 emitcode("sjmp","%05d$",tlbl1->key+100);
6471 emitcode("","%05d$:",tlbl->key+100);
6472 emitcode("mov","c,ov");
6473 _startLazyDPSEvaluation();
6475 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6477 emitcode("rrc","a");
6478 aopPut(AOP(result),"a",offset--);
6480 _endLazyDPSEvaluation();
6481 reAdjustPreg(AOP(result));
6482 emitcode("","%05d$:",tlbl1->key+100);
6483 emitcode("djnz","b,%05d$",tlbl->key+100);
6486 freeAsmop(left,NULL,ic,TRUE);
6487 freeAsmop(result,NULL,ic,TRUE);
6490 /*-----------------------------------------------------------------*/
6491 /* genRightShift - generate code for right shifting */
6492 /*-----------------------------------------------------------------*/
6493 static void genRightShift (iCode *ic)
6495 operand *right, *left, *result;
6499 symbol *tlbl, *tlbl1 ;
6501 D(emitcode(";", "genRightShift "););
6503 /* if signed then we do it the hard way preserve the
6504 sign bit moving it inwards */
6505 retype = getSpec(operandType(IC_RESULT(ic)));
6507 if (!SPEC_USIGN(retype)) {
6508 genSignedRightShift (ic);
6512 /* signed & unsigned types are treated the same : i.e. the
6513 signed is NOT propagated inwards : quoting from the
6514 ANSI - standard : "for E1 >> E2, is equivalent to division
6515 by 2**E2 if unsigned or if it has a non-negative value,
6516 otherwise the result is implementation defined ", MY definition
6517 is that the sign does not get propagated */
6519 right = IC_RIGHT(ic);
6521 result = IC_RESULT(ic);
6523 aopOp(right,ic,FALSE, FALSE);
6526 /* if the shift count is known then do it
6527 as efficiently as possible */
6528 if (AOP_TYPE(right) == AOP_LIT) {
6529 genRightShiftLiteral (left,right,result,ic, 0);
6534 /* shift count is unknown then we have to form
6535 a loop get the loop count in B : Note: we take
6536 only the lower order byte since shifting
6537 more that 32 bits make no sense anyway, ( the
6538 largest size of an object can be only 32 bits ) */
6540 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6541 emitcode("inc","b");
6542 freeAsmop (right,NULL,ic,TRUE);
6543 aopOp(left,ic,FALSE, FALSE);
6544 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6546 /* now move the left to the result if they are not the
6548 if (!sameRegs(AOP(left),AOP(result)) &&
6549 AOP_SIZE(result) > 1) {
6551 size = AOP_SIZE(result);
6553 _startLazyDPSEvaluation();
6555 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6556 if (*l == '@' && IS_AOP_PREG(result)) {
6558 emitcode("mov","a,%s",l);
6559 aopPut(AOP(result),"a",offset);
6561 aopPut(AOP(result),l,offset);
6564 _endLazyDPSEvaluation();
6567 tlbl = newiTempLabel(NULL);
6568 tlbl1= newiTempLabel(NULL);
6569 size = AOP_SIZE(result);
6572 /* if it is only one byte then */
6574 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6576 emitcode("sjmp","%05d$",tlbl1->key+100);
6577 emitcode("","%05d$:",tlbl->key+100);
6579 emitcode("rrc","a");
6580 emitcode("","%05d$:",tlbl1->key+100);
6581 emitcode("djnz","b,%05d$",tlbl->key+100);
6582 aopPut(AOP(result),"a",0);
6586 reAdjustPreg(AOP(result));
6587 emitcode("sjmp","%05d$",tlbl1->key+100);
6588 emitcode("","%05d$:",tlbl->key+100);
6590 _startLazyDPSEvaluation();
6592 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6594 emitcode("rrc","a");
6595 aopPut(AOP(result),"a",offset--);
6597 _endLazyDPSEvaluation();
6598 reAdjustPreg(AOP(result));
6600 emitcode("","%05d$:",tlbl1->key+100);
6601 emitcode("djnz","b,%05d$",tlbl->key+100);
6604 freeAsmop(left,NULL,ic,TRUE);
6605 freeAsmop(result,NULL,ic,TRUE);
6608 /*-----------------------------------------------------------------*/
6609 /* genUnpackBits - generates code for unpacking bits */
6610 /*-----------------------------------------------------------------*/
6611 static void genUnpackBits (operand *result, char *rname, int ptype)
6618 D(emitcode(";", "genUnpackBits "););
6620 etype = getSpec(operandType(result));
6622 /* read the first byte */
6627 emitcode("mov","a,@%s",rname);
6631 emitcode("movx","a,@%s",rname);
6635 emitcode("movx","a,@dptr");
6639 emitcode("clr","a");
6640 emitcode("movc","a","@a+dptr");
6644 emitcode("lcall","__gptrget");
6648 /* if we have bitdisplacement then it fits */
6649 /* into this byte completely or if length is */
6650 /* less than a byte */
6651 if ((shCnt = SPEC_BSTR(etype)) ||
6652 (SPEC_BLEN(etype) <= 8)) {
6654 /* shift right acc */
6657 emitcode("anl","a,#0x%02x",
6658 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6659 aopPut(AOP(result),"a",offset);
6663 /* bit field did not fit in a byte */
6664 rlen = SPEC_BLEN(etype) - 8;
6665 aopPut(AOP(result),"a",offset++);
6672 emitcode("inc","%s",rname);
6673 emitcode("mov","a,@%s",rname);
6677 emitcode("inc","%s",rname);
6678 emitcode("movx","a,@%s",rname);
6682 emitcode("inc","dptr");
6683 emitcode("movx","a,@dptr");
6687 emitcode("clr","a");
6688 emitcode("inc","dptr");
6689 emitcode("movc","a","@a+dptr");
6693 emitcode("inc","dptr");
6694 emitcode("lcall","__gptrget");
6699 /* if we are done */
6703 aopPut(AOP(result),"a",offset++);
6708 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6709 aopPut(AOP(result),"a",offset);
6716 /*-----------------------------------------------------------------*/
6717 /* genDataPointerGet - generates code when ptr offset is known */
6718 /*-----------------------------------------------------------------*/
6719 static void genDataPointerGet (operand *left,
6725 int size , offset = 0;
6726 aopOp(result,ic,TRUE, FALSE);
6728 /* get the string representation of the name */
6729 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6730 size = AOP_SIZE(result);
6731 _startLazyDPSEvaluation();
6734 sprintf(buffer,"(%s + %d)",l+1,offset);
6736 sprintf(buffer,"%s",l+1);
6737 aopPut(AOP(result),buffer,offset++);
6739 _endLazyDPSEvaluation();
6741 freeAsmop(left,NULL,ic,TRUE);
6742 freeAsmop(result,NULL,ic,TRUE);
6745 /*-----------------------------------------------------------------*/
6746 /* genNearPointerGet - emitcode for near pointer fetch */
6747 /*-----------------------------------------------------------------*/
6748 static void genNearPointerGet (operand *left,
6755 link *rtype, *retype;
6756 link *ltype = operandType(left);
6759 rtype = operandType(result);
6760 retype= getSpec(rtype);
6762 aopOp(left,ic,FALSE, FALSE);
6764 /* if left is rematerialisable and
6765 result is not bit variable type and
6766 the left is pointer to data space i.e
6767 lower 128 bytes of space */
6768 if (AOP_TYPE(left) == AOP_IMMD &&
6769 !IS_BITVAR(retype) &&
6770 DCL_TYPE(ltype) == POINTER) {
6771 genDataPointerGet (left,result,ic);
6775 /* if the value is already in a pointer register
6776 then don't need anything more */
6777 if (!AOP_INPREG(AOP(left))) {
6778 /* otherwise get a free pointer register */
6780 preg = getFreePtr(ic,&aop,FALSE);
6781 emitcode("mov","%s,%s",
6783 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6784 rname = preg->name ;
6786 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6788 freeAsmop(left,NULL,ic,TRUE);
6789 aopOp (result,ic,FALSE, FALSE);
6791 /* if bitfield then unpack the bits */
6792 if (IS_BITVAR(retype))
6793 genUnpackBits (result,rname,POINTER);
6795 /* we have can just get the values */
6796 int size = AOP_SIZE(result);
6800 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6802 emitcode("mov","a,@%s",rname);
6803 aopPut(AOP(result),"a",offset);
6805 sprintf(buffer,"@%s",rname);
6806 aopPut(AOP(result),buffer,offset);
6810 emitcode("inc","%s",rname);
6814 /* now some housekeeping stuff */
6816 /* we had to allocate for this iCode */
6817 freeAsmop(NULL,aop,ic,TRUE);
6819 /* we did not allocate which means left
6820 already in a pointer register, then
6821 if size > 0 && this could be used again
6822 we have to point it back to where it
6824 if (AOP_SIZE(result) > 1 &&
6825 !OP_SYMBOL(left)->remat &&
6826 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6828 int size = AOP_SIZE(result) - 1;
6830 emitcode("dec","%s",rname);
6835 freeAsmop(result,NULL,ic,TRUE);
6839 /*-----------------------------------------------------------------*/
6840 /* genPagedPointerGet - emitcode for paged pointer fetch */
6841 /*-----------------------------------------------------------------*/
6842 static void genPagedPointerGet (operand *left,
6849 link *rtype, *retype;
6851 rtype = operandType(result);
6852 retype= getSpec(rtype);
6854 aopOp(left,ic,FALSE, FALSE);
6856 /* if the value is already in a pointer register
6857 then don't need anything more */
6858 if (!AOP_INPREG(AOP(left))) {
6859 /* otherwise get a free pointer register */
6861 preg = getFreePtr(ic,&aop,FALSE);
6862 emitcode("mov","%s,%s",
6864 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6865 rname = preg->name ;
6867 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6869 freeAsmop(left,NULL,ic,TRUE);
6870 aopOp (result,ic,FALSE, FALSE);
6872 /* if bitfield then unpack the bits */
6873 if (IS_BITVAR(retype))
6874 genUnpackBits (result,rname,PPOINTER);
6876 /* we have can just get the values */
6877 int size = AOP_SIZE(result);
6882 emitcode("movx","a,@%s",rname);
6883 aopPut(AOP(result),"a",offset);
6888 emitcode("inc","%s",rname);
6892 /* now some housekeeping stuff */
6894 /* we had to allocate for this iCode */
6895 freeAsmop(NULL,aop,ic,TRUE);
6897 /* we did not allocate which means left
6898 already in a pointer register, then
6899 if size > 0 && this could be used again
6900 we have to point it back to where it
6902 if (AOP_SIZE(result) > 1 &&
6903 !OP_SYMBOL(left)->remat &&
6904 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6906 int size = AOP_SIZE(result) - 1;
6908 emitcode("dec","%s",rname);
6913 freeAsmop(result,NULL,ic,TRUE);
6918 /*-----------------------------------------------------------------*/
6919 /* genFarPointerGet - gget value from far space */
6920 /*-----------------------------------------------------------------*/
6921 static void genFarPointerGet (operand *left,
6922 operand *result, iCode *ic)
6925 link *retype = getSpec(operandType(result));
6927 D(emitcode(";", "genFarPointerGet"););
6929 aopOp(left,ic,FALSE, FALSE);
6931 /* if the operand is already in dptr
6932 then we do nothing else we move the value to dptr */
6933 if (AOP_TYPE(left) != AOP_STR) {
6934 /* if this is remateriazable */
6935 if (AOP_TYPE(left) == AOP_IMMD)
6937 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6941 /* we need to get it byte by byte */
6942 _startLazyDPSEvaluation();
6943 if (AOP_TYPE(left) != AOP_DPTR)
6945 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6946 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6947 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6951 /* We need to generate a load to DPTR indirect through DPTR. */
6952 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6953 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6954 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6955 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6956 emitcode("pop", "dph");
6957 emitcode("pop", "dpl");
6959 _endLazyDPSEvaluation();
6962 /* so dptr know contains the address */
6963 freeAsmop(left,NULL,ic,TRUE);
6964 aopOp(result,ic,FALSE, TRUE);
6966 /* if bit then unpack */
6967 if (IS_BITVAR(retype))
6968 genUnpackBits(result,"dptr",FPOINTER);
6970 size = AOP_SIZE(result);
6973 _startLazyDPSEvaluation();
6979 emitcode("movx","a,@dptr");
6981 emitcode("inc","dptr");
6983 aopPut(AOP(result),"a",offset++);
6985 _endLazyDPSEvaluation();
6988 freeAsmop(result,NULL,ic,TRUE);
6991 /*-----------------------------------------------------------------*/
6992 /* emitcodePointerGet - gget value from code space */
6993 /*-----------------------------------------------------------------*/
6994 static void emitcodePointerGet (operand *left,
6995 operand *result, iCode *ic)
6998 link *retype = getSpec(operandType(result));
7000 aopOp(left,ic,FALSE, FALSE);
7002 /* if the operand is already in dptr
7003 then we do nothing else we move the value to dptr */
7004 if (AOP_TYPE(left) != AOP_STR) {
7005 /* if this is remateriazable */
7006 if (AOP_TYPE(left) == AOP_IMMD)
7007 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7008 else { /* we need to get it byte by byte */
7009 _startLazyDPSEvaluation();
7010 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7011 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7012 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7013 _endLazyDPSEvaluation();
7016 /* so dptr know contains the address */
7017 freeAsmop(left,NULL,ic,TRUE);
7018 aopOp(result,ic,FALSE, TRUE);
7020 /* if bit then unpack */
7021 if (IS_BITVAR(retype))
7022 genUnpackBits(result,"dptr",CPOINTER);
7024 size = AOP_SIZE(result);
7027 _startLazyDPSEvaluation();
7033 emitcode("clr","a");
7034 emitcode("movc","a,@a+dptr");
7036 emitcode("inc","dptr");
7037 aopPut(AOP(result),"a",offset++);
7039 _endLazyDPSEvaluation();
7042 freeAsmop(result,NULL,ic,TRUE);
7045 /*-----------------------------------------------------------------*/
7046 /* genGenPointerGet - gget value from generic pointer space */
7047 /*-----------------------------------------------------------------*/
7048 static void genGenPointerGet (operand *left,
7049 operand *result, iCode *ic)
7052 link *retype = getSpec(operandType(result));
7054 aopOp(left,ic,FALSE, TRUE);
7056 /* if the operand is already in dptr
7057 then we do nothing else we move the value to dptr */
7058 if (AOP_TYPE(left) != AOP_STR) {
7059 /* if this is remateriazable */
7060 if (AOP_TYPE(left) == AOP_IMMD) {
7061 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7062 emitcode("mov","b,#%d",pointerCode(retype));
7064 else { /* we need to get it byte by byte */
7065 _startLazyDPSEvaluation();
7066 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7067 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7068 if (options.model == MODEL_FLAT24)
7070 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7071 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7075 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7077 _endLazyDPSEvaluation();
7080 /* so dptr know contains the address */
7081 freeAsmop(left,NULL,ic,TRUE);
7082 aopOp(result,ic,FALSE, TRUE);
7084 /* if bit then unpack */
7085 if (IS_BITVAR(retype))
7086 genUnpackBits(result,"dptr",GPOINTER);
7088 size = AOP_SIZE(result);
7092 emitcode("lcall","__gptrget");
7093 aopPut(AOP(result),"a",offset++);
7095 emitcode("inc","dptr");
7099 freeAsmop(result,NULL,ic,TRUE);
7102 /*-----------------------------------------------------------------*/
7103 /* genPointerGet - generate code for pointer get */
7104 /*-----------------------------------------------------------------*/
7105 static void genPointerGet (iCode *ic)
7107 operand *left, *result ;
7111 D(emitcode(";", "genPointerGet "););
7114 result = IC_RESULT(ic) ;
7116 /* depending on the type of pointer we need to
7117 move it to the correct pointer register */
7118 type = operandType(left);
7119 etype = getSpec(type);
7120 /* if left is of type of pointer then it is simple */
7121 if (IS_PTR(type) && !IS_FUNC(type->next))
7122 p_type = DCL_TYPE(type);
7124 /* we have to go by the storage class */
7125 p_type = PTR_TYPE(SPEC_OCLS(etype));
7127 /* if (SPEC_OCLS(etype)->codesp ) { */
7128 /* p_type = CPOINTER ; */
7131 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7132 /* p_type = FPOINTER ; */
7134 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7135 /* p_type = PPOINTER; */
7137 /* if (SPEC_OCLS(etype) == idata ) */
7138 /* p_type = IPOINTER; */
7140 /* p_type = POINTER ; */
7143 /* now that we have the pointer type we assign
7144 the pointer values */
7149 genNearPointerGet (left,result,ic);
7153 genPagedPointerGet(left,result,ic);
7157 genFarPointerGet (left,result,ic);
7161 emitcodePointerGet (left,result,ic);
7165 genGenPointerGet (left,result,ic);
7171 /*-----------------------------------------------------------------*/
7172 /* genPackBits - generates code for packed bit storage */
7173 /*-----------------------------------------------------------------*/
7174 static void genPackBits (link *etype ,
7176 char *rname, int p_type)
7184 blen = SPEC_BLEN(etype);
7185 bstr = SPEC_BSTR(etype);
7187 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7190 /* if the bit lenth is less than or */
7191 /* it exactly fits a byte then */
7192 if (SPEC_BLEN(etype) <= 8 ) {
7193 shCount = SPEC_BSTR(etype) ;
7195 /* shift left acc */
7198 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7203 emitcode ("mov","b,a");
7204 emitcode("mov","a,@%s",rname);
7208 emitcode ("mov","b,a");
7209 emitcode("movx","a,@dptr");
7213 emitcode ("push","b");
7214 emitcode ("push","acc");
7215 emitcode ("lcall","__gptrget");
7216 emitcode ("pop","b");
7220 emitcode ("anl","a,#0x%02x",(unsigned char)
7221 ((unsigned char)(0xFF << (blen+bstr)) |
7222 (unsigned char)(0xFF >> (8-bstr)) ) );
7223 emitcode ("orl","a,b");
7224 if (p_type == GPOINTER)
7225 emitcode("pop","b");
7231 emitcode("mov","@%s,a",rname);
7235 emitcode("movx","@dptr,a");
7239 emitcode("lcall","__gptrput");
7244 if ( SPEC_BLEN(etype) <= 8 )
7247 emitcode("inc","%s",rname);
7248 rLen = SPEC_BLEN(etype) ;
7250 /* now generate for lengths greater than one byte */
7253 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7263 emitcode("mov","@%s,a",rname);
7265 emitcode("mov","@%s,%s",rname,l);
7270 emitcode("movx","@dptr,a");
7275 emitcode("lcall","__gptrput");
7278 emitcode ("inc","%s",rname);
7283 /* last last was not complete */
7285 /* save the byte & read byte */
7288 emitcode ("mov","b,a");
7289 emitcode("mov","a,@%s",rname);
7293 emitcode ("mov","b,a");
7294 emitcode("movx","a,@dptr");
7298 emitcode ("push","b");
7299 emitcode ("push","acc");
7300 emitcode ("lcall","__gptrget");
7301 emitcode ("pop","b");
7305 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7306 emitcode ("orl","a,b");
7309 if (p_type == GPOINTER)
7310 emitcode("pop","b");
7315 emitcode("mov","@%s,a",rname);
7319 emitcode("movx","@dptr,a");
7323 emitcode("lcall","__gptrput");
7327 /*-----------------------------------------------------------------*/
7328 /* genDataPointerSet - remat pointer to data space */
7329 /*-----------------------------------------------------------------*/
7330 static void genDataPointerSet(operand *right,
7334 int size, offset = 0 ;
7335 char *l, buffer[256];
7337 aopOp(right,ic,FALSE, FALSE);
7339 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7340 size = AOP_SIZE(right);
7343 sprintf(buffer,"(%s + %d)",l+1,offset);
7345 sprintf(buffer,"%s",l+1);
7346 emitcode("mov","%s,%s",buffer,
7347 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7350 freeAsmop(right,NULL,ic,TRUE);
7351 freeAsmop(result,NULL,ic,TRUE);
7354 /*-----------------------------------------------------------------*/
7355 /* genNearPointerSet - emitcode for near pointer put */
7356 /*-----------------------------------------------------------------*/
7357 static void genNearPointerSet (operand *right,
7365 link *ptype = operandType(result);
7367 retype= getSpec(operandType(right));
7369 aopOp(result,ic,FALSE, FALSE);
7371 /* if the result is rematerializable &
7372 in data space & not a bit variable */
7373 if (AOP_TYPE(result) == AOP_IMMD &&
7374 DCL_TYPE(ptype) == POINTER &&
7375 !IS_BITVAR(retype)) {
7376 genDataPointerSet (right,result,ic);
7380 /* if the value is already in a pointer register
7381 then don't need anything more */
7382 if (!AOP_INPREG(AOP(result))) {
7383 /* otherwise get a free pointer register */
7385 preg = getFreePtr(ic,&aop,FALSE);
7386 emitcode("mov","%s,%s",
7388 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7389 rname = preg->name ;
7391 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7393 freeAsmop(result,NULL,ic,TRUE);
7394 aopOp (right,ic,FALSE, FALSE);
7396 /* if bitfield then unpack the bits */
7397 if (IS_BITVAR(retype))
7398 genPackBits (retype,right,rname,POINTER);
7400 /* we have can just get the values */
7401 int size = AOP_SIZE(right);
7405 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7408 emitcode("mov","@%s,a",rname);
7410 emitcode("mov","@%s,%s",rname,l);
7412 emitcode("inc","%s",rname);
7417 /* now some housekeeping stuff */
7419 /* we had to allocate for this iCode */
7420 freeAsmop(NULL,aop,ic,TRUE);
7422 /* we did not allocate which means left
7423 already in a pointer register, then
7424 if size > 0 && this could be used again
7425 we have to point it back to where it
7427 if (AOP_SIZE(right) > 1 &&
7428 !OP_SYMBOL(result)->remat &&
7429 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7431 int size = AOP_SIZE(right) - 1;
7433 emitcode("dec","%s",rname);
7438 freeAsmop(right,NULL,ic,TRUE);
7443 /*-----------------------------------------------------------------*/
7444 /* genPagedPointerSet - emitcode for Paged pointer put */
7445 /*-----------------------------------------------------------------*/
7446 static void genPagedPointerSet (operand *right,
7455 retype= getSpec(operandType(right));
7457 aopOp(result,ic,FALSE, FALSE);
7459 /* if the value is already in a pointer register
7460 then don't need anything more */
7461 if (!AOP_INPREG(AOP(result))) {
7462 /* otherwise get a free pointer register */
7464 preg = getFreePtr(ic,&aop,FALSE);
7465 emitcode("mov","%s,%s",
7467 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7468 rname = preg->name ;
7470 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7472 freeAsmop(result,NULL,ic,TRUE);
7473 aopOp (right,ic,FALSE, FALSE);
7475 /* if bitfield then unpack the bits */
7476 if (IS_BITVAR(retype))
7477 genPackBits (retype,right,rname,PPOINTER);
7479 /* we have can just get the values */
7480 int size = AOP_SIZE(right);
7484 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7487 emitcode("movx","@%s,a",rname);
7490 emitcode("inc","%s",rname);
7496 /* now some housekeeping stuff */
7498 /* we had to allocate for this iCode */
7499 freeAsmop(NULL,aop,ic,TRUE);
7501 /* we did not allocate which means left
7502 already in a pointer register, then
7503 if size > 0 && this could be used again
7504 we have to point it back to where it
7506 if (AOP_SIZE(right) > 1 &&
7507 !OP_SYMBOL(result)->remat &&
7508 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7510 int size = AOP_SIZE(right) - 1;
7512 emitcode("dec","%s",rname);
7517 freeAsmop(right,NULL,ic,TRUE);
7522 /*-----------------------------------------------------------------*/
7523 /* genFarPointerSet - set value from far space */
7524 /*-----------------------------------------------------------------*/
7525 static void genFarPointerSet (operand *right,
7526 operand *result, iCode *ic)
7529 link *retype = getSpec(operandType(right));
7531 aopOp(result,ic,FALSE, FALSE);
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 /* if this is remateriazable */
7537 if (AOP_TYPE(result) == AOP_IMMD)
7538 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7541 /* we need to get it byte by byte */
7542 _startLazyDPSEvaluation();
7543 if (AOP_TYPE(result) != AOP_DPTR)
7545 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7546 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7547 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7551 /* We need to generate a load to DPTR indirect through DPTR. */
7552 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7553 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7554 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7555 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7556 emitcode("pop", "dph");
7557 emitcode("pop", "dpl");
7559 _endLazyDPSEvaluation();
7562 /* so dptr know contains the address */
7563 freeAsmop(result,NULL,ic,TRUE);
7564 aopOp(right,ic,FALSE, TRUE);
7566 /* if bit then unpack */
7567 if (IS_BITVAR(retype))
7568 genPackBits(retype,right,"dptr",FPOINTER);
7570 size = AOP_SIZE(right);
7573 _startLazyDPSEvaluation();
7575 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7581 emitcode("movx","@dptr,a");
7583 emitcode("inc","dptr");
7585 _endLazyDPSEvaluation();
7588 freeAsmop(right,NULL,ic,TRUE);
7591 /*-----------------------------------------------------------------*/
7592 /* genGenPointerSet - set value from generic pointer space */
7593 /*-----------------------------------------------------------------*/
7594 static void genGenPointerSet (operand *right,
7595 operand *result, iCode *ic)
7598 link *retype = getSpec(operandType(right));
7600 aopOp(result,ic,FALSE, TRUE);
7602 /* if the operand is already in dptr
7603 then we do nothing else we move the value to dptr */
7604 if (AOP_TYPE(result) != AOP_STR) {
7605 _startLazyDPSEvaluation();
7606 /* if this is remateriazable */
7607 if (AOP_TYPE(result) == AOP_IMMD) {
7608 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7609 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7611 else { /* we need to get it byte by byte */
7612 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7613 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7614 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7615 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7617 _endLazyDPSEvaluation();
7619 /* so dptr know contains the address */
7620 freeAsmop(result,NULL,ic,TRUE);
7621 aopOp(right,ic,FALSE, TRUE);
7623 /* if bit then unpack */
7624 if (IS_BITVAR(retype))
7625 genPackBits(retype,right,"dptr",GPOINTER);
7627 size = AOP_SIZE(right);
7630 _startLazyDPSEvaluation();
7632 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7638 emitcode("lcall","__gptrput");
7640 emitcode("inc","dptr");
7642 _endLazyDPSEvaluation();
7645 freeAsmop(right,NULL,ic,TRUE);
7648 /*-----------------------------------------------------------------*/
7649 /* genPointerSet - stores the value into a pointer location */
7650 /*-----------------------------------------------------------------*/
7651 static void genPointerSet (iCode *ic)
7653 operand *right, *result ;
7657 D(emitcode(";", "genPointerSet "););
7659 right = IC_RIGHT(ic);
7660 result = IC_RESULT(ic) ;
7662 /* depending on the type of pointer we need to
7663 move it to the correct pointer register */
7664 type = operandType(result);
7665 etype = getSpec(type);
7666 /* if left is of type of pointer then it is simple */
7667 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7668 p_type = DCL_TYPE(type);
7671 /* we have to go by the storage class */
7672 p_type = PTR_TYPE(SPEC_OCLS(etype));
7674 /* if (SPEC_OCLS(etype)->codesp ) { */
7675 /* p_type = CPOINTER ; */
7678 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7679 /* p_type = FPOINTER ; */
7681 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7682 /* p_type = PPOINTER ; */
7684 /* if (SPEC_OCLS(etype) == idata ) */
7685 /* p_type = IPOINTER ; */
7687 /* p_type = POINTER ; */
7690 /* now that we have the pointer type we assign
7691 the pointer values */
7696 genNearPointerSet (right,result,ic);
7700 genPagedPointerSet (right,result,ic);
7704 genFarPointerSet (right,result,ic);
7708 genGenPointerSet (right,result,ic);
7714 /*-----------------------------------------------------------------*/
7715 /* genIfx - generate code for Ifx statement */
7716 /*-----------------------------------------------------------------*/
7717 static void genIfx (iCode *ic, iCode *popIc)
7719 operand *cond = IC_COND(ic);
7722 D(emitcode(";", "genIfx "););
7724 aopOp(cond,ic,FALSE, FALSE);
7726 /* get the value into acc */
7727 if (AOP_TYPE(cond) != AOP_CRY)
7731 /* the result is now in the accumulator */
7732 freeAsmop(cond,NULL,ic,TRUE);
7734 /* if there was something to be popped then do it */
7738 /* if the condition is a bit variable */
7739 if (isbit && IS_ITEMP(cond) &&
7741 genIfxJump(ic,SPIL_LOC(cond)->rname);
7743 if (isbit && !IS_ITEMP(cond))
7744 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7751 /*-----------------------------------------------------------------*/
7752 /* genAddrOf - generates code for address of */
7753 /*-----------------------------------------------------------------*/
7754 static void genAddrOf (iCode *ic)
7756 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7759 D(emitcode(";", "genAddrOf "););
7761 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7763 /* if the operand is on the stack then we
7764 need to get the stack offset of this
7767 /* if it has an offset then we need to compute
7770 emitcode("mov","a,_bp");
7771 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7772 aopPut(AOP(IC_RESULT(ic)),"a",0);
7774 /* we can just move _bp */
7775 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7777 /* fill the result with zero */
7778 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7781 if (options.stack10bit && size < (FPTRSIZE - 1))
7784 "*** warning: pointer to stack var truncated.\n");
7791 if (options.stack10bit && offset == 2)
7793 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7797 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7804 /* object not on stack then we need the name */
7805 size = AOP_SIZE(IC_RESULT(ic));
7809 char s[SDCC_NAME_MAX];
7811 sprintf(s,"#(%s >> %d)",
7815 sprintf(s,"#%s",sym->rname);
7816 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7820 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7824 /*-----------------------------------------------------------------*/
7825 /* genFarFarAssign - assignment when both are in far space */
7826 /*-----------------------------------------------------------------*/
7827 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7829 int size = AOP_SIZE(right);
7836 /* This is a net loss for size == 1, but a big gain
7839 D(emitcode(";", "genFarFarAssign (improved)"););
7841 aopOp(result,ic,TRUE, TRUE);
7843 _startLazyDPSEvaluation();
7847 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7851 _endLazyDPSEvaluation();
7852 freeAsmop(result,NULL,ic,FALSE);
7853 freeAsmop(right,NULL,ic,FALSE);
7858 D(emitcode(";", "genFarFarAssign "););
7860 /* first push the right side on to the stack */
7861 _startLazyDPSEvaluation();
7863 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7865 emitcode ("push","acc");
7868 freeAsmop(right,NULL,ic,FALSE);
7869 /* now assign DPTR to result */
7870 aopOp(result,ic,FALSE, FALSE);
7871 size = AOP_SIZE(result);
7873 emitcode ("pop","acc");
7874 aopPut(AOP(result),"a",--offset);
7876 freeAsmop(result,NULL,ic,FALSE);
7877 _endLazyDPSEvaluation();
7881 /*-----------------------------------------------------------------*/
7882 /* genAssign - generate code for assignment */
7883 /*-----------------------------------------------------------------*/
7884 static void genAssign (iCode *ic)
7886 operand *result, *right;
7888 unsigned long lit = 0L;
7890 D(emitcode(";", "genAssign "););
7892 result = IC_RESULT(ic);
7893 right = IC_RIGHT(ic) ;
7895 /* if they are the same */
7896 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7899 aopOp(right,ic,FALSE, FALSE);
7901 emitcode(";", "genAssign: resultIsFar = %s",
7902 isOperandInFarSpace(result) ?
7905 /* special case both in far space */
7906 if ((AOP_TYPE(right) == AOP_DPTR ||
7907 AOP_TYPE(right) == AOP_DPTR2) &&
7908 /* IS_TRUE_SYMOP(result) && */
7909 isOperandInFarSpace(result)) {
7911 genFarFarAssign (result,right,ic);
7915 aopOp(result,ic,TRUE, FALSE);
7917 /* if they are the same registers */
7918 if (sameRegs(AOP(right),AOP(result)))
7921 /* if the result is a bit */
7922 if (AOP_TYPE(result) == AOP_CRY) {
7924 /* if the right size is a literal then
7925 we know what the value is */
7926 if (AOP_TYPE(right) == AOP_LIT) {
7927 if (((int) operandLitValue(right)))
7928 aopPut(AOP(result),one,0);
7930 aopPut(AOP(result),zero,0);
7934 /* the right is also a bit variable */
7935 if (AOP_TYPE(right) == AOP_CRY) {
7936 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7937 aopPut(AOP(result),"c",0);
7943 aopPut(AOP(result),"a",0);
7947 /* bit variables done */
7949 size = AOP_SIZE(result);
7951 if(AOP_TYPE(right) == AOP_LIT)
7952 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7955 (AOP_TYPE(result) != AOP_REG) &&
7956 (AOP_TYPE(right) == AOP_LIT) &&
7957 !IS_FLOAT(operandType(right))
7958 #ifndef LAZY_DPS_OPT
7964 D(emitcode(";", "Kevin's better literal load code"););
7965 _startLazyDPSEvaluation();
7966 while (size && ((unsigned int)(lit >> (offset*8)) != 0))
7969 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
7974 /* And now fill the rest with zeros. */
7977 emitcode("clr","a");
7981 aopPut(AOP(result), "a", offset++);
7983 _endLazyDPSEvaluation();
7985 emitcode("clr","a");
7987 _startLazyDPSEvaluation();
7990 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7991 aopPut(AOP(result),"a",size);
7994 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
7997 _endLazyDPSEvaluation();
8002 _startLazyDPSEvaluation();
8006 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8010 _endLazyDPSEvaluation();
8014 freeAsmop (right,NULL,ic,FALSE);
8015 freeAsmop (result,NULL,ic,TRUE);
8018 /*-----------------------------------------------------------------*/
8019 /* genJumpTab - generates code for jump table */
8020 /*-----------------------------------------------------------------*/
8021 static void genJumpTab (iCode *ic)
8026 D(emitcode(";", "genJumpTab "););
8028 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
8029 /* get the condition into accumulator */
8030 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
8032 /* multiply by four! */
8033 emitcode("add","a,acc");
8034 emitcode("add","a,acc");
8035 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8037 jtab = newiTempLabel(NULL);
8038 emitcode("mov","dptr,#%05d$",jtab->key+100);
8039 emitcode("jmp","@a+dptr");
8040 emitcode("","%05d$:",jtab->key+100);
8041 /* now generate the jump labels */
8042 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8043 jtab = setNextItem(IC_JTLABELS(ic)))
8044 emitcode("ljmp","%05d$",jtab->key+100);
8048 /*-----------------------------------------------------------------*/
8049 /* genCast - gen code for casting */
8050 /*-----------------------------------------------------------------*/
8051 static void genCast (iCode *ic)
8053 operand *result = IC_RESULT(ic);
8054 link *ctype = operandType(IC_LEFT(ic));
8055 link *rtype = operandType(IC_RIGHT(ic));
8056 operand *right = IC_RIGHT(ic);
8059 D(emitcode(";", "genCast "););
8061 /* if they are equivalent then do nothing */
8062 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8065 aopOp(right,ic,FALSE, FALSE) ;
8066 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
8068 /* if the result is a bit */
8069 if (AOP_TYPE(result) == AOP_CRY) {
8070 /* if the right size is a literal then
8071 we know what the value is */
8072 if (AOP_TYPE(right) == AOP_LIT) {
8073 if (((int) operandLitValue(right)))
8074 aopPut(AOP(result),one,0);
8076 aopPut(AOP(result),zero,0);
8081 /* the right is also a bit variable */
8082 if (AOP_TYPE(right) == AOP_CRY) {
8083 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8084 aopPut(AOP(result),"c",0);
8090 aopPut(AOP(result),"a",0);
8094 /* if they are the same size : or less */
8095 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8097 /* if they are in the same place */
8098 if (sameRegs(AOP(right),AOP(result)))
8101 /* if they in different places then copy */
8102 size = AOP_SIZE(result);
8104 _startLazyDPSEvaluation();
8107 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8111 _endLazyDPSEvaluation();
8116 /* if the result is of type pointer */
8117 if (IS_PTR(ctype)) {
8120 link *type = operandType(right);
8122 /* pointer to generic pointer */
8123 if (IS_GENPTR(ctype)) {
8128 p_type = DCL_TYPE(type);
8132 #if OLD_CAST_BEHAVIOR
8133 /* KV: we are converting a non-pointer type to
8134 * a generic pointer. This (ifdef'd out) code
8135 * says that the resulting generic pointer
8136 * should have the same class as the storage
8137 * location of the non-pointer variable.
8139 * For example, converting an int (which happens
8140 * to be stored in DATA space) to a pointer results
8141 * in a DATA generic pointer; if the original int
8142 * in XDATA space, so will be the resulting pointer.
8144 * I don't like that behavior, and thus this change:
8145 * all such conversions will be forced to XDATA and
8146 * throw a warning. If you want some non-XDATA
8147 * type, or you want to suppress the warning, you
8148 * must go through an intermediate cast, like so:
8150 * char _generic *gp = (char _xdata *)(intVar);
8152 link *etype = getSpec(type);
8154 /* we have to go by the storage class */
8155 if (SPEC_OCLS(etype) != generic)
8157 p_type = PTR_TYPE(SPEC_OCLS(etype));
8162 /* Converting unknown class (i.e. register variable)
8163 * to generic pointer. This is not good, but
8164 * we'll make a guess (and throw a warning).
8167 werror(W_INT_TO_GEN_PTR_CAST);
8171 /* the first two bytes are known */
8172 size = GPTRSIZE - 1;
8174 _startLazyDPSEvaluation();
8177 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8181 _endLazyDPSEvaluation();
8183 /* the last byte depending on type */
8200 /* this should never happen */
8201 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8202 "got unknown pointer type");
8205 aopPut(AOP(result),l, GPTRSIZE - 1);
8209 /* just copy the pointers */
8210 size = AOP_SIZE(result);
8212 _startLazyDPSEvaluation();
8215 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8219 _endLazyDPSEvaluation();
8223 /* so we now know that the size of destination is greater
8224 than the size of the source */
8225 /* we move to result for the size of source */
8226 size = AOP_SIZE(right);
8228 _startLazyDPSEvaluation();
8231 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8235 _endLazyDPSEvaluation();
8237 /* now depending on the sign of the source && destination */
8238 size = AOP_SIZE(result) - AOP_SIZE(right);
8239 /* if unsigned or not an integral type */
8240 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
8242 aopPut(AOP(result),zero,offset++);
8244 /* we need to extend the sign :{ */
8245 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8248 emitcode("rlc","a");
8249 emitcode("subb","a,acc");
8251 aopPut(AOP(result),"a",offset++);
8254 /* we are done hurray !!!! */
8257 freeAsmop(right,NULL,ic,TRUE);
8258 freeAsmop(result,NULL,ic,TRUE);
8262 /*-----------------------------------------------------------------*/
8263 /* genDjnz - generate decrement & jump if not zero instrucion */
8264 /*-----------------------------------------------------------------*/
8265 static int genDjnz (iCode *ic, iCode *ifx)
8271 /* if the if condition has a false label
8272 then we cannot save */
8276 /* if the minus is not of the form
8278 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8279 !IS_OP_LITERAL(IC_RIGHT(ic)))
8282 if (operandLitValue(IC_RIGHT(ic)) != 1)
8285 /* if the size of this greater than one then no
8287 if (getSize(operandType(IC_RESULT(ic))) > 1)
8290 /* otherwise we can save BIG */
8291 lbl = newiTempLabel(NULL);
8292 lbl1= newiTempLabel(NULL);
8294 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8296 if (IS_AOP_PREG(IC_RESULT(ic))) {
8297 emitcode("dec","%s",
8298 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8299 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8300 emitcode("jnz","%05d$",lbl->key+100);
8302 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8305 emitcode ("sjmp","%05d$",lbl1->key+100);
8306 emitcode ("","%05d$:",lbl->key+100);
8307 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8308 emitcode ("","%05d$:",lbl1->key+100);
8310 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8315 /*-----------------------------------------------------------------*/
8316 /* genReceive - generate code for a receive iCode */
8317 /*-----------------------------------------------------------------*/
8318 static void genReceive (iCode *ic)
8321 D(emitcode(";", "genReceive "););
8323 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8324 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8325 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8326 int size = getSize(operandType(IC_RESULT(ic)));
8327 int offset = fReturnSize_390 - size;
8329 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8330 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8333 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8334 size = AOP_SIZE(IC_RESULT(ic));
8337 emitcode ("pop","acc");
8338 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8343 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8345 assignResultValue(IC_RESULT(ic));
8348 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8351 /*-----------------------------------------------------------------*/
8352 /* gen390Code - generate code for 8051 based controllers */
8353 /*-----------------------------------------------------------------*/
8354 void gen390Code (iCode *lic)
8359 lineHead = lineCurr = NULL;
8361 /* print the allocation information */
8363 printAllocInfo( currFunc, codeOutFile);
8364 /* if debug information required */
8365 /* if (options.debug && currFunc) { */
8367 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8369 if (IS_STATIC(currFunc->etype))
8370 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8372 emitcode("","G$%s$0$0 ==.",currFunc->name);
8375 /* stack pointer name */
8376 if (options.useXstack)
8382 for (ic = lic ; ic ; ic = ic->next ) {
8384 if ( cln != ic->lineno ) {
8385 if ( options.debug ) {
8387 emitcode("","C$%s$%d$%d$%d ==.",
8388 ic->filename,ic->lineno,
8389 ic->level,ic->block);
8392 emitcode(";","%s %d",ic->filename,ic->lineno);
8395 /* if the result is marked as
8396 spilt and rematerializable or code for
8397 this has already been generated then
8399 if (resultRemat(ic) || ic->generated )
8402 /* depending on the operation */
8421 /* IPOP happens only when trying to restore a
8422 spilt live range, if there is an ifx statement
8423 following this pop then the if statement might
8424 be using some of the registers being popped which
8425 would destory the contents of the register so
8426 we need to check for this condition and handle it */
8428 ic->next->op == IFX &&
8429 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8430 genIfx (ic->next,ic);
8448 genEndFunction (ic);
8468 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8485 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8489 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8496 /* note these two are xlated by algebraic equivalence
8497 during parsing SDCC.y */
8498 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8499 "got '>=' or '<=' shouldn't have come here");
8503 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8515 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8519 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8523 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8550 case GET_VALUE_AT_ADDRESS:
8555 if (POINTER_SET(ic))
8582 addSet(&_G.sendSet,ic);
8587 /* piCode(ic,stdout); */
8593 /* now we are ready to call the
8594 peep hole optimizer */
8595 if (!options.nopeep)
8596 peepHole (&lineHead);
8598 /* now do the actual printing */
8599 printLine (lineHead,codeOutFile);