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 /* #define LAZY_DPS_OPT */ /* turn this on after some more testing. */
246 static int _currentDPS; /* Current processor DPS. */
247 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
248 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
250 /*-----------------------------------------------------------------*/
251 /* genSetDPTR: generate code to select which DPTR is in use (zero */
252 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
253 /* alternate DPTR (DPL1/DPH1/DPX1). */
254 /*-----------------------------------------------------------------*/
255 static void genSetDPTR(int n)
259 /* If we are doing lazy evaluation, simply note the desired
260 * change, but don't emit any code yet.
271 emitcode("mov", "dps, #0x00");
275 emitcode("mov", "dps, #0x01");
279 /*-----------------------------------------------------------------*/
280 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation*/
282 /* Any code that operates on DPTR (NB: not on the individual */
283 /* components, like DPH) *must* call _flushLazyDPS() before using */
284 /* DPTR within a lazy DPS evaluation block. */
286 /* Note that aopPut and aopGet already contain the proper calls to */
287 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
288 /* DPS evaluation block. */
290 /* Also, _flushLazyDPS must be called before any flow control */
291 /* operations that could potentially branch out of the block. */
293 /* Lazy DPS evaluation is simply an optimization (though an */
294 /* important one), so if in doubt, leave it out. */
295 /*-----------------------------------------------------------------*/
296 static void _startLazyDPSEvaluation(void)
303 /*-----------------------------------------------------------------*/
304 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
305 /* desired one. Call before using DPTR within a lazy DPS evaluation*/
307 /*-----------------------------------------------------------------*/
308 static void _flushLazyDPS(void)
316 if (_desiredDPS != _currentDPS)
320 emitcode("inc", "dps");
324 emitcode("dec", "dps");
326 _currentDPS = _desiredDPS;
330 /*-----------------------------------------------------------------*/
331 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
333 /* Forces us back to the safe state (standard DPTR selected). */
334 /*-----------------------------------------------------------------*/
335 static void _endLazyDPSEvaluation(void)
349 /*-----------------------------------------------------------------*/
350 /* pointerCode - returns the code for a pointer type */
351 /*-----------------------------------------------------------------*/
352 static int pointerCode (link *etype)
355 return PTR_TYPE(SPEC_OCLS(etype));
359 /*-----------------------------------------------------------------*/
360 /* aopForSym - for a true symbol */
361 /*-----------------------------------------------------------------*/
362 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
365 memmap *space= SPEC_OCLS(sym->etype);
367 /* if already has one */
371 /* assign depending on the storage class */
372 /* if it is on the stack or indirectly addressable */
373 /* space we need to assign either r0 or r1 to it */
374 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
375 sym->aop = aop = newAsmop(0);
376 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
377 aop->size = getSize(sym->type);
379 /* now assign the address of the variable to
380 the pointer register */
381 if (aop->type != AOP_STK) {
385 emitcode("push","acc");
387 emitcode("mov","a,_bp");
388 emitcode("add","a,#0x%02x",
390 ((char)(sym->stack - _G.nRegsSaved )) :
391 ((char)sym->stack)) & 0xff);
392 emitcode("mov","%s,a",
393 aop->aopu.aop_ptr->name);
396 emitcode("pop","acc");
398 emitcode("mov","%s,#%s",
399 aop->aopu.aop_ptr->name,
401 aop->paged = space->paged;
403 aop->aopu.aop_stk = sym->stack;
407 if (sym->onStack && options.stack10bit)
409 /* It's on the 10 bit stack, which is located in
414 emitcode("push","acc");
416 emitcode("mov","a,_bp");
417 emitcode("add","a,#0x%02x",
419 ((char)(sym->stack - _G.nRegsSaved )) :
420 ((char)sym->stack)) & 0xff);
425 emitcode ("mov","dpx1,#0x40");
426 emitcode ("mov","dph1,#0x00");
427 emitcode ("mov","dpl1, a");
432 emitcode ("mov","dpx,#0x40");
433 emitcode ("mov","dph,#0x00");
434 emitcode ("mov","dpl, a");
438 emitcode("pop","acc");
440 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
441 aop->size = getSize(sym->type);
445 /* if in bit space */
446 if (IN_BITSPACE(space)) {
447 sym->aop = aop = newAsmop (AOP_CRY);
448 aop->aopu.aop_dir = sym->rname ;
449 aop->size = getSize(sym->type);
452 /* if it is in direct space */
453 if (IN_DIRSPACE(space)) {
454 sym->aop = aop = newAsmop (AOP_DIR);
455 aop->aopu.aop_dir = sym->rname ;
456 aop->size = getSize(sym->type);
460 /* special case for a function */
461 if (IS_FUNC(sym->type)) {
462 sym->aop = aop = newAsmop(AOP_IMMD);
463 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
464 strcpy(aop->aopu.aop_immd,sym->rname);
465 aop->size = FPTRSIZE;
469 /* only remaining is far space */
470 /* in which case DPTR gets the address */
471 sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
476 emitcode ("mov","dptr,#%s", sym->rname);
481 emitcode ("mov","dptr,#%s", sym->rname);
483 aop->size = getSize(sym->type);
485 /* if it is in code space */
486 if (IN_CODESPACE(space))
492 /*-----------------------------------------------------------------*/
493 /* aopForRemat - rematerialzes an object */
494 /*-----------------------------------------------------------------*/
495 static asmop *aopForRemat (symbol *sym)
497 iCode *ic = sym->rematiCode;
498 asmop *aop = newAsmop(AOP_IMMD);
504 val += operandLitValue(IC_RIGHT(ic));
505 else if (ic->op == '-')
506 val -= operandLitValue(IC_RIGHT(ic));
510 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
514 sprintf(buffer,"(%s %c 0x%04x)",
515 OP_SYMBOL(IC_LEFT(ic))->rname,
516 val >= 0 ? '+' : '-',
519 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
521 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
522 strcpy(aop->aopu.aop_immd,buffer);
526 /*-----------------------------------------------------------------*/
527 /* regsInCommon - two operands have some registers in common */
528 /*-----------------------------------------------------------------*/
529 static bool regsInCommon (operand *op1, operand *op2)
534 /* if they have registers in common */
535 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
538 sym1 = OP_SYMBOL(op1);
539 sym2 = OP_SYMBOL(op2);
541 if (sym1->nRegs == 0 || sym2->nRegs == 0)
544 for (i = 0 ; i < sym1->nRegs ; i++) {
549 for (j = 0 ; j < sym2->nRegs ;j++ ) {
553 if (sym2->regs[j] == sym1->regs[i])
561 /*-----------------------------------------------------------------*/
562 /* operandsEqu - equivalent */
563 /*-----------------------------------------------------------------*/
564 static bool operandsEqu ( operand *op1, operand *op2)
568 /* if they not symbols */
569 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
572 sym1 = OP_SYMBOL(op1);
573 sym2 = OP_SYMBOL(op2);
575 /* if both are itemps & one is spilt
576 and the other is not then false */
577 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
578 sym1->isspilt != sym2->isspilt )
581 /* if they are the same */
585 if (strcmp(sym1->rname,sym2->rname) == 0)
589 /* if left is a tmp & right is not */
593 (sym1->usl.spillLoc == sym2))
600 (sym2->usl.spillLoc == sym1))
606 /*-----------------------------------------------------------------*/
607 /* sameRegs - two asmops have the same registers */
608 /*-----------------------------------------------------------------*/
609 static bool sameRegs (asmop *aop1, asmop *aop2 )
615 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
622 if (aop1->type != AOP_REG ||
623 aop2->type != AOP_REG )
626 if (aop1->size != aop2->size )
629 for (i = 0 ; i < aop1->size ; i++ )
630 if (aop1->aopu.aop_reg[i] !=
631 aop2->aopu.aop_reg[i] )
637 /*-----------------------------------------------------------------*/
638 /* aopOp - allocates an asmop for an operand : */
639 /*-----------------------------------------------------------------*/
640 static void aopOp (operand *op, iCode *ic, bool result, bool useDP2)
649 /* if this a literal */
650 if (IS_OP_LITERAL(op)) {
651 op->aop = aop = newAsmop(AOP_LIT);
652 aop->aopu.aop_lit = op->operand.valOperand;
653 aop->size = getSize(operandType(op));
657 /* if already has a asmop then continue */
661 /* if the underlying symbol has a aop */
662 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
663 op->aop = OP_SYMBOL(op)->aop;
667 /* if this is a true symbol */
668 if (IS_TRUE_SYMOP(op)) {
669 op->aop = aopForSym(ic,OP_SYMBOL(op),result, useDP2);
673 /* this is a temporary : this has
679 e) can be a return use only */
684 /* if the type is a conditional */
685 if (sym->regType == REG_CND) {
686 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
691 /* if it is spilt then two situations
693 b) has a spill location */
694 if (sym->isspilt || sym->nRegs == 0) {
696 /* rematerialize it NOW */
698 sym->aop = op->aop = aop =
700 aop->size = getSize(sym->type);
706 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
707 aop->size = getSize(sym->type);
708 for ( i = 0 ; i < 2 ; i++ )
709 aop->aopu.aop_str[i] = accUse[i];
715 aop = op->aop = sym->aop = newAsmop(AOP_STR);
716 aop->size = getSize(sym->type);
717 for ( i = 0 ; i < fReturnSize_390 ; i++ )
718 aop->aopu.aop_str[i] = fReturn[i];
722 /* else spill location */
723 sym->aop = op->aop = aop =
724 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
725 aop->size = getSize(sym->type);
729 /* must be in a register */
730 sym->aop = op->aop = aop = newAsmop(AOP_REG);
731 aop->size = sym->nRegs;
732 for ( i = 0 ; i < sym->nRegs ;i++)
733 aop->aopu.aop_reg[i] = sym->regs[i];
736 /*-----------------------------------------------------------------*/
737 /* freeAsmop - free up the asmop given to an operand */
738 /*----------------------------------------------------------------*/
739 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
756 /* depending on the asmop type only three cases need work AOP_RO
757 , AOP_R1 && AOP_STK */
762 emitcode ("pop","ar0");
766 bitVectUnSetBit(ic->rUsed,R0_IDX);
772 emitcode ("pop","ar1");
776 bitVectUnSetBit(ic->rUsed,R1_IDX);
782 int stk = aop->aopu.aop_stk + aop->size;
783 bitVectUnSetBit(ic->rUsed,R0_IDX);
784 bitVectUnSetBit(ic->rUsed,R1_IDX);
786 getFreePtr(ic,&aop,FALSE);
788 if (options.stack10bit)
790 /* I'm not sure what to do here yet... */
793 "*** Warning: probably generating bad code for "
794 "10 bit stack mode.\n");
798 emitcode ("mov","a,_bp");
799 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
800 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
802 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
806 emitcode("pop","acc");
807 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
809 emitcode("dec","%s",aop->aopu.aop_ptr->name);
812 freeAsmop(op,NULL,ic,TRUE);
814 emitcode("pop","ar0");
819 emitcode("pop","ar1");
826 /* all other cases just dealloc */
830 OP_SYMBOL(op)->aop = NULL;
831 /* if the symbol has a spill */
833 SPIL_LOC(op)->aop = NULL;
838 /*------------------------------------------------------------------*/
839 /* aopGet - for fetching value of the aop */
841 /* Set canClobberACC if you are aure it is OK to clobber the value */
842 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe,*/
843 /* just less efficient. */
844 /*------------------------------------------------------------------*/
846 static char *aopGet (asmop *aop,
855 /* offset is greater than
857 if (offset > (aop->size - 1) &&
858 aop->type != AOP_LIT)
861 /* depending on type */
866 /* if we need to increment it */
867 while (offset > aop->coff) {
868 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
872 while (offset < aop->coff) {
873 emitcode("dec","%s",aop->aopu.aop_ptr->name);
879 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
880 return (dname ? "acc" : "a");
882 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
883 ALLOC_ATOMIC(rs,strlen(s)+1);
890 if (aop->type == AOP_DPTR2)
894 #ifndef KEVIN_BROKE_IT
898 emitcode("xch", "a, ap");
904 while (offset > aop->coff) {
905 emitcode ("inc","dptr");
909 while (offset < aop->coff) {
910 emitcode("lcall","__decdptr");
917 emitcode("movc","a,@a+dptr");
920 emitcode("movx","a,@dptr");
923 if (aop->type == AOP_DPTR2)
927 #ifndef KEVIN_BROKE_IT
931 emitcode("xch", "a, ap");
936 return (dname ? "acc" : "a");
940 sprintf (s,"#%s",aop->aopu.aop_immd);
943 sprintf(s,"#(%s >> %d)",
949 ALLOC_ATOMIC(rs,strlen(s)+1);
955 sprintf(s,"(%s + %d)",
959 sprintf(s,"%s",aop->aopu.aop_dir);
960 ALLOC_ATOMIC(rs,strlen(s)+1);
966 return aop->aopu.aop_reg[offset]->dname;
968 return aop->aopu.aop_reg[offset]->name;
972 emitcode("mov","c,%s",aop->aopu.aop_dir);
973 emitcode("rlc","a") ;
974 return (dname ? "acc" : "a");
977 if (!offset && dname)
979 return aop->aopu.aop_str[offset];
982 return aopLiteral (aop->aopu.aop_lit,offset);
986 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
990 return aop->aopu.aop_str[offset];
994 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
995 "aopget got unsupported aop->type");
998 /*-----------------------------------------------------------------*/
999 /* aopPut - puts a string for a aop */
1000 /*-----------------------------------------------------------------*/
1001 static void aopPut (asmop *aop, char *s, int offset)
1006 if (aop->size && offset > ( aop->size - 1)) {
1007 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1008 "aopPut got offset > aop->size");
1012 /* will assign value to value */
1013 /* depending on where it is ofcourse */
1014 switch (aop->type) {
1017 sprintf(d,"(%s + %d)",
1018 aop->aopu.aop_dir,offset);
1020 sprintf(d,"%s",aop->aopu.aop_dir);
1023 emitcode("mov","%s,%s",d,s);
1028 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1029 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1031 strcmp(s,"r0") == 0 ||
1032 strcmp(s,"r1") == 0 ||
1033 strcmp(s,"r2") == 0 ||
1034 strcmp(s,"r3") == 0 ||
1035 strcmp(s,"r4") == 0 ||
1036 strcmp(s,"r5") == 0 ||
1037 strcmp(s,"r6") == 0 ||
1038 strcmp(s,"r7") == 0 )
1039 emitcode("mov","%s,%s",
1040 aop->aopu.aop_reg[offset]->dname,s);
1042 emitcode("mov","%s,%s",
1043 aop->aopu.aop_reg[offset]->name,s);
1050 if (aop->type == AOP_DPTR2)
1057 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1058 "aopPut writting to code space");
1062 while (offset > aop->coff) {
1064 emitcode ("inc","dptr");
1067 while (offset < aop->coff) {
1069 emitcode("lcall","__decdptr");
1074 /* if not in accumulater */
1077 emitcode ("movx","@dptr,a");
1079 if (aop->type == AOP_DPTR2)
1087 while (offset > aop->coff) {
1089 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1091 while (offset < aop->coff) {
1093 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1099 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1104 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1106 if (strcmp(s,"r0") == 0 ||
1107 strcmp(s,"r1") == 0 ||
1108 strcmp(s,"r2") == 0 ||
1109 strcmp(s,"r3") == 0 ||
1110 strcmp(s,"r4") == 0 ||
1111 strcmp(s,"r5") == 0 ||
1112 strcmp(s,"r6") == 0 ||
1113 strcmp(s,"r7") == 0 ) {
1115 sprintf(buffer,"a%s",s);
1116 emitcode("mov","@%s,%s",
1117 aop->aopu.aop_ptr->name,buffer);
1119 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1124 if (strcmp(s,"a") == 0)
1125 emitcode("push","acc");
1127 emitcode("push","%s",s);
1132 /* if bit variable */
1133 if (!aop->aopu.aop_dir) {
1134 emitcode("clr","a");
1135 emitcode("rlc","a");
1138 emitcode("clr","%s",aop->aopu.aop_dir);
1141 emitcode("setb","%s",aop->aopu.aop_dir);
1144 emitcode("mov","%s,c",aop->aopu.aop_dir);
1146 lbl = newiTempLabel(NULL);
1148 if (strcmp(s,"a")) {
1151 emitcode("clr","c");
1152 emitcode("jz","%05d$",lbl->key+100);
1153 emitcode("cpl","c");
1154 emitcode("","%05d$:",lbl->key+100);
1155 emitcode("mov","%s,c",aop->aopu.aop_dir);
1162 if (strcmp(aop->aopu.aop_str[offset],s))
1163 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1168 if (!offset && (strcmp(s,"acc") == 0))
1171 if (strcmp(aop->aopu.aop_str[offset],s))
1172 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1176 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1177 "aopPut got unsupported aop->type");
1184 /*-----------------------------------------------------------------*/
1185 /* reAdjustPreg - points a register back to where it should */
1186 /*-----------------------------------------------------------------*/
1187 static void reAdjustPreg (asmop *aop)
1192 if ((size = aop->size) <= 1)
1195 switch (aop->type) {
1199 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1203 if (aop->type == AOP_DPTR2)
1210 emitcode("lcall","__decdptr");
1213 if (aop->type == AOP_DPTR2)
1223 #define AOP(op) op->aop
1224 #define AOP_TYPE(op) AOP(op)->type
1225 #define AOP_SIZE(op) AOP(op)->size
1226 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1227 AOP_TYPE(x) == AOP_R0))
1229 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1230 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1233 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1234 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1235 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1237 /* Workaround for DS80C390 bug: div ab may return bogus results
1238 * if A is accessed in instruction immediately before the div.
1240 * Will be fixed in B4 rev of processor, Dallas claims.
1243 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1244 if (!AOP_NEEDSACC(RIGHT)) \
1246 /* We can load A first, then B, since \
1247 * B (the RIGHT operand) won't clobber A, \
1248 * thus avoiding touching A right before the div. \
1250 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1251 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1253 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1257 /* Just stuff in a nop after loading A. */ \
1258 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1259 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1261 emitcode("nop", "; workaround for DS80C390 div bug."); \
1264 /*-----------------------------------------------------------------*/
1265 /* genNotFloat - generates not for float operations */
1266 /*-----------------------------------------------------------------*/
1267 static void genNotFloat (operand *op, operand *res)
1273 D(emitcode(";", "genNotFloat "););
1275 /* we will put 127 in the first byte of
1277 aopPut(AOP(res),"#127",0);
1278 size = AOP_SIZE(op) - 1;
1281 _startLazyDPSEvaluation();
1282 l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
1286 emitcode("orl","a,%s",
1288 offset++,FALSE,FALSE,FALSE));
1290 _endLazyDPSEvaluation();
1291 tlbl = newiTempLabel(NULL);
1293 tlbl = newiTempLabel(NULL);
1294 aopPut(res->aop,one,1);
1295 emitcode("jz","%05d$",(tlbl->key+100));
1296 aopPut(res->aop,zero,1);
1297 emitcode("","%05d$:",(tlbl->key+100));
1299 size = res->aop->size - 2;
1301 /* put zeros in the rest */
1303 aopPut(res->aop,zero,offset++);
1306 /*-----------------------------------------------------------------*/
1307 /* opIsGptr: returns non-zero if the passed operand is */
1308 /* a generic pointer type. */
1309 /*-----------------------------------------------------------------*/
1310 static int opIsGptr(operand *op)
1312 link *type = operandType(op);
1314 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1321 /*-----------------------------------------------------------------*/
1322 /* getDataSize - get the operand data size */
1323 /*-----------------------------------------------------------------*/
1324 static int getDataSize(operand *op)
1327 size = AOP_SIZE(op);
1328 if (size == GPTRSIZE)
1330 link *type = operandType(op);
1331 if (IS_GENPTR(type))
1333 /* generic pointer; arithmetic operations
1334 * should ignore the high byte (pointer type).
1342 /*-----------------------------------------------------------------*/
1343 /* outAcc - output Acc */
1344 /*-----------------------------------------------------------------*/
1345 static void outAcc(operand *result)
1348 size = getDataSize(result);
1350 aopPut(AOP(result),"a",0);
1353 /* unsigned or positive */
1355 aopPut(AOP(result),zero,offset++);
1360 /*-----------------------------------------------------------------*/
1361 /* outBitC - output a bit C */
1362 /*-----------------------------------------------------------------*/
1363 static void outBitC(operand *result)
1365 /* if the result is bit */
1366 if (AOP_TYPE(result) == AOP_CRY)
1367 aopPut(AOP(result),"c",0);
1369 emitcode("clr","a");
1370 emitcode("rlc","a");
1375 /*-----------------------------------------------------------------*/
1376 /* toBoolean - emit code for orl a,operator(sizeop) */
1377 /*-----------------------------------------------------------------*/
1378 static void toBoolean(operand *oper)
1380 int size = AOP_SIZE(oper) - 1;
1383 /* The generic part of a generic pointer should
1384 * not participate in it's truth value.
1386 * i.e. 0x10000000 is zero.
1390 D(emitcode(";", "toBoolean: generic ptr special case."););
1394 _startLazyDPSEvaluation();
1395 if (AOP_NEEDSACC(oper))
1397 emitcode("push", "b");
1398 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1402 MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1406 if (AOP_NEEDSACC(oper))
1408 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1412 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1415 _endLazyDPSEvaluation();
1417 if (AOP_NEEDSACC(oper))
1419 emitcode("mov", "a,b");
1420 emitcode("pop", "b");
1425 /*-----------------------------------------------------------------*/
1426 /* genNot - generate code for ! operation */
1427 /*-----------------------------------------------------------------*/
1428 static void genNot (iCode *ic)
1431 link *optype = operandType(IC_LEFT(ic));
1433 D(emitcode(";", "genNot "););
1435 /* assign asmOps to operand & result */
1436 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1437 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1439 /* if in bit space then a special case */
1440 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1441 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1442 emitcode("cpl","c");
1443 outBitC(IC_RESULT(ic));
1447 /* if type float then do float */
1448 if (IS_FLOAT(optype)) {
1449 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1453 toBoolean(IC_LEFT(ic));
1455 tlbl = newiTempLabel(NULL);
1456 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1457 emitcode("","%05d$:",tlbl->key+100);
1458 outBitC(IC_RESULT(ic));
1461 /* release the aops */
1462 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1463 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1467 /*-----------------------------------------------------------------*/
1468 /* genCpl - generate code for complement */
1469 /*-----------------------------------------------------------------*/
1470 static void genCpl (iCode *ic)
1475 D(emitcode(";", "genCpl "););
1478 /* assign asmOps to operand & result */
1479 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1480 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1482 /* if both are in bit space then
1484 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1485 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1487 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1488 emitcode("cpl","c");
1489 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1493 size = AOP_SIZE(IC_RESULT(ic));
1494 _startLazyDPSEvaluation();
1496 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1498 emitcode("cpl","a");
1499 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1501 _endLazyDPSEvaluation();
1505 /* release the aops */
1506 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1507 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1510 /*-----------------------------------------------------------------*/
1511 /* genUminusFloat - unary minus for floating points */
1512 /*-----------------------------------------------------------------*/
1513 static void genUminusFloat(operand *op,operand *result)
1515 int size ,offset =0 ;
1517 /* for this we just need to flip the
1518 first it then copy the rest in place */
1519 D(emitcode(";", "genUminusFloat"););
1521 _startLazyDPSEvaluation();
1522 size = AOP_SIZE(op) - 1;
1523 l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1526 emitcode("cpl","acc.7");
1527 aopPut(AOP(result),"a",3);
1531 aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1535 _endLazyDPSEvaluation();
1538 /*-----------------------------------------------------------------*/
1539 /* genUminus - unary minus code generation */
1540 /*-----------------------------------------------------------------*/
1541 static void genUminus (iCode *ic)
1544 link *optype, *rtype;
1546 D(emitcode(";", "genUminus "););
1550 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1551 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1553 /* if both in bit space then special
1555 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1556 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1558 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1559 emitcode("cpl","c");
1560 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1564 optype = operandType(IC_LEFT(ic));
1565 rtype = operandType(IC_RESULT(ic));
1567 /* if float then do float stuff */
1568 if (IS_FLOAT(optype)) {
1569 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1573 /* otherwise subtract from zero */
1574 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);
1835 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1836 size = AOP_SIZE(IC_LEFT(ic));
1838 _startLazyDPSEvaluation();
1840 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1841 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1842 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1844 emitcode("mov","a,%s",l);
1845 emitcode("push","acc");
1847 emitcode("push","%s",l);
1849 _endLazyDPSEvaluation();
1851 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1854 /*-----------------------------------------------------------------*/
1855 /* genIpop - recover the registers: can happen only for spilling */
1856 /*-----------------------------------------------------------------*/
1857 static void genIpop (iCode *ic)
1861 D(emitcode(";", "genIpop "););
1864 /* if the temp was not pushed then */
1865 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1868 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1869 size = AOP_SIZE(IC_LEFT(ic));
1871 _startLazyDPSEvaluation();
1874 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1877 _endLazyDPSEvaluation();
1879 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1882 /*-----------------------------------------------------------------*/
1883 /* unsaverbank - restores the resgister bank from stack */
1884 /*-----------------------------------------------------------------*/
1885 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1892 if (options.useXstack) {
1894 r = getFreePtr(ic,&aop,FALSE);
1897 emitcode("mov","%s,_spx",r->name);
1898 emitcode("movx","a,@%s",r->name);
1899 emitcode("mov","psw,a");
1900 emitcode("dec","%s",r->name);
1903 emitcode ("pop","psw");
1906 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1907 if (options.useXstack) {
1908 emitcode("movx","a,@%s",r->name);
1909 emitcode("mov","(%s+%d),a",
1910 regs390[i].base,8*bank+regs390[i].offset);
1911 emitcode("dec","%s",r->name);
1914 emitcode("pop","(%s+%d)",
1915 regs390[i].base,8*bank+regs390[i].offset);
1918 if (options.useXstack) {
1920 emitcode("mov","_spx,%s",r->name);
1921 freeAsmop(NULL,aop,ic,TRUE);
1926 /*-----------------------------------------------------------------*/
1927 /* saverbank - saves an entire register bank on the stack */
1928 /*-----------------------------------------------------------------*/
1929 static void saverbank (int bank, iCode *ic, bool pushPsw)
1935 if (options.useXstack) {
1938 r = getFreePtr(ic,&aop,FALSE);
1939 emitcode("mov","%s,_spx",r->name);
1943 for (i = 0 ; i < ds390_nRegs ;i++) {
1944 if (options.useXstack) {
1945 emitcode("inc","%s",r->name);
1946 emitcode("mov","a,(%s+%d)",
1947 regs390[i].base,8*bank+regs390[i].offset);
1948 emitcode("movx","@%s,a",r->name);
1950 emitcode("push","(%s+%d)",
1951 regs390[i].base,8*bank+regs390[i].offset);
1955 if (options.useXstack) {
1956 emitcode("mov","a,psw");
1957 emitcode("movx","@%s,a",r->name);
1958 emitcode("inc","%s",r->name);
1959 emitcode("mov","_spx,%s",r->name);
1960 freeAsmop (NULL,aop,ic,TRUE);
1963 emitcode("push","psw");
1965 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1971 /*-----------------------------------------------------------------*/
1972 /* genCall - generates a call statement */
1973 /*-----------------------------------------------------------------*/
1974 static void genCall (iCode *ic)
1978 D(emitcode(";", "genCall "););
1980 /* if caller saves & we have not saved then */
1984 /* if we are calling a function that is not using
1985 the same register bank then we need to save the
1986 destination registers on the stack */
1987 detype = getSpec(operandType(IC_LEFT(ic)));
1989 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1990 IS_ISR(currFunc->etype) &&
1993 saverbank(SPEC_BANK(detype),ic,TRUE);
1995 /* if send set is not empty the assign */
1999 for (sic = setFirstItem(_G.sendSet) ; sic ;
2000 sic = setNextItem(_G.sendSet))
2002 int size, offset = 0;
2004 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
2005 size = AOP_SIZE(IC_LEFT(sic));
2007 _startLazyDPSEvaluation();
2009 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2010 FALSE, FALSE, TRUE);
2011 if (strcmp(l,fReturn[offset]))
2012 emitcode("mov","%s,%s",
2017 _endLazyDPSEvaluation();
2018 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2023 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2024 OP_SYMBOL(IC_LEFT(ic))->rname :
2025 OP_SYMBOL(IC_LEFT(ic))->name));
2027 /* if we need assign a result value */
2028 if ((IS_ITEMP(IC_RESULT(ic)) &&
2029 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2030 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2031 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2034 /* Not really related to LAZY_DPS_OPT, but don't want
2035 * another testing flag right now...
2038 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2041 assignResultValue(IC_RESULT(ic));
2043 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2046 if (!isOperandInFarSpace(IC_RESULT(ic)))
2049 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2052 assignResultValue(IC_RESULT(ic));
2054 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2058 /* Result is in far space, and requires DPTR to access
2059 * it. Push the result onto the stack and restore from
2062 int size = getSize(operandType(IC_RESULT(ic)));
2063 int offset = size - 1;
2066 emitcode(";", "Kevin function call abuse #1");
2068 /* first push the right side on to the stack */
2069 /* NB: this relies on the fact that "a" is the last
2070 * register in fReturn. If it were not, the MOVA
2071 * would potentially clobber a returned byte in A.
2074 l = fReturn[offset--];
2076 emitcode ("push","acc");
2079 /* now assign DPTR to result */
2080 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2081 size = AOP_SIZE(IC_RESULT(ic));
2082 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
2084 emitcode ("pop","acc");
2085 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
2087 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2092 /* adjust the stack for parameters if
2094 if (IC_LEFT(ic)->parmBytes) {
2096 if (IC_LEFT(ic)->parmBytes > 3) {
2097 emitcode("mov","a,%s",spname);
2098 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2099 emitcode("mov","%s,a",spname);
2101 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2102 emitcode("dec","%s",spname);
2106 /* if register bank was saved then pop them */
2108 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2110 /* if we hade saved some registers then unsave them */
2111 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2112 unsaveRegisters (ic);
2117 /*-----------------------------------------------------------------*/
2118 /* genPcall - generates a call by pointer statement */
2119 /*-----------------------------------------------------------------*/
2120 static void genPcall (iCode *ic)
2123 symbol *rlbl = newiTempLabel(NULL);
2125 D(emitcode(";", "genPcall "););
2128 /* if caller saves & we have not saved then */
2132 /* if we are calling a function that is not using
2133 the same register bank then we need to save the
2134 destination registers on the stack */
2135 detype = getSpec(operandType(IC_LEFT(ic)));
2137 IS_ISR(currFunc->etype) &&
2138 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2139 saverbank(SPEC_BANK(detype),ic,TRUE);
2142 /* push the return address on to the stack */
2143 emitcode("mov","a,#%05d$",(rlbl->key+100));
2144 emitcode("push","acc");
2145 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2146 emitcode("push","acc");
2148 if (options.model == MODEL_FLAT24)
2150 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2151 emitcode("push","acc");
2154 /* now push the calling address */
2155 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2157 pushSide(IC_LEFT(ic), FPTRSIZE);
2159 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2161 /* if send set is not empty the assign */
2165 for (sic = setFirstItem(_G.sendSet) ; sic ;
2166 sic = setNextItem(_G.sendSet))
2168 int size, offset = 0;
2170 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2171 size = AOP_SIZE(IC_LEFT(sic));
2172 _startLazyDPSEvaluation();
2175 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2177 if (strcmp(l,fReturn[offset]))
2179 emitcode("mov","%s,%s",
2185 _endLazyDPSEvaluation();
2186 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2192 emitcode("","%05d$:",(rlbl->key+100));
2195 /* if we need assign a result value */
2196 if ((IS_ITEMP(IC_RESULT(ic)) &&
2197 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2198 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2199 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2202 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2205 assignResultValue(IC_RESULT(ic));
2207 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2210 /* adjust the stack for parameters if
2212 if (IC_LEFT(ic)->parmBytes) {
2214 if (IC_LEFT(ic)->parmBytes > 3) {
2215 emitcode("mov","a,%s",spname);
2216 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2217 emitcode("mov","%s,a",spname);
2219 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2220 emitcode("dec","%s",spname);
2224 /* if register bank was saved then unsave them */
2226 (SPEC_BANK(currFunc->etype) !=
2228 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2230 /* if we hade saved some registers then
2233 unsaveRegisters (ic);
2237 /*-----------------------------------------------------------------*/
2238 /* resultRemat - result is rematerializable */
2239 /*-----------------------------------------------------------------*/
2240 static int resultRemat (iCode *ic)
2242 if (SKIP_IC(ic) || ic->op == IFX)
2245 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2246 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2247 if (sym->remat && !POINTER_SET(ic))
2255 #define STRCASECMP stricmp
2257 #define STRCASECMP strcasecmp
2260 /*-----------------------------------------------------------------*/
2261 /* inExcludeList - return 1 if the string is in exclude Reg list */
2262 /*-----------------------------------------------------------------*/
2263 static bool inExcludeList(char *s)
2267 if (options.excludeRegs[i] &&
2268 STRCASECMP(options.excludeRegs[i],"none") == 0)
2271 for ( i = 0 ; options.excludeRegs[i]; i++) {
2272 if (options.excludeRegs[i] &&
2273 STRCASECMP(s,options.excludeRegs[i]) == 0)
2279 /*-----------------------------------------------------------------*/
2280 /* genFunction - generated code for function entry */
2281 /*-----------------------------------------------------------------*/
2282 static void genFunction (iCode *ic)
2287 D(emitcode(";", "genFunction "););
2290 /* create the function header */
2291 emitcode(";","-----------------------------------------");
2292 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2293 emitcode(";","-----------------------------------------");
2295 emitcode("","%s:",sym->rname);
2296 fetype = getSpec(operandType(IC_LEFT(ic)));
2298 /* if critical function then turn interrupts off */
2299 if (SPEC_CRTCL(fetype))
2300 emitcode("clr","ea");
2302 /* here we need to generate the equates for the
2303 register bank if required */
2304 if (SPEC_BANK(fetype) != rbank) {
2307 rbank = SPEC_BANK(fetype);
2308 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2309 if (strcmp(regs390[i].base,"0") == 0)
2310 emitcode("","%s = 0x%02x",
2312 8*rbank+regs390[i].offset);
2314 emitcode ("","%s = %s + 0x%02x",
2317 8*rbank+regs390[i].offset);
2321 /* if this is an interrupt service routine then
2322 save acc, b, dpl, dph */
2323 if (IS_ISR(sym->etype)) {
2325 if (!inExcludeList("acc"))
2326 emitcode ("push","acc");
2327 if (!inExcludeList("b"))
2328 emitcode ("push","b");
2329 if (!inExcludeList("dpl"))
2330 emitcode ("push","dpl");
2331 if (!inExcludeList("dph"))
2332 emitcode ("push","dph");
2333 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2335 emitcode ("push", "dpx");
2336 /* Make sure we're using standard DPTR */
2337 emitcode ("push", "dps");
2338 emitcode ("mov", "dps, #0x00");
2339 if (options.stack10bit)
2341 /* This ISR could conceivably use DPTR2. Better save it. */
2342 emitcode ("push", "dpl1");
2343 emitcode ("push", "dph1");
2344 emitcode ("push", "dpx1");
2345 emitcode ("push", "ap");
2348 /* if this isr has no bank i.e. is going to
2349 run with bank 0 , then we need to save more
2351 if (!SPEC_BANK(sym->etype)) {
2353 /* if this function does not call any other
2354 function then we can be economical and
2355 save only those registers that are used */
2356 if (! sym->hasFcall) {
2359 /* if any registers used */
2360 if (sym->regsUsed) {
2361 /* save the registers used */
2362 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2363 if (bitVectBitValue(sym->regsUsed,i) ||
2364 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2365 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2370 /* this function has a function call cannot
2371 determines register usage so we will have the
2373 saverbank(0,ic,FALSE);
2377 /* if callee-save to be used for this function
2378 then save the registers being used in this function */
2379 if (sym->calleeSave) {
2382 /* if any registers used */
2383 if (sym->regsUsed) {
2384 /* save the registers used */
2385 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2386 if (bitVectBitValue(sym->regsUsed,i) ||
2387 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2388 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2396 /* set the register bank to the desired value */
2397 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2398 emitcode("push","psw");
2399 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2402 if (IS_RENT(sym->etype) || options.stackAuto) {
2404 if (options.useXstack) {
2405 emitcode("mov","r0,%s",spname);
2406 emitcode("mov","a,_bp");
2407 emitcode("movx","@r0,a");
2408 emitcode("inc","%s",spname);
2412 /* set up the stack */
2413 emitcode ("push","_bp"); /* save the callers stack */
2415 emitcode ("mov","_bp,%s",spname);
2418 /* adjust the stack for the function */
2423 werror(W_STACK_OVERFLOW,sym->name);
2425 if (i > 3 && sym->recvSize < 4) {
2427 emitcode ("mov","a,sp");
2428 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2429 emitcode ("mov","sp,a");
2434 emitcode("inc","sp");
2439 emitcode ("mov","a,_spx");
2440 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2441 emitcode ("mov","_spx,a");
2446 /*-----------------------------------------------------------------*/
2447 /* genEndFunction - generates epilogue for functions */
2448 /*-----------------------------------------------------------------*/
2449 static void genEndFunction (iCode *ic)
2451 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2453 D(emitcode(";", "genEndFunction "););
2455 if (IS_RENT(sym->etype) || options.stackAuto)
2457 emitcode ("mov","%s,_bp",spname);
2460 /* if use external stack but some variables were
2461 added to the local stack then decrement the
2463 if (options.useXstack && sym->stack) {
2464 emitcode("mov","a,sp");
2465 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2466 emitcode("mov","sp,a");
2470 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2471 if (options.useXstack) {
2472 emitcode("mov","r0,%s",spname);
2473 emitcode("movx","a,@r0");
2474 emitcode("mov","_bp,a");
2475 emitcode("dec","%s",spname);
2479 emitcode ("pop","_bp");
2483 /* restore the register bank */
2484 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2485 emitcode ("pop","psw");
2487 if (IS_ISR(sym->etype)) {
2489 /* now we need to restore the registers */
2490 /* if this isr has no bank i.e. is going to
2491 run with bank 0 , then we need to save more
2493 if (!SPEC_BANK(sym->etype)) {
2495 /* if this function does not call any other
2496 function then we can be economical and
2497 save only those registers that are used */
2498 if (! sym->hasFcall) {
2501 /* if any registers used */
2502 if (sym->regsUsed) {
2503 /* save the registers used */
2504 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2505 if (bitVectBitValue(sym->regsUsed,i) ||
2506 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2507 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2512 /* this function has a function call cannot
2513 determines register usage so we will have the
2515 unsaverbank(0,ic,FALSE);
2519 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2521 if (options.stack10bit)
2523 emitcode ("pop", "ap");
2524 emitcode ("pop", "dpx1");
2525 emitcode ("pop", "dph1");
2526 emitcode ("pop", "dpl1");
2528 emitcode ("pop", "dps");
2529 emitcode ("pop", "dpx");
2531 if (!inExcludeList("dph"))
2532 emitcode ("pop","dph");
2533 if (!inExcludeList("dpl"))
2534 emitcode ("pop","dpl");
2535 if (!inExcludeList("b"))
2536 emitcode ("pop","b");
2537 if (!inExcludeList("acc"))
2538 emitcode ("pop","acc");
2540 if (SPEC_CRTCL(sym->etype))
2541 emitcode("setb","ea");
2543 /* if debug then send end of function */
2544 /* if (options.debug && currFunc) { */
2547 emitcode("","C$%s$%d$%d$%d ==.",
2548 ic->filename,currFunc->lastLine,
2549 ic->level,ic->block);
2550 if (IS_STATIC(currFunc->etype))
2551 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2553 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2557 emitcode ("reti","");
2560 if (SPEC_CRTCL(sym->etype))
2561 emitcode("setb","ea");
2563 if (sym->calleeSave) {
2566 /* if any registers used */
2567 if (sym->regsUsed) {
2568 /* save the registers used */
2569 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2570 if (bitVectBitValue(sym->regsUsed,i) ||
2571 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2572 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2578 /* if debug then send end of function */
2581 emitcode("","C$%s$%d$%d$%d ==.",
2582 ic->filename,currFunc->lastLine,
2583 ic->level,ic->block);
2584 if (IS_STATIC(currFunc->etype))
2585 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2587 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2591 emitcode ("ret","");
2596 /*-----------------------------------------------------------------*/
2597 /* genRet - generate code for return statement */
2598 /*-----------------------------------------------------------------*/
2599 static void genRet (iCode *ic)
2601 int size,offset = 0 , pushed = 0;
2603 D(emitcode(";", "genRet "););
2605 /* if we have no return value then
2606 just generate the "ret" */
2610 /* we have something to return then
2611 move the return value into place */
2612 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2613 size = AOP_SIZE(IC_LEFT(ic));
2615 _startLazyDPSEvaluation();
2618 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2619 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2621 emitcode("push","%s",l);
2624 l = aopGet(AOP(IC_LEFT(ic)),offset,
2626 if (strcmp(fReturn[offset],l))
2627 emitcode("mov","%s,%s",fReturn[offset++],l);
2630 _endLazyDPSEvaluation();
2635 if (strcmp(fReturn[pushed],"a"))
2636 emitcode("pop",fReturn[pushed]);
2638 emitcode("pop","acc");
2641 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2644 /* generate a jump to the return label
2645 if the next is not the return statement */
2646 if (!(ic->next && ic->next->op == LABEL &&
2647 IC_LABEL(ic->next) == returnLabel))
2649 emitcode("ljmp","%05d$",(returnLabel->key+100));
2653 /*-----------------------------------------------------------------*/
2654 /* genLabel - generates a label */
2655 /*-----------------------------------------------------------------*/
2656 static void genLabel (iCode *ic)
2658 /* special case never generate */
2659 if (IC_LABEL(ic) == entryLabel)
2662 D(emitcode(";", "genLabel "););
2664 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2667 /*-----------------------------------------------------------------*/
2668 /* genGoto - generates a ljmp */
2669 /*-----------------------------------------------------------------*/
2670 static void genGoto (iCode *ic)
2672 D(emitcode(";", "genGoto "););
2673 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2676 /*-----------------------------------------------------------------*/
2677 /* findLabelBackwards: walks back through the iCode chain looking */
2678 /* for the given label. Returns number of iCode instructions */
2679 /* between that label and given ic. */
2680 /* Returns zero if label not found. */
2681 /*-----------------------------------------------------------------*/
2682 static int findLabelBackwards(iCode *ic, int key)
2691 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2693 /* printf("findLabelBackwards = %d\n", count); */
2701 /*-----------------------------------------------------------------*/
2702 /* genPlusIncr :- does addition with increment if possible */
2703 /*-----------------------------------------------------------------*/
2704 static bool genPlusIncr (iCode *ic)
2706 unsigned int icount ;
2707 unsigned int size = getDataSize(IC_RESULT(ic));
2709 /* will try to generate an increment */
2710 /* if the right side is not a literal
2712 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2715 /* if the literal value of the right hand side
2716 is greater than 4 then it is not worth it */
2717 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2720 /* if increment 16 bits in register */
2722 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2723 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2724 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2731 /* If the next instruction is a goto and the goto target
2732 * is <= 5 instructions previous to this, we can generate
2733 * jumps straight to that target.
2735 if (ic->next && ic->next->op == GOTO
2736 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2737 && labelRange <= 5 )
2739 emitcode(";", "tail increment optimized (range %d)", labelRange);
2740 tlbl = IC_LABEL(ic->next);
2745 tlbl = newiTempLabel(NULL);
2748 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2749 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2750 IS_AOP_PREG(IC_RESULT(ic)))
2751 emitcode("cjne","%s,#0x00,%05d$"
2752 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2755 emitcode("clr","a");
2756 emitcode("cjne","a,%s,%05d$"
2757 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2761 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2764 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2765 IS_AOP_PREG(IC_RESULT(ic)))
2766 emitcode("cjne","%s,#0x00,%05d$"
2767 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2770 emitcode("cjne","a,%s,%05d$"
2771 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2774 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2778 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2779 IS_AOP_PREG(IC_RESULT(ic)))
2780 emitcode("cjne","%s,#0x00,%05d$"
2781 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2784 emitcode("cjne","a,%s,%05d$"
2785 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2788 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2793 emitcode("","%05d$:",tlbl->key+100);
2798 /* if the sizes are greater than 1 then we cannot */
2799 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2800 AOP_SIZE(IC_LEFT(ic)) > 1 )
2803 /* we can if the aops of the left & result match or
2804 if they are in registers and the registers are the
2807 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2808 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2809 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2812 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2813 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2814 aopPut(AOP(IC_RESULT(ic)),"a",0);
2817 _startLazyDPSEvaluation();
2820 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2822 _endLazyDPSEvaluation();
2831 /*-----------------------------------------------------------------*/
2832 /* outBitAcc - output a bit in acc */
2833 /*-----------------------------------------------------------------*/
2834 static void outBitAcc(operand *result)
2836 symbol *tlbl = newiTempLabel(NULL);
2837 /* if the result is a bit */
2838 if (AOP_TYPE(result) == AOP_CRY){
2839 aopPut(AOP(result),"a",0);
2842 emitcode("jz","%05d$",tlbl->key+100);
2843 emitcode("mov","a,%s",one);
2844 emitcode("","%05d$:",tlbl->key+100);
2849 /*-----------------------------------------------------------------*/
2850 /* genPlusBits - generates code for addition of two bits */
2851 /*-----------------------------------------------------------------*/
2852 static void genPlusBits (iCode *ic)
2854 D(emitcode(";", "genPlusBits "););
2855 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2856 symbol *lbl = newiTempLabel(NULL);
2857 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2858 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2859 emitcode("cpl","c");
2860 emitcode("","%05d$:",(lbl->key+100));
2861 outBitC(IC_RESULT(ic));
2864 emitcode("clr","a");
2865 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2866 emitcode("rlc","a");
2867 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2868 emitcode("addc","a,#0x00");
2869 outAcc(IC_RESULT(ic));
2873 static void adjustArithmeticResult(iCode *ic)
2875 if (opIsGptr(IC_RESULT(ic)) &&
2876 opIsGptr(IC_LEFT(ic)) &&
2877 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2879 aopPut(AOP(IC_RESULT(ic)),
2880 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2884 if (opIsGptr(IC_RESULT(ic)) &&
2885 opIsGptr(IC_RIGHT(ic)) &&
2886 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2888 aopPut(AOP(IC_RESULT(ic)),
2889 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2893 if (opIsGptr(IC_RESULT(ic)) &&
2894 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2895 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2896 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2897 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2899 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2900 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2904 #define AOP_OP_3(ic) \
2905 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2906 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2907 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2908 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2909 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2911 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2913 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2916 #define AOP_SET_LOCALS(ic) \
2917 left = IC_LEFT(ic); \
2918 right = IC_RIGHT(ic); \
2919 result = IC_RESULT(ic);
2921 /*-----------------------------------------------------------------*/
2922 /* genPlus - generates code for addition */
2923 /*-----------------------------------------------------------------*/
2924 static void genPlus (iCode *ic)
2926 int size, offset = 0;
2927 bool pushResult = FALSE;
2930 D(emitcode(";", "genPlus "););
2932 /* special cases :- */
2934 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2935 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2936 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2937 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2943 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR);
2945 /* if literal, literal on the right or
2946 if left requires ACC or right is already
2948 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2949 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2950 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2951 operand *t = IC_RIGHT(ic);
2952 IC_RIGHT(ic) = IC_LEFT(ic);
2956 /* if both left & right are in bit
2958 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2959 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2964 /* if left in bit space & right literal */
2965 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2966 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2967 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2968 /* if result in bit space */
2969 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2970 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2971 emitcode("cpl","c");
2972 outBitC(IC_RESULT(ic));
2974 size = getDataSize(IC_RESULT(ic));
2975 _startLazyDPSEvaluation();
2977 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
2978 emitcode("addc","a,#00");
2979 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2981 _endLazyDPSEvaluation();
2986 /* if I can do an increment instead
2987 of add then GOOD for ME */
2988 if (genPlusIncr (ic) == TRUE)
2992 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
2994 _startLazyDPSEvaluation();
2997 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
2999 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3001 emitcode("add","a,%s",
3002 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3004 emitcode("addc","a,%s",
3005 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3007 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3009 emitcode("add","a,%s",
3010 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3012 emitcode("addc","a,%s",
3013 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3017 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3021 emitcode("push", "acc");
3025 _endLazyDPSEvaluation();
3029 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3031 size = getDataSize(IC_LEFT(ic));
3032 rSize = getDataSize(IC_RESULT(ic));
3034 /* If the pushed data is bigger than the result,
3035 * simply discard unused bytes. Icky, but works.
3037 * Should we throw a warning here? We're losing data...
3039 while (size > rSize)
3041 D(emitcode(";", "discarding unused result byte."););
3042 emitcode("pop", "acc");
3048 emitcode("clr", "a");
3049 /* Conversly, we haven't pushed enough here.
3050 * just zero-pad, and all is well.
3052 while (size < rSize)
3054 emitcode("push", "acc");
3060 _startLazyDPSEvaluation();
3063 emitcode("pop", "acc");
3064 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3066 _endLazyDPSEvaluation();
3069 adjustArithmeticResult(ic);
3072 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3073 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3074 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3077 /*-----------------------------------------------------------------*/
3078 /* genMinusDec :- does subtraction with deccrement if possible */
3079 /*-----------------------------------------------------------------*/
3080 static bool genMinusDec (iCode *ic)
3082 unsigned int icount ;
3083 unsigned int size = getDataSize(IC_RESULT(ic));
3085 /* will try to generate an increment */
3086 /* if the right side is not a literal
3088 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3091 /* if the literal value of the right hand side
3092 is greater than 4 then it is not worth it */
3093 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3096 /* if decrement 16 bits in register */
3097 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3098 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3099 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3106 /* If the next instruction is a goto and the goto target
3107 * is <= 5 instructions previous to this, we can generate
3108 * jumps straight to that target.
3110 if (ic->next && ic->next->op == GOTO
3111 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3112 && labelRange <= 5 )
3114 emitcode(";", "tail decrement optimized (range %d)", labelRange);
3115 tlbl = IC_LABEL(ic->next);
3120 tlbl = newiTempLabel(NULL);
3124 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3125 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3126 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3127 IS_AOP_PREG(IC_RESULT(ic)))
3128 emitcode("cjne","%s,#0xff,%05d$"
3129 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3132 emitcode("mov","a,#0xff");
3133 emitcode("cjne","a,%s,%05d$"
3134 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3137 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3140 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3141 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3142 IS_AOP_PREG(IC_RESULT(ic)))
3143 emitcode("cjne","%s,#0xff,%05d$"
3144 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3147 emitcode("cjne","a,%s,%05d$"
3148 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3151 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3155 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3156 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3157 IS_AOP_PREG(IC_RESULT(ic)))
3158 emitcode("cjne","%s,#0xff,%05d$"
3159 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3162 emitcode("cjne","a,%s,%05d$"
3163 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3166 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3170 emitcode("","%05d$:",tlbl->key+100);
3175 /* if the sizes are greater than 1 then we cannot */
3176 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3177 AOP_SIZE(IC_LEFT(ic)) > 1 )
3180 /* we can if the aops of the left & result match or
3181 if they are in registers and the registers are the
3184 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3185 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3186 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3188 _startLazyDPSEvaluation();
3191 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3193 _endLazyDPSEvaluation();
3201 /*-----------------------------------------------------------------*/
3202 /* addSign - complete with sign */
3203 /*-----------------------------------------------------------------*/
3204 static void addSign(operand *result, int offset, int sign)
3206 int size = (getDataSize(result) - offset);
3209 emitcode("rlc","a");
3210 emitcode("subb","a,acc");
3212 aopPut(AOP(result),"a",offset++);
3215 aopPut(AOP(result),zero,offset++);
3219 /*-----------------------------------------------------------------*/
3220 /* genMinusBits - generates code for subtraction of two bits */
3221 /*-----------------------------------------------------------------*/
3222 static void genMinusBits (iCode *ic)
3224 symbol *lbl = newiTempLabel(NULL);
3226 D(emitcode(";", "genMinusBits "););
3228 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3229 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3230 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3231 emitcode("cpl","c");
3232 emitcode("","%05d$:",(lbl->key+100));
3233 outBitC(IC_RESULT(ic));
3236 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3237 emitcode("subb","a,acc");
3238 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3239 emitcode("inc","a");
3240 emitcode("","%05d$:",(lbl->key+100));
3241 aopPut(AOP(IC_RESULT(ic)),"a",0);
3242 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3246 /*-----------------------------------------------------------------*/
3247 /* genMinus - generates code for subtraction */
3248 /*-----------------------------------------------------------------*/
3249 static void genMinus (iCode *ic)
3251 int size, offset = 0;
3253 unsigned long lit = 0L;
3254 bool pushResult = FALSE;
3256 D(emitcode(";", "genMinus "););
3258 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3259 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3260 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3261 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3267 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3269 /* special cases :- */
3270 /* if both left & right are in bit space */
3271 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3272 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3277 /* if I can do an decrement instead
3278 of subtract then GOOD for ME */
3279 if (genMinusDec (ic) == TRUE)
3284 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3286 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3290 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3295 /* if literal, add a,#-lit, else normal subb */
3296 _startLazyDPSEvaluation();
3298 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3299 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3300 emitcode("subb","a,%s",
3301 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3303 /* first add without previous c */
3305 emitcode("add","a,#0x%02x",
3306 (unsigned int)(lit & 0x0FFL));
3308 emitcode("addc","a,#0x%02x",
3309 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3314 emitcode("push", "acc");
3318 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3322 _endLazyDPSEvaluation();
3326 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3328 size = getDataSize(IC_LEFT(ic));
3329 rSize = getDataSize(IC_RESULT(ic));
3331 /* If the pushed data is bigger than the result,
3332 * simply discard unused bytes. Icky, but works.
3334 * Should we throw a warning here? We're losing data...
3336 while (size > getDataSize(IC_RESULT(ic)))
3338 emitcode(";", "discarding unused result byte.");
3339 emitcode("pop", "acc");
3345 emitcode("clr", "a");
3346 /* Conversly, we haven't pushed enough here.
3347 * just zero-pad, and all is well.
3349 while (size < rSize)
3351 emitcode("push", "acc");
3359 emitcode("pop", "acc");
3360 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3364 adjustArithmeticResult(ic);
3367 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3368 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3369 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3373 /*-----------------------------------------------------------------*/
3374 /* genMultbits :- multiplication of bits */
3375 /*-----------------------------------------------------------------*/
3376 static void genMultbits (operand *left,
3380 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3381 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3386 /*-----------------------------------------------------------------*/
3387 /* genMultOneByte : 8 bit multiplication & division */
3388 /*-----------------------------------------------------------------*/
3389 static void genMultOneByte (operand *left,
3393 link *opetype = operandType(result);
3398 /* (if two literals, the value is computed before) */
3399 /* if one literal, literal on the right */
3400 if (AOP_TYPE(left) == AOP_LIT){
3406 size = AOP_SIZE(result);
3407 /* signed or unsigned */
3408 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3409 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3411 emitcode("mul","ab");
3412 /* if result size = 1, mul signed = mul unsigned */
3413 aopPut(AOP(result),"a",0);
3415 if (SPEC_USIGN(opetype)){
3416 aopPut(AOP(result),"b",1);
3418 /* for filling the MSBs */
3419 emitcode("clr","a");
3422 emitcode("mov","a,b");
3424 /* adjust the MSB if left or right neg */
3426 /* if one literal */
3427 if (AOP_TYPE(right) == AOP_LIT){
3428 /* AND literal negative */
3429 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3430 /* adjust MSB (c==0 after mul) */
3431 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3435 lbl = newiTempLabel(NULL);
3436 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3437 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3438 emitcode("","%05d$:",(lbl->key+100));
3439 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3440 lbl = newiTempLabel(NULL);
3441 emitcode("jc","%05d$",(lbl->key+100));
3442 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3443 emitcode("","%05d$:",(lbl->key+100));
3446 lbl = newiTempLabel(NULL);
3447 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3448 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3449 emitcode("","%05d$:",(lbl->key+100));
3450 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3451 lbl = newiTempLabel(NULL);
3452 emitcode("jc","%05d$",(lbl->key+100));
3453 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3454 emitcode("","%05d$:",(lbl->key+100));
3456 aopPut(AOP(result),"a",1);
3459 emitcode("rlc","a");
3460 emitcode("subb","a,acc");
3467 aopPut(AOP(result),"a",offset++);
3471 /*-----------------------------------------------------------------*/
3472 /* genMult - generates code for multiplication */
3473 /*-----------------------------------------------------------------*/
3474 static void genMult (iCode *ic)
3476 operand *left = IC_LEFT(ic);
3477 operand *right = IC_RIGHT(ic);
3478 operand *result= IC_RESULT(ic);
3480 D(emitcode(";", "genMult "););
3482 /* assign the amsops */
3485 aopOp (left,ic,FALSE, FALSE);
3486 aopOp (right,ic,FALSE, TRUE);
3487 aopOp (result,ic,TRUE, FALSE);
3490 /* special cases first */
3492 if (AOP_TYPE(left) == AOP_CRY &&
3493 AOP_TYPE(right)== AOP_CRY) {
3494 genMultbits(left,right,result);
3498 /* if both are of size == 1 */
3499 if (AOP_SIZE(left) == 1 &&
3500 AOP_SIZE(right) == 1 ) {
3501 genMultOneByte(left,right,result);
3505 /* should have been converted to function call */
3509 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3510 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3511 freeAsmop(result,NULL,ic,TRUE);
3514 /*-----------------------------------------------------------------*/
3515 /* genDivbits :- division of bits */
3516 /*-----------------------------------------------------------------*/
3517 static void genDivbits (operand *left,
3524 /* the result must be bit */
3525 LOAD_AB_FOR_DIV(left, right, l);
3526 emitcode("div","ab");
3527 emitcode("rrc","a");
3528 aopPut(AOP(result),"c",0);
3531 /*-----------------------------------------------------------------*/
3532 /* genDivOneByte : 8 bit division */
3533 /*-----------------------------------------------------------------*/
3534 static void genDivOneByte (operand *left,
3538 link *opetype = operandType(result);
3543 size = AOP_SIZE(result) - 1;
3545 /* signed or unsigned */
3546 if (SPEC_USIGN(opetype)) {
3547 /* unsigned is easy */
3548 LOAD_AB_FOR_DIV(left, right, l);
3549 emitcode("div","ab");
3550 aopPut(AOP(result),"a",0);
3552 aopPut(AOP(result),zero,offset++);
3556 /* signed is a little bit more difficult */
3558 /* save the signs of the operands */
3559 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3561 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3562 emitcode("push","acc"); /* save it on the stack */
3564 /* now sign adjust for both left & right */
3565 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3567 lbl = newiTempLabel(NULL);
3568 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3569 emitcode("cpl","a");
3570 emitcode("inc","a");
3571 emitcode("","%05d$:",(lbl->key+100));
3572 emitcode("mov","b,a");
3574 /* sign adjust left side */
3575 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3578 lbl = newiTempLabel(NULL);
3579 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3580 emitcode("cpl","a");
3581 emitcode("inc","a");
3582 emitcode("","%05d$:",(lbl->key+100));
3584 /* now the division */
3585 emitcode("nop", "; workaround for DS80C390 div bug.");
3586 emitcode("div","ab");
3587 /* we are interested in the lower order
3589 emitcode("mov","b,a");
3590 lbl = newiTempLabel(NULL);
3591 emitcode("pop","acc");
3592 /* if there was an over flow we don't
3593 adjust the sign of the result */
3594 emitcode("jb","ov,%05d$",(lbl->key+100));
3595 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3597 emitcode("clr","a");
3598 emitcode("subb","a,b");
3599 emitcode("mov","b,a");
3600 emitcode("","%05d$:",(lbl->key+100));
3602 /* now we are done */
3603 aopPut(AOP(result),"b",0);
3605 emitcode("mov","c,b.7");
3606 emitcode("subb","a,acc");
3609 aopPut(AOP(result),"a",offset++);
3613 /*-----------------------------------------------------------------*/
3614 /* genDiv - generates code for division */
3615 /*-----------------------------------------------------------------*/
3616 static void genDiv (iCode *ic)
3618 operand *left = IC_LEFT(ic);
3619 operand *right = IC_RIGHT(ic);
3620 operand *result= IC_RESULT(ic);
3622 D(emitcode(";", "genDiv "););
3624 /* assign the amsops */
3627 aopOp (left,ic,FALSE, FALSE);
3628 aopOp (right,ic,FALSE, TRUE);
3629 aopOp (result,ic,TRUE, FALSE);
3632 /* special cases first */
3634 if (AOP_TYPE(left) == AOP_CRY &&
3635 AOP_TYPE(right)== AOP_CRY) {
3636 genDivbits(left,right,result);
3640 /* if both are of size == 1 */
3641 if (AOP_SIZE(left) == 1 &&
3642 AOP_SIZE(right) == 1 ) {
3643 genDivOneByte(left,right,result);
3647 /* should have been converted to function call */
3650 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3651 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3652 freeAsmop(result,NULL,ic,TRUE);
3655 /*-----------------------------------------------------------------*/
3656 /* genModbits :- modulus of bits */
3657 /*-----------------------------------------------------------------*/
3658 static void genModbits (operand *left,
3665 /* the result must be bit */
3666 LOAD_AB_FOR_DIV(left, right, l);
3667 emitcode("div","ab");
3668 emitcode("mov","a,b");
3669 emitcode("rrc","a");
3670 aopPut(AOP(result),"c",0);
3673 /*-----------------------------------------------------------------*/
3674 /* genModOneByte : 8 bit modulus */
3675 /*-----------------------------------------------------------------*/
3676 static void genModOneByte (operand *left,
3680 link *opetype = operandType(result);
3684 /* signed or unsigned */
3685 if (SPEC_USIGN(opetype)) {
3686 /* unsigned is easy */
3687 LOAD_AB_FOR_DIV(left, right, l);
3688 emitcode("div","ab");
3689 aopPut(AOP(result),"b",0);
3693 /* signed is a little bit more difficult */
3695 /* save the signs of the operands */
3696 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3699 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3700 emitcode("push","acc"); /* save it on the stack */
3702 /* now sign adjust for both left & right */
3703 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3706 lbl = newiTempLabel(NULL);
3707 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3708 emitcode("cpl","a");
3709 emitcode("inc","a");
3710 emitcode("","%05d$:",(lbl->key+100));
3711 emitcode("mov","b,a");
3713 /* sign adjust left side */
3714 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3717 lbl = newiTempLabel(NULL);
3718 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3719 emitcode("cpl","a");
3720 emitcode("inc","a");
3721 emitcode("","%05d$:",(lbl->key+100));
3723 /* now the multiplication */
3724 emitcode("nop", "; workaround for DS80C390 div bug.");
3725 emitcode("div","ab");
3726 /* we are interested in the lower order
3728 lbl = newiTempLabel(NULL);
3729 emitcode("pop","acc");
3730 /* if there was an over flow we don't
3731 adjust the sign of the result */
3732 emitcode("jb","ov,%05d$",(lbl->key+100));
3733 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3735 emitcode("clr","a");
3736 emitcode("subb","a,b");
3737 emitcode("mov","b,a");
3738 emitcode("","%05d$:",(lbl->key+100));
3740 /* now we are done */
3741 aopPut(AOP(result),"b",0);
3745 /*-----------------------------------------------------------------*/
3746 /* genMod - generates code for division */
3747 /*-----------------------------------------------------------------*/
3748 static void genMod (iCode *ic)
3750 operand *left = IC_LEFT(ic);
3751 operand *right = IC_RIGHT(ic);
3752 operand *result= IC_RESULT(ic);
3754 D(emitcode(";", "genMod "););
3756 /* assign the amsops */
3759 aopOp (left,ic,FALSE, FALSE);
3760 aopOp (right,ic,FALSE, TRUE);
3761 aopOp (result,ic,TRUE, FALSE);
3764 /* special cases first */
3766 if (AOP_TYPE(left) == AOP_CRY &&
3767 AOP_TYPE(right)== AOP_CRY) {
3768 genModbits(left,right,result);
3772 /* if both are of size == 1 */
3773 if (AOP_SIZE(left) == 1 &&
3774 AOP_SIZE(right) == 1 ) {
3775 genModOneByte(left,right,result);
3779 /* should have been converted to function call */
3783 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3784 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3785 freeAsmop(result,NULL,ic,TRUE);
3788 /*-----------------------------------------------------------------*/
3789 /* genIfxJump :- will create a jump depending on the ifx */
3790 /*-----------------------------------------------------------------*/
3791 static void genIfxJump (iCode *ic, char *jval)
3794 symbol *tlbl = newiTempLabel(NULL);
3797 D(emitcode(";", "genIfxJump "););
3799 /* if true label then we jump if condition
3801 if ( IC_TRUE(ic) ) {
3803 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3804 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3807 /* false label is present */
3808 jlbl = IC_FALSE(ic) ;
3809 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3810 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3812 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3813 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3815 emitcode(inst,"%05d$",tlbl->key+100);
3816 emitcode("ljmp","%05d$",jlbl->key+100);
3817 emitcode("","%05d$:",tlbl->key+100);
3819 /* mark the icode as generated */
3823 /*-----------------------------------------------------------------*/
3824 /* genCmp :- greater or less than comparison */
3825 /*-----------------------------------------------------------------*/
3826 static void genCmp (operand *left,operand *right,
3827 operand *result, iCode *ifx, int sign)
3829 int size, offset = 0 ;
3830 unsigned long lit = 0L;
3831 bool swappedOps = FALSE;
3833 D(emitcode(";", "genCmp"););
3836 /* If left if lit and right isn't, swap 'em. */
3837 if (AOP_TYPE(left) == AOP_LIT &&
3838 AOP_TYPE(right) != AOP_LIT)
3840 operand *tmp = left;
3843 D(emitcode(";", "kevin literal hack"););
3844 swappedOps = !swappedOps;
3847 if (AOP_NEEDSACC(right))
3849 if (AOP_NEEDSACC(left))
3851 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3852 "both CMP operands need ACC!");
3857 operand *tmp = left;
3860 D(emitcode(";", "kevin ACC hack"););
3861 swappedOps = !swappedOps;
3866 /* if left & right are bit variables */
3867 if (AOP_TYPE(left) == AOP_CRY &&
3868 AOP_TYPE(right) == AOP_CRY ) {
3869 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3870 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3872 /* subtract right from left if at the
3873 end the carry flag is set then we know that
3874 left is greater than right */
3875 size = max(AOP_SIZE(left),AOP_SIZE(right));
3877 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3878 if((size == 1) && !sign &&
3879 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3880 symbol *lbl = newiTempLabel(NULL);
3881 emitcode("cjne","%s,%s,%05d$",
3882 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3883 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3885 emitcode("","%05d$:",lbl->key+100);
3887 if(AOP_TYPE(right) == AOP_LIT){
3888 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3889 /* optimize if(x < 0) or if(x >= 0) */
3895 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3896 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3897 genIfxJump (ifx,"acc.7");
3901 emitcode("rlc","a");
3909 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3910 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3911 emitcode(";", "genCmp #2");
3912 if (sign && (size == 0))
3914 emitcode(";", "genCmp #3");
3915 emitcode("xrl","a,#0x80");
3916 if (AOP_TYPE(right) == AOP_LIT)
3918 unsigned long lit = (unsigned long)
3919 floatFromVal(AOP(right)->aopu.aop_lit);
3920 emitcode(";", "genCmp #3.1");
3921 emitcode("subb","a,#0x%02x",
3922 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3926 emitcode(";", "genCmp #3.2");
3927 if (AOP_NEEDSACC(right))
3929 emitcode("push", "acc");
3931 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3932 FALSE,FALSE,FALSE));
3933 emitcode("xrl","b,#0x80");
3934 if (AOP_NEEDSACC(right))
3936 emitcode("pop", "acc");
3938 emitcode("subb","a,b");
3945 emitcode(";", "genCmp #4");
3946 if (AOP_NEEDSACC(right))
3949 emitcode(";", "genCmp #4.1");
3950 emitcode("xch", "a, b");
3951 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3952 emitcode("xch", "a, b");
3957 emitcode(";", "genCmp #4.2");
3958 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
3961 emitcode("subb","a,%s",s);
3970 D(emitcode(";","kevHack: flip carry."););
3971 emitcode("cpl", "c");
3974 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3977 /* if the result is used in the next
3978 ifx conditional branch then generate
3979 code a little differently */
3981 genIfxJump (ifx,"c");
3984 /* leave the result in acc */
3988 /*-----------------------------------------------------------------*/
3989 /* genCmpGt :- greater than comparison */
3990 /*-----------------------------------------------------------------*/
3991 static void genCmpGt (iCode *ic, iCode *ifx)
3993 operand *left, *right, *result;
3994 link *letype , *retype;
3997 D(emitcode(";", "genCmpGt "););
4000 right= IC_RIGHT(ic);
4001 result = IC_RESULT(ic);
4003 letype = getSpec(operandType(left));
4004 retype =getSpec(operandType(right));
4005 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4006 /* assign the amsops */
4009 aopOp (left,ic,FALSE, TRUE);
4010 aopOp (right,ic,FALSE, FALSE);
4011 aopOp (result,ic,TRUE, FALSE);
4014 genCmp(right, left, result, ifx, sign);
4016 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4017 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4018 freeAsmop(result,NULL,ic,TRUE);
4021 /*-----------------------------------------------------------------*/
4022 /* genCmpLt - less than comparisons */
4023 /*-----------------------------------------------------------------*/
4024 static void genCmpLt (iCode *ic, iCode *ifx)
4026 operand *left, *right, *result;
4027 link *letype , *retype;
4030 D(emitcode(";", "genCmpLt "););
4033 right= IC_RIGHT(ic);
4034 result = IC_RESULT(ic);
4036 letype = getSpec(operandType(left));
4037 retype =getSpec(operandType(right));
4038 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4040 /* assign the amsops */
4043 aopOp (left,ic,FALSE, FALSE);
4044 aopOp (right,ic,FALSE, TRUE);
4045 aopOp (result,ic,TRUE, FALSE);
4048 genCmp(left, right, result, ifx, sign);
4050 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4051 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4052 freeAsmop(result,NULL,ic,TRUE);
4055 /*-----------------------------------------------------------------*/
4056 /* gencjneshort - compare and jump if not equal */
4057 /*-----------------------------------------------------------------*/
4058 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4060 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4062 unsigned long lit = 0L;
4064 D(emitcode(";", "gencjneshort"););
4066 /* if the left side is a literal or
4067 if the right is in a pointer register and left
4069 if ((AOP_TYPE(left) == AOP_LIT) ||
4070 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4076 if(AOP_TYPE(right) == AOP_LIT)
4077 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4079 if (opIsGptr(left) || opIsGptr(right))
4081 /* We are comparing a generic pointer to something.
4082 * Exclude the generic type byte from the comparison.
4085 D(emitcode(";", "cjneshort: generic ptr special case.");)
4089 /* if the right side is a literal then anything goes */
4090 if (AOP_TYPE(right) == AOP_LIT &&
4091 AOP_TYPE(left) != AOP_DIR ) {
4093 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4095 emitcode("cjne","a,%s,%05d$",
4096 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4102 /* if the right side is in a register or in direct space or
4103 if the left is a pointer register & right is not */
4104 else if (AOP_TYPE(right) == AOP_REG ||
4105 AOP_TYPE(right) == AOP_DIR ||
4106 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4107 (IS_AOP_PREG(left) && !IS_AOP_PREG(right)))
4111 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4112 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4113 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4114 emitcode("jnz","%05d$",lbl->key+100);
4116 emitcode("cjne","a,%s,%05d$",
4117 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4122 /* right is a pointer reg need both a & b */
4124 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4126 emitcode("mov","b,%s",l);
4127 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4128 emitcode("cjne","a,b,%05d$",lbl->key+100);
4134 /*-----------------------------------------------------------------*/
4135 /* gencjne - compare and jump if not equal */
4136 /*-----------------------------------------------------------------*/
4137 static void gencjne(operand *left, operand *right, symbol *lbl)
4139 symbol *tlbl = newiTempLabel(NULL);
4141 D(emitcode(";", "gencjne"););
4143 gencjneshort(left, right, lbl);
4145 emitcode("mov","a,%s",one);
4146 emitcode("sjmp","%05d$",tlbl->key+100);
4147 emitcode("","%05d$:",lbl->key+100);
4148 emitcode("clr","a");
4149 emitcode("","%05d$:",tlbl->key+100);
4152 /*-----------------------------------------------------------------*/
4153 /* genCmpEq - generates code for equal to */
4154 /*-----------------------------------------------------------------*/
4155 static void genCmpEq (iCode *ic, iCode *ifx)
4157 operand *left, *right, *result;
4159 D(emitcode(";", "genCmpEq "););
4164 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4165 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4166 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4169 /* if literal, literal on the right or
4170 if the right is in a pointer register and left
4172 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4173 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4174 operand *t = IC_RIGHT(ic);
4175 IC_RIGHT(ic) = IC_LEFT(ic);
4179 if(ifx && !AOP_SIZE(result)){
4181 /* if they are both bit variables */
4182 if (AOP_TYPE(left) == AOP_CRY &&
4183 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4184 if(AOP_TYPE(right) == AOP_LIT){
4185 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4187 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4188 emitcode("cpl","c");
4189 } else if(lit == 1L) {
4190 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4192 emitcode("clr","c");
4194 /* AOP_TYPE(right) == AOP_CRY */
4196 symbol *lbl = newiTempLabel(NULL);
4197 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4198 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4199 emitcode("cpl","c");
4200 emitcode("","%05d$:",(lbl->key+100));
4202 /* if true label then we jump if condition
4204 tlbl = newiTempLabel(NULL);
4205 if ( IC_TRUE(ifx) ) {
4206 emitcode("jnc","%05d$",tlbl->key+100);
4207 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4209 emitcode("jc","%05d$",tlbl->key+100);
4210 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4212 emitcode("","%05d$:",tlbl->key+100);
4214 tlbl = newiTempLabel(NULL);
4215 gencjneshort(left, right, tlbl);
4216 if ( IC_TRUE(ifx) ) {
4217 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4218 emitcode("","%05d$:",tlbl->key+100);
4220 symbol *lbl = newiTempLabel(NULL);
4221 emitcode("sjmp","%05d$",lbl->key+100);
4222 emitcode("","%05d$:",tlbl->key+100);
4223 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4224 emitcode("","%05d$:",lbl->key+100);
4227 /* mark the icode as generated */
4232 /* if they are both bit variables */
4233 if (AOP_TYPE(left) == AOP_CRY &&
4234 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4235 if(AOP_TYPE(right) == AOP_LIT){
4236 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4238 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4239 emitcode("cpl","c");
4240 } else if(lit == 1L) {
4241 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4243 emitcode("clr","c");
4245 /* AOP_TYPE(right) == AOP_CRY */
4247 symbol *lbl = newiTempLabel(NULL);
4248 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4249 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4250 emitcode("cpl","c");
4251 emitcode("","%05d$:",(lbl->key+100));
4254 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4259 genIfxJump (ifx,"c");
4262 /* if the result is used in an arithmetic operation
4263 then put the result in place */
4266 gencjne(left,right,newiTempLabel(NULL));
4267 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4268 aopPut(AOP(result),"a",0);
4272 genIfxJump (ifx,"a");
4275 /* if the result is used in an arithmetic operation
4276 then put the result in place */
4277 if (AOP_TYPE(result) != AOP_CRY)
4279 /* leave the result in acc */
4283 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4284 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4285 freeAsmop(result,NULL,ic,TRUE);
4288 /*-----------------------------------------------------------------*/
4289 /* ifxForOp - returns the icode containing the ifx for operand */
4290 /*-----------------------------------------------------------------*/
4291 static iCode *ifxForOp ( operand *op, iCode *ic )
4293 /* if true symbol then needs to be assigned */
4294 if (IS_TRUE_SYMOP(op))
4297 /* if this has register type condition and
4298 the next instruction is ifx with the same operand
4299 and live to of the operand is upto the ifx only then */
4301 ic->next->op == IFX &&
4302 IC_COND(ic->next)->key == op->key &&
4303 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4308 /*-----------------------------------------------------------------*/
4309 /* genAndOp - for && operation */
4310 /*-----------------------------------------------------------------*/
4311 static void genAndOp (iCode *ic)
4313 operand *left,*right, *result;
4316 D(emitcode(";", "genAndOp "););
4318 /* note here that && operations that are in an
4319 if statement are taken away by backPatchLabels
4320 only those used in arthmetic operations remain */
4324 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4325 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4326 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4329 /* if both are bit variables */
4330 if (AOP_TYPE(left) == AOP_CRY &&
4331 AOP_TYPE(right) == AOP_CRY ) {
4332 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4333 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4336 tlbl = newiTempLabel(NULL);
4338 emitcode("jz","%05d$",tlbl->key+100);
4340 emitcode("","%05d$:",tlbl->key+100);
4344 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4345 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4346 freeAsmop(result,NULL,ic,TRUE);
4350 /*-----------------------------------------------------------------*/
4351 /* genOrOp - for || operation */
4352 /*-----------------------------------------------------------------*/
4353 static void genOrOp (iCode *ic)
4355 operand *left,*right, *result;
4358 D(emitcode(";", "genOrOp "););
4360 /* note here that || operations that are in an
4361 if statement are taken away by backPatchLabels
4362 only those used in arthmetic operations remain */
4366 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4367 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4368 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4371 /* if both are bit variables */
4372 if (AOP_TYPE(left) == AOP_CRY &&
4373 AOP_TYPE(right) == AOP_CRY ) {
4374 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4375 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4378 tlbl = newiTempLabel(NULL);
4380 emitcode("jnz","%05d$",tlbl->key+100);
4382 emitcode("","%05d$:",tlbl->key+100);
4386 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4387 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4388 freeAsmop(result,NULL,ic,TRUE);
4391 /*-----------------------------------------------------------------*/
4392 /* isLiteralBit - test if lit == 2^n */
4393 /*-----------------------------------------------------------------*/
4394 static int isLiteralBit(unsigned long lit)
4396 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4397 0x100L,0x200L,0x400L,0x800L,
4398 0x1000L,0x2000L,0x4000L,0x8000L,
4399 0x10000L,0x20000L,0x40000L,0x80000L,
4400 0x100000L,0x200000L,0x400000L,0x800000L,
4401 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4402 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4405 for(idx = 0; idx < 32; idx++)
4411 /*-----------------------------------------------------------------*/
4412 /* continueIfTrue - */
4413 /*-----------------------------------------------------------------*/
4414 static void continueIfTrue (iCode *ic)
4417 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4421 /*-----------------------------------------------------------------*/
4423 /*-----------------------------------------------------------------*/
4424 static void jumpIfTrue (iCode *ic)
4427 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4431 /*-----------------------------------------------------------------*/
4432 /* jmpTrueOrFalse - */
4433 /*-----------------------------------------------------------------*/
4434 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4436 // ugly but optimized by peephole
4438 symbol *nlbl = newiTempLabel(NULL);
4439 emitcode("sjmp","%05d$",nlbl->key+100);
4440 emitcode("","%05d$:",tlbl->key+100);
4441 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4442 emitcode("","%05d$:",nlbl->key+100);
4445 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4446 emitcode("","%05d$:",tlbl->key+100);
4451 /*-----------------------------------------------------------------*/
4452 /* genAnd - code for and */
4453 /*-----------------------------------------------------------------*/
4454 static void genAnd (iCode *ic, iCode *ifx)
4456 operand *left, *right, *result;
4458 unsigned long lit = 0L;
4462 D(emitcode(";", "genAnd "););
4467 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4468 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4469 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4473 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4475 AOP_TYPE(left), AOP_TYPE(right));
4476 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4478 AOP_SIZE(left), AOP_SIZE(right));
4481 /* if left is a literal & right is not then exchange them */
4482 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4483 AOP_NEEDSACC(left)) {
4484 operand *tmp = right ;
4489 /* if result = right then exchange them */
4490 if(sameRegs(AOP(result),AOP(right))){
4491 operand *tmp = right ;
4496 /* if right is bit then exchange them */
4497 if (AOP_TYPE(right) == AOP_CRY &&
4498 AOP_TYPE(left) != AOP_CRY){
4499 operand *tmp = right ;
4503 if(AOP_TYPE(right) == AOP_LIT)
4504 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4506 size = AOP_SIZE(result);
4509 // result = bit & yy;
4510 if (AOP_TYPE(left) == AOP_CRY){
4511 // c = bit & literal;
4512 if(AOP_TYPE(right) == AOP_LIT){
4514 if(size && sameRegs(AOP(result),AOP(left)))
4517 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4520 if(size && (AOP_TYPE(result) == AOP_CRY)){
4521 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4524 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4528 emitcode("clr","c");
4531 if (AOP_TYPE(right) == AOP_CRY){
4533 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4534 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4537 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4539 emitcode("rrc","a");
4540 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4548 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4549 genIfxJump(ifx, "c");
4553 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4554 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4555 if((AOP_TYPE(right) == AOP_LIT) &&
4556 (AOP_TYPE(result) == AOP_CRY) &&
4557 (AOP_TYPE(left) != AOP_CRY)){
4558 int posbit = isLiteralBit(lit);
4562 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4565 emitcode("mov","c,acc.%d",posbit&0x07);
4569 sprintf(buffer,"acc.%d",posbit&0x07);
4570 genIfxJump(ifx, buffer);
4575 symbol *tlbl = newiTempLabel(NULL);
4576 int sizel = AOP_SIZE(left);
4578 emitcode("setb","c");
4580 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4581 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4583 if((posbit = isLiteralBit(bytelit)) != 0)
4584 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4586 if(bytelit != 0x0FFL)
4587 emitcode("anl","a,%s",
4588 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4589 emitcode("jnz","%05d$",tlbl->key+100);
4594 // bit = left & literal
4596 emitcode("clr","c");
4597 emitcode("","%05d$:",tlbl->key+100);
4599 // if(left & literal)
4602 jmpTrueOrFalse(ifx, tlbl);
4610 /* if left is same as result */
4611 if(sameRegs(AOP(result),AOP(left))){
4612 for(;size--; offset++) {
4613 if(AOP_TYPE(right) == AOP_LIT){
4614 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4618 aopPut(AOP(result),zero,offset);
4620 if (IS_AOP_PREG(result)) {
4621 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4622 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4623 aopPut(AOP(result),"a",offset);
4625 emitcode("anl","%s,%s",
4626 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4627 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4629 if (AOP_TYPE(left) == AOP_ACC)
4630 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4632 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4633 if (IS_AOP_PREG(result)) {
4634 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4635 aopPut(AOP(result),"a",offset);
4638 emitcode("anl","%s,a",
4639 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4644 // left & result in different registers
4645 if(AOP_TYPE(result) == AOP_CRY){
4647 // if(size), result in bit
4648 // if(!size && ifx), conditional oper: if(left & right)
4649 symbol *tlbl = newiTempLabel(NULL);
4650 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4652 emitcode("setb","c");
4654 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4655 emitcode("anl","a,%s",
4656 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4657 emitcode("jnz","%05d$",tlbl->key+100);
4662 emitcode("","%05d$:",tlbl->key+100);
4665 jmpTrueOrFalse(ifx, tlbl);
4667 for(;(size--);offset++) {
4669 // result = left & right
4670 if(AOP_TYPE(right) == AOP_LIT){
4671 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4673 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4676 } else if(bytelit == 0){
4677 aopPut(AOP(result),zero,offset);
4681 // faster than result <- left, anl result,right
4682 // and better if result is SFR
4683 if (AOP_TYPE(left) == AOP_ACC)
4684 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4686 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4687 emitcode("anl","a,%s",
4688 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4690 aopPut(AOP(result),"a",offset);
4696 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4697 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4698 freeAsmop(result,NULL,ic,TRUE);
4701 /*-----------------------------------------------------------------*/
4702 /* genOr - code for or */
4703 /*-----------------------------------------------------------------*/
4704 static void genOr (iCode *ic, iCode *ifx)
4706 operand *left, *right, *result;
4708 unsigned long lit = 0L;
4710 D(emitcode(";", "genOr "););
4715 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4716 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4717 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4721 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4723 AOP_TYPE(left), AOP_TYPE(right));
4724 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4726 AOP_SIZE(left), AOP_SIZE(right));
4729 /* if left is a literal & right is not then exchange them */
4730 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4731 AOP_NEEDSACC(left)) {
4732 operand *tmp = right ;
4737 /* if result = right then exchange them */
4738 if(sameRegs(AOP(result),AOP(right))){
4739 operand *tmp = right ;
4744 /* if right is bit then exchange them */
4745 if (AOP_TYPE(right) == AOP_CRY &&
4746 AOP_TYPE(left) != AOP_CRY){
4747 operand *tmp = right ;
4751 if(AOP_TYPE(right) == AOP_LIT)
4752 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4754 size = AOP_SIZE(result);
4758 if (AOP_TYPE(left) == AOP_CRY){
4759 if(AOP_TYPE(right) == AOP_LIT){
4760 // c = bit & literal;
4762 // lit != 0 => result = 1
4763 if(AOP_TYPE(result) == AOP_CRY){
4765 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4767 continueIfTrue(ifx);
4770 emitcode("setb","c");
4772 // lit == 0 => result = left
4773 if(size && sameRegs(AOP(result),AOP(left)))
4775 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4778 if (AOP_TYPE(right) == AOP_CRY){
4780 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4781 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4785 symbol *tlbl = newiTempLabel(NULL);
4786 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4787 emitcode("setb","c");
4788 emitcode("jb","%s,%05d$",
4789 AOP(left)->aopu.aop_dir,tlbl->key+100);
4791 emitcode("jnz","%05d$",tlbl->key+100);
4792 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4793 jmpTrueOrFalse(ifx, tlbl);
4797 emitcode("","%05d$:",tlbl->key+100);
4806 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4807 genIfxJump(ifx, "c");
4811 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4812 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4813 if((AOP_TYPE(right) == AOP_LIT) &&
4814 (AOP_TYPE(result) == AOP_CRY) &&
4815 (AOP_TYPE(left) != AOP_CRY)){
4819 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4821 continueIfTrue(ifx);
4824 // lit = 0, result = boolean(left)
4826 emitcode("setb","c");
4829 symbol *tlbl = newiTempLabel(NULL);
4830 emitcode("jnz","%05d$",tlbl->key+100);
4832 emitcode("","%05d$:",tlbl->key+100);
4834 genIfxJump (ifx,"a");
4842 /* if left is same as result */
4843 if(sameRegs(AOP(result),AOP(left))){
4844 for(;size--; offset++) {
4845 if(AOP_TYPE(right) == AOP_LIT){
4846 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4849 if (IS_AOP_PREG(left)) {
4850 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4851 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4852 aopPut(AOP(result),"a",offset);
4854 emitcode("orl","%s,%s",
4855 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4856 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4858 if (AOP_TYPE(left) == AOP_ACC)
4859 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4861 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4862 if (IS_AOP_PREG(left)) {
4863 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4864 aopPut(AOP(result),"a",offset);
4866 emitcode("orl","%s,a",
4867 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4872 // left & result in different registers
4873 if(AOP_TYPE(result) == AOP_CRY){
4875 // if(size), result in bit
4876 // if(!size && ifx), conditional oper: if(left | right)
4877 symbol *tlbl = newiTempLabel(NULL);
4878 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4880 emitcode("setb","c");
4882 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4883 emitcode("orl","a,%s",
4884 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4885 emitcode("jnz","%05d$",tlbl->key+100);
4890 emitcode("","%05d$:",tlbl->key+100);
4893 jmpTrueOrFalse(ifx, tlbl);
4894 } else for(;(size--);offset++){
4896 // result = left & right
4897 if(AOP_TYPE(right) == AOP_LIT){
4898 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4900 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4905 // faster than result <- left, anl result,right
4906 // and better if result is SFR
4907 if (AOP_TYPE(left) == AOP_ACC)
4908 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4910 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4911 emitcode("orl","a,%s",
4912 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4914 aopPut(AOP(result),"a",offset);
4919 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4920 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4921 freeAsmop(result,NULL,ic,TRUE);
4924 /*-----------------------------------------------------------------*/
4925 /* genXor - code for xclusive or */
4926 /*-----------------------------------------------------------------*/
4927 static void genXor (iCode *ic, iCode *ifx)
4929 operand *left, *right, *result;
4931 unsigned long lit = 0L;
4933 D(emitcode(";", "genXor "););
4938 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4939 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4940 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4944 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4946 AOP_TYPE(left), AOP_TYPE(right));
4947 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4949 AOP_SIZE(left), AOP_SIZE(right));
4952 /* if left is a literal & right is not ||
4953 if left needs acc & right does not */
4954 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4955 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4956 operand *tmp = right ;
4961 /* if result = right then exchange them */
4962 if(sameRegs(AOP(result),AOP(right))){
4963 operand *tmp = right ;
4968 /* if right is bit then exchange them */
4969 if (AOP_TYPE(right) == AOP_CRY &&
4970 AOP_TYPE(left) != AOP_CRY){
4971 operand *tmp = right ;
4975 if(AOP_TYPE(right) == AOP_LIT)
4976 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4978 size = AOP_SIZE(result);
4982 if (AOP_TYPE(left) == AOP_CRY){
4983 if(AOP_TYPE(right) == AOP_LIT){
4984 // c = bit & literal;
4986 // lit>>1 != 0 => result = 1
4987 if(AOP_TYPE(result) == AOP_CRY){
4989 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4991 continueIfTrue(ifx);
4994 emitcode("setb","c");
4998 // lit == 0, result = left
4999 if(size && sameRegs(AOP(result),AOP(left)))
5001 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5003 // lit == 1, result = not(left)
5004 if(size && sameRegs(AOP(result),AOP(left))){
5005 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5008 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5009 emitcode("cpl","c");
5016 symbol *tlbl = newiTempLabel(NULL);
5017 if (AOP_TYPE(right) == AOP_CRY){
5019 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5022 int sizer = AOP_SIZE(right);
5024 // if val>>1 != 0, result = 1
5025 emitcode("setb","c");
5027 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5029 // test the msb of the lsb
5030 emitcode("anl","a,#0xfe");
5031 emitcode("jnz","%05d$",tlbl->key+100);
5035 emitcode("rrc","a");
5037 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5038 emitcode("cpl","c");
5039 emitcode("","%05d$:",(tlbl->key+100));
5046 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5047 genIfxJump(ifx, "c");
5051 if(sameRegs(AOP(result),AOP(left))){
5052 /* if left is same as result */
5053 for(;size--; offset++) {
5054 if(AOP_TYPE(right) == AOP_LIT){
5055 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5058 if (IS_AOP_PREG(left)) {
5059 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5060 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5061 aopPut(AOP(result),"a",offset);
5063 emitcode("xrl","%s,%s",
5064 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5065 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5067 if (AOP_TYPE(left) == AOP_ACC)
5068 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5070 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5071 if (IS_AOP_PREG(left)) {
5072 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5073 aopPut(AOP(result),"a",offset);
5075 emitcode("xrl","%s,a",
5076 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5081 // left & result in different registers
5082 if(AOP_TYPE(result) == AOP_CRY){
5084 // if(size), result in bit
5085 // if(!size && ifx), conditional oper: if(left ^ right)
5086 symbol *tlbl = newiTempLabel(NULL);
5087 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5089 emitcode("setb","c");
5091 if((AOP_TYPE(right) == AOP_LIT) &&
5092 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5093 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5095 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5096 emitcode("xrl","a,%s",
5097 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5099 emitcode("jnz","%05d$",tlbl->key+100);
5104 emitcode("","%05d$:",tlbl->key+100);
5107 jmpTrueOrFalse(ifx, tlbl);
5108 } else for(;(size--);offset++){
5110 // result = left & right
5111 if(AOP_TYPE(right) == AOP_LIT){
5112 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
5114 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5119 // faster than result <- left, anl result,right
5120 // and better if result is SFR
5121 if (AOP_TYPE(left) == AOP_ACC)
5122 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5124 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5125 emitcode("xrl","a,%s",
5126 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5128 aopPut(AOP(result),"a",offset);
5133 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5134 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5135 freeAsmop(result,NULL,ic,TRUE);
5138 /*-----------------------------------------------------------------*/
5139 /* genInline - write the inline code out */
5140 /*-----------------------------------------------------------------*/
5141 static void genInline (iCode *ic)
5143 char buffer[MAX_INLINEASM];
5147 D(emitcode(";", "genInline "););
5149 _G.inLine += (!options.asmpeep);
5150 strcpy(buffer,IC_INLINE(ic));
5152 /* emit each line as a code */
5171 /* emitcode("",buffer); */
5172 _G.inLine -= (!options.asmpeep);
5175 /*-----------------------------------------------------------------*/
5176 /* genRRC - rotate right with carry */
5177 /*-----------------------------------------------------------------*/
5178 static void genRRC (iCode *ic)
5180 operand *left , *result ;
5181 int size, offset = 0;
5184 D(emitcode(";", "genRRC "););
5186 /* rotate right with carry */
5188 result=IC_RESULT(ic);
5189 aopOp (left,ic,FALSE, FALSE);
5190 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5192 /* move it to the result */
5193 size = AOP_SIZE(result);
5197 _startLazyDPSEvaluation();
5199 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5201 emitcode("rrc","a");
5202 if (AOP_SIZE(result) > 1)
5203 aopPut(AOP(result),"a",offset--);
5205 _endLazyDPSEvaluation();
5207 /* now we need to put the carry into the
5208 highest order byte of the result */
5209 if (AOP_SIZE(result) > 1) {
5210 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5213 emitcode("mov","acc.7,c");
5214 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5215 freeAsmop(left,NULL,ic,TRUE);
5216 freeAsmop(result,NULL,ic,TRUE);
5219 /*-----------------------------------------------------------------*/
5220 /* genRLC - generate code for rotate left with carry */
5221 /*-----------------------------------------------------------------*/
5222 static void genRLC (iCode *ic)
5224 operand *left , *result ;
5225 int size, offset = 0;
5228 D(emitcode(";", "genRLC "););
5230 /* rotate right with carry */
5232 result=IC_RESULT(ic);
5233 aopOp (left,ic,FALSE, FALSE);
5234 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5236 /* move it to the result */
5237 size = AOP_SIZE(result);
5240 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5242 emitcode("add","a,acc");
5243 if (AOP_SIZE(result) > 1)
5245 aopPut(AOP(result),"a",offset++);
5248 _startLazyDPSEvaluation();
5250 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5252 emitcode("rlc","a");
5253 if (AOP_SIZE(result) > 1)
5254 aopPut(AOP(result),"a",offset++);
5256 _endLazyDPSEvaluation();
5258 /* now we need to put the carry into the
5259 highest order byte of the result */
5260 if (AOP_SIZE(result) > 1) {
5261 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5264 emitcode("mov","acc.0,c");
5265 aopPut(AOP(result),"a",0);
5266 freeAsmop(left,NULL,ic,TRUE);
5267 freeAsmop(result,NULL,ic,TRUE);
5270 /*-----------------------------------------------------------------*/
5271 /* genGetHbit - generates code get highest order bit */
5272 /*-----------------------------------------------------------------*/
5273 static void genGetHbit (iCode *ic)
5275 operand *left, *result;
5277 result=IC_RESULT(ic);
5278 aopOp (left,ic,FALSE, FALSE);
5279 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5281 D(emitcode(";", "genGetHbit "););
5283 /* get the highest order byte into a */
5284 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5285 if(AOP_TYPE(result) == AOP_CRY){
5286 emitcode("rlc","a");
5291 emitcode("anl","a,#0x01");
5296 freeAsmop(left,NULL,ic,TRUE);
5297 freeAsmop(result,NULL,ic,TRUE);
5300 /*-----------------------------------------------------------------*/
5301 /* AccRol - rotate left accumulator by known count */
5302 /*-----------------------------------------------------------------*/
5303 static void AccRol (int shCount)
5305 shCount &= 0x0007; // shCount : 0..7
5317 emitcode("swap","a");
5321 emitcode("swap","a");
5324 emitcode("swap","a");
5337 /*-----------------------------------------------------------------*/
5338 /* AccLsh - left shift accumulator by known count */
5339 /*-----------------------------------------------------------------*/
5340 static void AccLsh (int shCount)
5344 emitcode("add","a,acc");
5347 emitcode("add","a,acc");
5348 emitcode("add","a,acc");
5350 /* rotate left accumulator */
5352 /* and kill the lower order bits */
5353 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5358 /*-----------------------------------------------------------------*/
5359 /* AccRsh - right shift accumulator by known count */
5360 /*-----------------------------------------------------------------*/
5361 static void AccRsh (int shCount)
5366 emitcode("rrc","a");
5368 /* rotate right accumulator */
5369 AccRol(8 - shCount);
5370 /* and kill the higher order bits */
5371 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5376 /*-----------------------------------------------------------------*/
5377 /* AccSRsh - signed right shift accumulator by known count */
5378 /*-----------------------------------------------------------------*/
5379 static void AccSRsh (int shCount)
5384 emitcode("mov","c,acc.7");
5385 emitcode("rrc","a");
5386 } else if(shCount == 2){
5387 emitcode("mov","c,acc.7");
5388 emitcode("rrc","a");
5389 emitcode("mov","c,acc.7");
5390 emitcode("rrc","a");
5392 tlbl = newiTempLabel(NULL);
5393 /* rotate right accumulator */
5394 AccRol(8 - shCount);
5395 /* and kill the higher order bits */
5396 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5397 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5398 emitcode("orl","a,#0x%02x",
5399 (unsigned char)~SRMask[shCount]);
5400 emitcode("","%05d$:",tlbl->key+100);
5405 /*-----------------------------------------------------------------*/
5406 /* shiftR1Left2Result - shift right one byte from left to result */
5407 /*-----------------------------------------------------------------*/
5408 static void shiftR1Left2Result (operand *left, int offl,
5409 operand *result, int offr,
5410 int shCount, int sign)
5412 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5413 /* shift right accumulator */
5418 aopPut(AOP(result),"a",offr);
5421 /*-----------------------------------------------------------------*/
5422 /* shiftL1Left2Result - shift left one byte from left to result */
5423 /*-----------------------------------------------------------------*/
5424 static void shiftL1Left2Result (operand *left, int offl,
5425 operand *result, int offr, int shCount)
5428 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5430 /* shift left accumulator */
5432 aopPut(AOP(result),"a",offr);
5435 /*-----------------------------------------------------------------*/
5436 /* movLeft2Result - move byte from left to result */
5437 /*-----------------------------------------------------------------*/
5438 static void movLeft2Result (operand *left, int offl,
5439 operand *result, int offr, int sign)
5442 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5443 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5445 if (*l == '@' && (IS_AOP_PREG(result))) {
5446 emitcode("mov","a,%s",l);
5447 aopPut(AOP(result),"a",offr);
5450 aopPut(AOP(result),l,offr);
5452 /* MSB sign in acc.7 ! */
5453 if(getDataSize(left) == offl+1){
5454 emitcode("mov","a,%s",l);
5455 aopPut(AOP(result),"a",offr);
5462 /*-----------------------------------------------------------------*/
5463 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5464 /*-----------------------------------------------------------------*/
5465 static void AccAXRrl1 (char *x)
5467 emitcode("rrc","a");
5468 emitcode("xch","a,%s", x);
5469 emitcode("rrc","a");
5470 emitcode("xch","a,%s", x);
5473 /*-----------------------------------------------------------------*/
5474 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5475 /*-----------------------------------------------------------------*/
5476 static void AccAXLrl1 (char *x)
5478 emitcode("xch","a,%s",x);
5479 emitcode("rlc","a");
5480 emitcode("xch","a,%s",x);
5481 emitcode("rlc","a");
5484 /*-----------------------------------------------------------------*/
5485 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5486 /*-----------------------------------------------------------------*/
5487 static void AccAXLsh1 (char *x)
5489 emitcode("xch","a,%s",x);
5490 emitcode("add","a,acc");
5491 emitcode("xch","a,%s",x);
5492 emitcode("rlc","a");
5495 /*-----------------------------------------------------------------*/
5496 /* AccAXLsh - left shift a:x by known count (0..7) */
5497 /*-----------------------------------------------------------------*/
5498 static void AccAXLsh (char *x, int shCount)
5512 case 5 : // AAAAABBB:CCCCCDDD
5513 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5514 emitcode("anl","a,#0x%02x",
5515 SLMask[shCount]); // BBB00000:CCCCCDDD
5516 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5517 AccRol(shCount); // DDDCCCCC:BBB00000
5518 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5519 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5520 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5521 emitcode("anl","a,#0x%02x",
5522 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5523 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5524 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5526 case 6 : // AAAAAABB:CCCCCCDD
5527 emitcode("anl","a,#0x%02x",
5528 SRMask[shCount]); // 000000BB:CCCCCCDD
5529 emitcode("mov","c,acc.0"); // c = B
5530 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5531 AccAXRrl1(x); // BCCCCCCD:D000000B
5532 AccAXRrl1(x); // BBCCCCCC:DD000000
5534 case 7 : // a:x <<= 7
5535 emitcode("anl","a,#0x%02x",
5536 SRMask[shCount]); // 0000000B:CCCCCCCD
5537 emitcode("mov","c,acc.0"); // c = B
5538 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5539 AccAXRrl1(x); // BCCCCCCC:D0000000
5546 /*-----------------------------------------------------------------*/
5547 /* AccAXRsh - right shift a:x known count (0..7) */
5548 /*-----------------------------------------------------------------*/
5549 static void AccAXRsh (char *x, int shCount)
5556 AccAXRrl1(x); // 0->a:x
5560 AccAXRrl1(x); // 0->a:x
5562 AccAXRrl1(x); // 0->a:x
5566 case 5 : // AAAAABBB:CCCCCDDD = a:x
5567 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5568 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5569 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5570 emitcode("anl","a,#0x%02x",
5571 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5572 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5573 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5574 emitcode("anl","a,#0x%02x",
5575 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5576 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5577 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5578 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5580 case 6 : // AABBBBBB:CCDDDDDD
5581 emitcode("mov","c,acc.7");
5582 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5583 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5584 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5585 emitcode("anl","a,#0x%02x",
5586 SRMask[shCount]); // 000000AA:BBBBBBCC
5588 case 7 : // ABBBBBBB:CDDDDDDD
5589 emitcode("mov","c,acc.7"); // c = A
5590 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5591 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5592 emitcode("anl","a,#0x%02x",
5593 SRMask[shCount]); // 0000000A:BBBBBBBC
5600 /*-----------------------------------------------------------------*/
5601 /* AccAXRshS - right shift signed a:x known count (0..7) */
5602 /*-----------------------------------------------------------------*/
5603 static void AccAXRshS (char *x, int shCount)
5610 emitcode("mov","c,acc.7");
5611 AccAXRrl1(x); // s->a:x
5614 emitcode("mov","c,acc.7");
5615 AccAXRrl1(x); // s->a:x
5616 emitcode("mov","c,acc.7");
5617 AccAXRrl1(x); // s->a:x
5621 case 5 : // AAAAABBB:CCCCCDDD = a:x
5622 tlbl = newiTempLabel(NULL);
5623 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5624 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5625 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5626 emitcode("anl","a,#0x%02x",
5627 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5628 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5629 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5630 emitcode("anl","a,#0x%02x",
5631 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5632 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5633 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5634 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5635 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5636 emitcode("orl","a,#0x%02x",
5637 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5638 emitcode("","%05d$:",tlbl->key+100);
5639 break; // SSSSAAAA:BBBCCCCC
5640 case 6 : // AABBBBBB:CCDDDDDD
5641 tlbl = newiTempLabel(NULL);
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
5648 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5649 emitcode("orl","a,#0x%02x",
5650 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5651 emitcode("","%05d$:",tlbl->key+100);
5653 case 7 : // ABBBBBBB:CDDDDDDD
5654 tlbl = newiTempLabel(NULL);
5655 emitcode("mov","c,acc.7"); // c = A
5656 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5657 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5658 emitcode("anl","a,#0x%02x",
5659 SRMask[shCount]); // 0000000A:BBBBBBBC
5660 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5661 emitcode("orl","a,#0x%02x",
5662 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5663 emitcode("","%05d$:",tlbl->key+100);
5670 /*-----------------------------------------------------------------*/
5671 /* shiftL2Left2Result - shift left two bytes from left to result */
5672 /*-----------------------------------------------------------------*/
5673 static void shiftL2Left2Result (operand *left, int offl,
5674 operand *result, int offr, int shCount)
5676 if(sameRegs(AOP(result), AOP(left)) &&
5677 ((offl + MSB16) == offr)){
5678 /* don't crash result[offr] */
5679 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5680 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5682 movLeft2Result(left,offl, result, offr, 0);
5683 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5685 /* ax << shCount (x = lsb(result))*/
5686 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5687 aopPut(AOP(result),"a",offr+MSB16);
5691 /*-----------------------------------------------------------------*/
5692 /* shiftR2Left2Result - shift right two bytes from left to result */
5693 /*-----------------------------------------------------------------*/
5694 static void shiftR2Left2Result (operand *left, int offl,
5695 operand *result, int offr,
5696 int shCount, int sign)
5698 if(sameRegs(AOP(result), AOP(left)) &&
5699 ((offl + MSB16) == offr)){
5700 /* don't crash result[offr] */
5701 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5702 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5704 movLeft2Result(left,offl, result, offr, 0);
5705 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5707 /* a:x >> shCount (x = lsb(result))*/
5709 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5711 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5712 if(getDataSize(result) > 1)
5713 aopPut(AOP(result),"a",offr+MSB16);
5716 /*-----------------------------------------------------------------*/
5717 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5718 /*-----------------------------------------------------------------*/
5719 static void shiftLLeftOrResult (operand *left, int offl,
5720 operand *result, int offr, int shCount)
5722 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5723 /* shift left accumulator */
5725 /* or with result */
5726 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5727 /* back to result */
5728 aopPut(AOP(result),"a",offr);
5731 /*-----------------------------------------------------------------*/
5732 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5733 /*-----------------------------------------------------------------*/
5734 static void shiftRLeftOrResult (operand *left, int offl,
5735 operand *result, int offr, int shCount)
5737 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5738 /* shift right accumulator */
5740 /* or with result */
5741 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5742 /* back to result */
5743 aopPut(AOP(result),"a",offr);
5746 /*-----------------------------------------------------------------*/
5747 /* genlshOne - left shift a one byte quantity by known count */
5748 /*-----------------------------------------------------------------*/
5749 static void genlshOne (operand *result, operand *left, int shCount)
5751 D(emitcode(";", "genlshOne "););
5752 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5755 /*-----------------------------------------------------------------*/
5756 /* genlshTwo - left shift two bytes by known amount != 0 */
5757 /*-----------------------------------------------------------------*/
5758 static void genlshTwo (operand *result,operand *left, int shCount)
5762 D(emitcode(";", "genlshTwo "););
5764 size = getDataSize(result);
5766 /* if shCount >= 8 */
5772 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5774 movLeft2Result(left, LSB, result, MSB16, 0);
5776 aopPut(AOP(result),zero,LSB);
5779 /* 1 <= shCount <= 7 */
5782 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5784 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5788 /*-----------------------------------------------------------------*/
5789 /* shiftLLong - shift left one long from left to result */
5790 /* offl = LSB or MSB16 */
5791 /*-----------------------------------------------------------------*/
5792 static void shiftLLong (operand *left, operand *result, int offr )
5795 int size = AOP_SIZE(result);
5797 if(size >= LSB+offr){
5798 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5800 emitcode("add","a,acc");
5801 if (sameRegs(AOP(left),AOP(result)) &&
5802 size >= MSB16+offr && offr != LSB )
5803 emitcode("xch","a,%s",
5804 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5806 aopPut(AOP(result),"a",LSB+offr);
5809 if(size >= MSB16+offr){
5810 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5811 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5814 emitcode("rlc","a");
5815 if (sameRegs(AOP(left),AOP(result)) &&
5816 size >= MSB24+offr && offr != LSB)
5817 emitcode("xch","a,%s",
5818 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5820 aopPut(AOP(result),"a",MSB16+offr);
5823 if(size >= MSB24+offr){
5824 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5825 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5828 emitcode("rlc","a");
5829 if (sameRegs(AOP(left),AOP(result)) &&
5830 size >= MSB32+offr && offr != LSB )
5831 emitcode("xch","a,%s",
5832 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5834 aopPut(AOP(result),"a",MSB24+offr);
5837 if(size > MSB32+offr){
5838 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5839 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5842 emitcode("rlc","a");
5843 aopPut(AOP(result),"a",MSB32+offr);
5846 aopPut(AOP(result),zero,LSB);
5849 /*-----------------------------------------------------------------*/
5850 /* genlshFour - shift four byte by a known amount != 0 */
5851 /*-----------------------------------------------------------------*/
5852 static void genlshFour (operand *result, operand *left, int shCount)
5856 D(emitcode(";", "genlshFour "););
5858 size = AOP_SIZE(result);
5860 /* if shifting more that 3 bytes */
5861 if (shCount >= 24 ) {
5864 /* lowest order of left goes to the highest
5865 order of the destination */
5866 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5868 movLeft2Result(left, LSB, result, MSB32, 0);
5869 aopPut(AOP(result),zero,LSB);
5870 aopPut(AOP(result),zero,MSB16);
5871 aopPut(AOP(result),zero,MSB32);
5875 /* more than two bytes */
5876 else if ( shCount >= 16 ) {
5877 /* lower order two bytes goes to higher order two bytes */
5879 /* if some more remaining */
5881 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5883 movLeft2Result(left, MSB16, result, MSB32, 0);
5884 movLeft2Result(left, LSB, result, MSB24, 0);
5886 aopPut(AOP(result),zero,MSB16);
5887 aopPut(AOP(result),zero,LSB);
5891 /* if more than 1 byte */
5892 else if ( shCount >= 8 ) {
5893 /* lower order three bytes goes to higher order three bytes */
5897 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5899 movLeft2Result(left, LSB, result, MSB16, 0);
5901 else{ /* size = 4 */
5903 movLeft2Result(left, MSB24, result, MSB32, 0);
5904 movLeft2Result(left, MSB16, result, MSB24, 0);
5905 movLeft2Result(left, LSB, result, MSB16, 0);
5906 aopPut(AOP(result),zero,LSB);
5908 else if(shCount == 1)
5909 shiftLLong(left, result, MSB16);
5911 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5912 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5913 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5914 aopPut(AOP(result),zero,LSB);
5919 /* 1 <= shCount <= 7 */
5920 else if(shCount <= 2){
5921 shiftLLong(left, result, LSB);
5923 shiftLLong(result, result, LSB);
5925 /* 3 <= shCount <= 7, optimize */
5927 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5928 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5929 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5933 /*-----------------------------------------------------------------*/
5934 /* genLeftShiftLiteral - left shifting by known count */
5935 /*-----------------------------------------------------------------*/
5936 static void genLeftShiftLiteral (operand *left,
5941 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5944 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5946 freeAsmop(right,NULL,ic,TRUE);
5948 aopOp(left,ic,FALSE, FALSE);
5949 aopOp(result,ic,FALSE, TRUE);
5951 size = getSize(operandType(result));
5954 emitcode("; shift left ","result %d, left %d",size,
5958 /* I suppose that the left size >= result size */
5961 movLeft2Result(left, size, result, size, 0);
5965 else if(shCount >= (size * 8))
5967 aopPut(AOP(result),zero,size);
5971 genlshOne (result,left,shCount);
5975 case 3: /* bug: this is for generic pointers, I bet. */
5976 genlshTwo (result,left,shCount);
5980 genlshFour (result,left,shCount);
5984 freeAsmop(left,NULL,ic,TRUE);
5985 freeAsmop(result,NULL,ic,TRUE);
5988 /*-----------------------------------------------------------------*/
5989 /* genLeftShift - generates code for left shifting */
5990 /*-----------------------------------------------------------------*/
5991 static void genLeftShift (iCode *ic)
5993 operand *left,*right, *result;
5996 symbol *tlbl , *tlbl1;
5998 D(emitcode(";", "genLeftShift "););
6000 right = IC_RIGHT(ic);
6002 result = IC_RESULT(ic);
6004 aopOp(right,ic,FALSE, FALSE);
6007 /* if the shift count is known then do it
6008 as efficiently as possible */
6009 if (AOP_TYPE(right) == AOP_LIT) {
6010 genLeftShiftLiteral (left,right,result,ic);
6015 /* shift count is unknown then we have to form
6016 a loop get the loop count in B : Note: we take
6017 only the lower order byte since shifting
6018 more that 32 bits make no sense anyway, ( the
6019 largest size of an object can be only 32 bits ) */
6021 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6022 emitcode("inc","b");
6023 freeAsmop (right,NULL,ic,TRUE);
6024 aopOp(left,ic,FALSE, FALSE);
6025 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6027 /* now move the left to the result if they are not the
6029 if (!sameRegs(AOP(left),AOP(result)) &&
6030 AOP_SIZE(result) > 1) {
6032 size = AOP_SIZE(result);
6034 _startLazyDPSEvaluation();
6036 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6037 if (*l == '@' && (IS_AOP_PREG(result))) {
6039 emitcode("mov","a,%s",l);
6040 aopPut(AOP(result),"a",offset);
6042 aopPut(AOP(result),l,offset);
6045 _endLazyDPSEvaluation();
6048 tlbl = newiTempLabel(NULL);
6049 size = AOP_SIZE(result);
6051 tlbl1 = newiTempLabel(NULL);
6053 /* if it is only one byte then */
6055 symbol *tlbl1 = newiTempLabel(NULL);
6057 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6059 emitcode("sjmp","%05d$",tlbl1->key+100);
6060 emitcode("","%05d$:",tlbl->key+100);
6061 emitcode("add","a,acc");
6062 emitcode("","%05d$:",tlbl1->key+100);
6063 emitcode("djnz","b,%05d$",tlbl->key+100);
6064 aopPut(AOP(result),"a",0);
6068 reAdjustPreg(AOP(result));
6070 emitcode("sjmp","%05d$",tlbl1->key+100);
6071 emitcode("","%05d$:",tlbl->key+100);
6072 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6074 emitcode("add","a,acc");
6075 aopPut(AOP(result),"a",offset++);
6076 _startLazyDPSEvaluation();
6078 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6080 emitcode("rlc","a");
6081 aopPut(AOP(result),"a",offset++);
6083 _endLazyDPSEvaluation();
6084 reAdjustPreg(AOP(result));
6086 emitcode("","%05d$:",tlbl1->key+100);
6087 emitcode("djnz","b,%05d$",tlbl->key+100);
6089 freeAsmop(left,NULL,ic,TRUE);
6090 freeAsmop(result,NULL,ic,TRUE);
6093 /*-----------------------------------------------------------------*/
6094 /* genrshOne - right shift a one byte quantity by known count */
6095 /*-----------------------------------------------------------------*/
6096 static void genrshOne (operand *result, operand *left,
6097 int shCount, int sign)
6099 D(emitcode(";", "genrshOne"););
6100 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6103 /*-----------------------------------------------------------------*/
6104 /* genrshTwo - right shift two bytes by known amount != 0 */
6105 /*-----------------------------------------------------------------*/
6106 static void genrshTwo (operand *result,operand *left,
6107 int shCount, int sign)
6109 D(emitcode(";", "genrshTwo"););
6111 /* if shCount >= 8 */
6115 shiftR1Left2Result(left, MSB16, result, LSB,
6118 movLeft2Result(left, MSB16, result, LSB, sign);
6119 addSign(result, MSB16, sign);
6122 /* 1 <= shCount <= 7 */
6124 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6127 /*-----------------------------------------------------------------*/
6128 /* shiftRLong - shift right one long from left to result */
6129 /* offl = LSB or MSB16 */
6130 /*-----------------------------------------------------------------*/
6131 static void shiftRLong (operand *left, int offl,
6132 operand *result, int sign)
6135 emitcode("clr","c");
6136 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6138 emitcode("mov","c,acc.7");
6139 emitcode("rrc","a");
6140 aopPut(AOP(result),"a",MSB32-offl);
6142 /* add sign of "a" */
6143 addSign(result, MSB32, sign);
6145 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6146 emitcode("rrc","a");
6147 aopPut(AOP(result),"a",MSB24-offl);
6149 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6150 emitcode("rrc","a");
6151 aopPut(AOP(result),"a",MSB16-offl);
6154 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6155 emitcode("rrc","a");
6156 aopPut(AOP(result),"a",LSB);
6160 /*-----------------------------------------------------------------*/
6161 /* genrshFour - shift four byte by a known amount != 0 */
6162 /*-----------------------------------------------------------------*/
6163 static void genrshFour (operand *result, operand *left,
6164 int shCount, int sign)
6166 D(emitcode(";", "genrshFour"););
6168 /* if shifting more that 3 bytes */
6169 if(shCount >= 24 ) {
6172 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6174 movLeft2Result(left, MSB32, result, LSB, sign);
6175 addSign(result, MSB16, sign);
6177 else if(shCount >= 16){
6180 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6182 movLeft2Result(left, MSB24, result, LSB, 0);
6183 movLeft2Result(left, MSB32, result, MSB16, sign);
6185 addSign(result, MSB24, sign);
6187 else if(shCount >= 8){
6190 shiftRLong(left, MSB16, result, sign);
6191 else if(shCount == 0){
6192 movLeft2Result(left, MSB16, result, LSB, 0);
6193 movLeft2Result(left, MSB24, result, MSB16, 0);
6194 movLeft2Result(left, MSB32, result, MSB24, sign);
6195 addSign(result, MSB32, sign);
6198 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6199 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6200 /* the last shift is signed */
6201 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6202 addSign(result, MSB32, sign);
6205 else{ /* 1 <= shCount <= 7 */
6207 shiftRLong(left, LSB, result, sign);
6209 shiftRLong(result, LSB, result, sign);
6212 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6213 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6214 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6219 /*-----------------------------------------------------------------*/
6220 /* genRightShiftLiteral - right shifting by known count */
6221 /*-----------------------------------------------------------------*/
6222 static void genRightShiftLiteral (operand *left,
6228 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6231 D(emitcode(";", "genRightShiftLiteral"););
6233 freeAsmop(right,NULL,ic,TRUE);
6235 aopOp(left,ic,FALSE, FALSE);
6236 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6239 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6243 size = getDataSize(left);
6244 /* test the LEFT size !!! */
6246 /* I suppose that the left size >= result size */
6248 size = getDataSize(result);
6250 movLeft2Result(left, size, result, size, 0);
6253 else if(shCount >= (size * 8)){
6255 /* get sign in acc.7 */
6256 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6257 addSign(result, LSB, sign);
6261 genrshOne (result,left,shCount,sign);
6265 genrshTwo (result,left,shCount,sign);
6269 genrshFour (result,left,shCount,sign);
6275 freeAsmop(left,NULL,ic,TRUE);
6276 freeAsmop(result,NULL,ic,TRUE);
6280 /*-----------------------------------------------------------------*/
6281 /* genSignedRightShift - right shift of signed number */
6282 /*-----------------------------------------------------------------*/
6283 static void genSignedRightShift (iCode *ic)
6285 operand *right, *left, *result;
6288 symbol *tlbl, *tlbl1 ;
6290 D(emitcode(";", "genSignedRightShift "););
6292 /* we do it the hard way put the shift count in b
6293 and loop thru preserving the sign */
6295 right = IC_RIGHT(ic);
6297 result = IC_RESULT(ic);
6299 aopOp(right,ic,FALSE, FALSE);
6302 if ( AOP_TYPE(right) == AOP_LIT) {
6303 genRightShiftLiteral (left,right,result,ic,1);
6307 /* shift count is unknown then we have to form
6308 a loop get the loop count in B : Note: we take
6309 only the lower order byte since shifting
6310 more that 32 bits make no sense anyway, ( the
6311 largest size of an object can be only 32 bits ) */
6313 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6314 emitcode("inc","b");
6315 freeAsmop (right,NULL,ic,TRUE);
6316 aopOp(left,ic,FALSE, FALSE);
6317 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6319 /* now move the left to the result if they are not the
6321 if (!sameRegs(AOP(left),AOP(result)) &&
6322 AOP_SIZE(result) > 1) {
6324 size = AOP_SIZE(result);
6326 _startLazyDPSEvaluation();
6328 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6329 if (*l == '@' && IS_AOP_PREG(result)) {
6331 emitcode("mov","a,%s",l);
6332 aopPut(AOP(result),"a",offset);
6334 aopPut(AOP(result),l,offset);
6337 _endLazyDPSEvaluation();
6340 /* mov the highest order bit to OVR */
6341 tlbl = newiTempLabel(NULL);
6342 tlbl1= newiTempLabel(NULL);
6344 size = AOP_SIZE(result);
6346 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6347 emitcode("rlc","a");
6348 emitcode("mov","ov,c");
6349 /* if it is only one byte then */
6351 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6353 emitcode("sjmp","%05d$",tlbl1->key+100);
6354 emitcode("","%05d$:",tlbl->key+100);
6355 emitcode("mov","c,ov");
6356 emitcode("rrc","a");
6357 emitcode("","%05d$:",tlbl1->key+100);
6358 emitcode("djnz","b,%05d$",tlbl->key+100);
6359 aopPut(AOP(result),"a",0);
6363 reAdjustPreg(AOP(result));
6364 emitcode("sjmp","%05d$",tlbl1->key+100);
6365 emitcode("","%05d$:",tlbl->key+100);
6366 emitcode("mov","c,ov");
6367 _startLazyDPSEvaluation();
6369 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6371 emitcode("rrc","a");
6372 aopPut(AOP(result),"a",offset--);
6374 _endLazyDPSEvaluation();
6375 reAdjustPreg(AOP(result));
6376 emitcode("","%05d$:",tlbl1->key+100);
6377 emitcode("djnz","b,%05d$",tlbl->key+100);
6380 freeAsmop(left,NULL,ic,TRUE);
6381 freeAsmop(result,NULL,ic,TRUE);
6384 /*-----------------------------------------------------------------*/
6385 /* genRightShift - generate code for right shifting */
6386 /*-----------------------------------------------------------------*/
6387 static void genRightShift (iCode *ic)
6389 operand *right, *left, *result;
6393 symbol *tlbl, *tlbl1 ;
6395 D(emitcode(";", "genRightShift "););
6397 /* if signed then we do it the hard way preserve the
6398 sign bit moving it inwards */
6399 retype = getSpec(operandType(IC_RESULT(ic)));
6401 if (!SPEC_USIGN(retype)) {
6402 genSignedRightShift (ic);
6406 /* signed & unsigned types are treated the same : i.e. the
6407 signed is NOT propagated inwards : quoting from the
6408 ANSI - standard : "for E1 >> E2, is equivalent to division
6409 by 2**E2 if unsigned or if it has a non-negative value,
6410 otherwise the result is implementation defined ", MY definition
6411 is that the sign does not get propagated */
6413 right = IC_RIGHT(ic);
6415 result = IC_RESULT(ic);
6417 aopOp(right,ic,FALSE, FALSE);
6420 /* if the shift count is known then do it
6421 as efficiently as possible */
6422 if (AOP_TYPE(right) == AOP_LIT) {
6423 genRightShiftLiteral (left,right,result,ic, 0);
6428 /* shift count is unknown then we have to form
6429 a loop get the loop count in B : Note: we take
6430 only the lower order byte since shifting
6431 more that 32 bits make no sense anyway, ( the
6432 largest size of an object can be only 32 bits ) */
6434 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6435 emitcode("inc","b");
6436 freeAsmop (right,NULL,ic,TRUE);
6437 aopOp(left,ic,FALSE, FALSE);
6438 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6440 /* now move the left to the result if they are not the
6442 if (!sameRegs(AOP(left),AOP(result)) &&
6443 AOP_SIZE(result) > 1) {
6445 size = AOP_SIZE(result);
6447 _startLazyDPSEvaluation();
6449 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6450 if (*l == '@' && IS_AOP_PREG(result)) {
6452 emitcode("mov","a,%s",l);
6453 aopPut(AOP(result),"a",offset);
6455 aopPut(AOP(result),l,offset);
6458 _endLazyDPSEvaluation();
6461 tlbl = newiTempLabel(NULL);
6462 tlbl1= newiTempLabel(NULL);
6463 size = AOP_SIZE(result);
6466 /* if it is only one byte then */
6468 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6470 emitcode("sjmp","%05d$",tlbl1->key+100);
6471 emitcode("","%05d$:",tlbl->key+100);
6473 emitcode("rrc","a");
6474 emitcode("","%05d$:",tlbl1->key+100);
6475 emitcode("djnz","b,%05d$",tlbl->key+100);
6476 aopPut(AOP(result),"a",0);
6480 reAdjustPreg(AOP(result));
6481 emitcode("sjmp","%05d$",tlbl1->key+100);
6482 emitcode("","%05d$:",tlbl->key+100);
6484 _startLazyDPSEvaluation();
6486 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6488 emitcode("rrc","a");
6489 aopPut(AOP(result),"a",offset--);
6491 _endLazyDPSEvaluation();
6492 reAdjustPreg(AOP(result));
6494 emitcode("","%05d$:",tlbl1->key+100);
6495 emitcode("djnz","b,%05d$",tlbl->key+100);
6498 freeAsmop(left,NULL,ic,TRUE);
6499 freeAsmop(result,NULL,ic,TRUE);
6502 /*-----------------------------------------------------------------*/
6503 /* genUnpackBits - generates code for unpacking bits */
6504 /*-----------------------------------------------------------------*/
6505 static void genUnpackBits (operand *result, char *rname, int ptype)
6512 D(emitcode(";", "genUnpackBits "););
6514 etype = getSpec(operandType(result));
6516 /* read the first byte */
6521 emitcode("mov","a,@%s",rname);
6525 emitcode("movx","a,@%s",rname);
6529 emitcode("movx","a,@dptr");
6533 emitcode("clr","a");
6534 emitcode("movc","a","@a+dptr");
6538 emitcode("lcall","__gptrget");
6542 /* if we have bitdisplacement then it fits */
6543 /* into this byte completely or if length is */
6544 /* less than a byte */
6545 if ((shCnt = SPEC_BSTR(etype)) ||
6546 (SPEC_BLEN(etype) <= 8)) {
6548 /* shift right acc */
6551 emitcode("anl","a,#0x%02x",
6552 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6553 aopPut(AOP(result),"a",offset);
6557 /* bit field did not fit in a byte */
6558 rlen = SPEC_BLEN(etype) - 8;
6559 aopPut(AOP(result),"a",offset++);
6566 emitcode("inc","%s",rname);
6567 emitcode("mov","a,@%s",rname);
6571 emitcode("inc","%s",rname);
6572 emitcode("movx","a,@%s",rname);
6576 emitcode("inc","dptr");
6577 emitcode("movx","a,@dptr");
6581 emitcode("clr","a");
6582 emitcode("inc","dptr");
6583 emitcode("movc","a","@a+dptr");
6587 emitcode("inc","dptr");
6588 emitcode("lcall","__gptrget");
6593 /* if we are done */
6597 aopPut(AOP(result),"a",offset++);
6602 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6603 aopPut(AOP(result),"a",offset);
6610 /*-----------------------------------------------------------------*/
6611 /* genDataPointerGet - generates code when ptr offset is known */
6612 /*-----------------------------------------------------------------*/
6613 static void genDataPointerGet (operand *left,
6619 int size , offset = 0;
6620 aopOp(result,ic,TRUE, FALSE);
6622 /* get the string representation of the name */
6623 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6624 size = AOP_SIZE(result);
6625 _startLazyDPSEvaluation();
6628 sprintf(buffer,"(%s + %d)",l+1,offset);
6630 sprintf(buffer,"%s",l+1);
6631 aopPut(AOP(result),buffer,offset++);
6633 _endLazyDPSEvaluation();
6635 freeAsmop(left,NULL,ic,TRUE);
6636 freeAsmop(result,NULL,ic,TRUE);
6639 /*-----------------------------------------------------------------*/
6640 /* genNearPointerGet - emitcode for near pointer fetch */
6641 /*-----------------------------------------------------------------*/
6642 static void genNearPointerGet (operand *left,
6649 link *rtype, *retype;
6650 link *ltype = operandType(left);
6653 rtype = operandType(result);
6654 retype= getSpec(rtype);
6656 aopOp(left,ic,FALSE, FALSE);
6658 /* if left is rematerialisable and
6659 result is not bit variable type and
6660 the left is pointer to data space i.e
6661 lower 128 bytes of space */
6662 if (AOP_TYPE(left) == AOP_IMMD &&
6663 !IS_BITVAR(retype) &&
6664 DCL_TYPE(ltype) == POINTER) {
6665 genDataPointerGet (left,result,ic);
6669 /* if the value is already in a pointer register
6670 then don't need anything more */
6671 if (!AOP_INPREG(AOP(left))) {
6672 /* otherwise get a free pointer register */
6674 preg = getFreePtr(ic,&aop,FALSE);
6675 emitcode("mov","%s,%s",
6677 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6678 rname = preg->name ;
6680 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6682 freeAsmop(left,NULL,ic,TRUE);
6683 aopOp (result,ic,FALSE, FALSE);
6685 /* if bitfield then unpack the bits */
6686 if (IS_BITVAR(retype))
6687 genUnpackBits (result,rname,POINTER);
6689 /* we have can just get the values */
6690 int size = AOP_SIZE(result);
6694 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6696 emitcode("mov","a,@%s",rname);
6697 aopPut(AOP(result),"a",offset);
6699 sprintf(buffer,"@%s",rname);
6700 aopPut(AOP(result),buffer,offset);
6704 emitcode("inc","%s",rname);
6708 /* now some housekeeping stuff */
6710 /* we had to allocate for this iCode */
6711 freeAsmop(NULL,aop,ic,TRUE);
6713 /* we did not allocate which means left
6714 already in a pointer register, then
6715 if size > 0 && this could be used again
6716 we have to point it back to where it
6718 if (AOP_SIZE(result) > 1 &&
6719 !OP_SYMBOL(left)->remat &&
6720 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6722 int size = AOP_SIZE(result) - 1;
6724 emitcode("dec","%s",rname);
6729 freeAsmop(result,NULL,ic,TRUE);
6733 /*-----------------------------------------------------------------*/
6734 /* genPagedPointerGet - emitcode for paged pointer fetch */
6735 /*-----------------------------------------------------------------*/
6736 static void genPagedPointerGet (operand *left,
6743 link *rtype, *retype;
6745 rtype = operandType(result);
6746 retype= getSpec(rtype);
6748 aopOp(left,ic,FALSE, FALSE);
6750 /* if the value is already in a pointer register
6751 then don't need anything more */
6752 if (!AOP_INPREG(AOP(left))) {
6753 /* otherwise get a free pointer register */
6755 preg = getFreePtr(ic,&aop,FALSE);
6756 emitcode("mov","%s,%s",
6758 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6759 rname = preg->name ;
6761 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6763 freeAsmop(left,NULL,ic,TRUE);
6764 aopOp (result,ic,FALSE, FALSE);
6766 /* if bitfield then unpack the bits */
6767 if (IS_BITVAR(retype))
6768 genUnpackBits (result,rname,PPOINTER);
6770 /* we have can just get the values */
6771 int size = AOP_SIZE(result);
6776 emitcode("movx","a,@%s",rname);
6777 aopPut(AOP(result),"a",offset);
6782 emitcode("inc","%s",rname);
6786 /* now some housekeeping stuff */
6788 /* we had to allocate for this iCode */
6789 freeAsmop(NULL,aop,ic,TRUE);
6791 /* we did not allocate which means left
6792 already in a pointer register, then
6793 if size > 0 && this could be used again
6794 we have to point it back to where it
6796 if (AOP_SIZE(result) > 1 &&
6797 !OP_SYMBOL(left)->remat &&
6798 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6800 int size = AOP_SIZE(result) - 1;
6802 emitcode("dec","%s",rname);
6807 freeAsmop(result,NULL,ic,TRUE);
6812 /*-----------------------------------------------------------------*/
6813 /* genFarPointerGet - gget value from far space */
6814 /*-----------------------------------------------------------------*/
6815 static void genFarPointerGet (operand *left,
6816 operand *result, iCode *ic)
6819 link *retype = getSpec(operandType(result));
6821 D(emitcode(";", "genFarPointerGet"););
6823 aopOp(left,ic,FALSE, FALSE);
6825 /* if the operand is already in dptr
6826 then we do nothing else we move the value to dptr */
6827 if (AOP_TYPE(left) != AOP_STR) {
6828 /* if this is remateriazable */
6829 if (AOP_TYPE(left) == AOP_IMMD)
6831 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6835 /* we need to get it byte by byte */
6836 _startLazyDPSEvaluation();
6837 if (AOP_TYPE(left) != AOP_DPTR)
6839 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6840 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6841 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6845 /* We need to generate a load to DPTR indirect through DPTR. */
6846 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6847 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6848 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6849 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6850 emitcode("pop", "dph");
6851 emitcode("pop", "dpl");
6853 _endLazyDPSEvaluation();
6856 /* so dptr know contains the address */
6857 freeAsmop(left,NULL,ic,TRUE);
6858 aopOp(result,ic,FALSE, TRUE);
6860 /* if bit then unpack */
6861 if (IS_BITVAR(retype))
6862 genUnpackBits(result,"dptr",FPOINTER);
6864 size = AOP_SIZE(result);
6867 _startLazyDPSEvaluation();
6873 emitcode("movx","a,@dptr");
6874 aopPut(AOP(result),"a",offset++);
6876 emitcode("inc","dptr");
6878 _endLazyDPSEvaluation();
6881 freeAsmop(result,NULL,ic,TRUE);
6884 /*-----------------------------------------------------------------*/
6885 /* emitcodePointerGet - gget value from code space */
6886 /*-----------------------------------------------------------------*/
6887 static void emitcodePointerGet (operand *left,
6888 operand *result, iCode *ic)
6891 link *retype = getSpec(operandType(result));
6893 aopOp(left,ic,FALSE, FALSE);
6895 /* if the operand is already in dptr
6896 then we do nothing else we move the value to dptr */
6897 if (AOP_TYPE(left) != AOP_STR) {
6898 /* if this is remateriazable */
6899 if (AOP_TYPE(left) == AOP_IMMD)
6900 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6901 else { /* we need to get it byte by byte */
6902 _startLazyDPSEvaluation();
6903 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6904 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6905 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6906 _endLazyDPSEvaluation();
6909 /* so dptr know contains the address */
6910 freeAsmop(left,NULL,ic,TRUE);
6911 aopOp(result,ic,FALSE, FALSE);
6913 /* if bit then unpack */
6914 if (IS_BITVAR(retype))
6915 genUnpackBits(result,"dptr",CPOINTER);
6917 size = AOP_SIZE(result);
6921 emitcode("clr","a");
6922 emitcode("movc","a,@a+dptr");
6923 aopPut(AOP(result),"a",offset++);
6925 emitcode("inc","dptr");
6929 freeAsmop(result,NULL,ic,TRUE);
6932 /*-----------------------------------------------------------------*/
6933 /* genGenPointerGet - gget value from generic pointer space */
6934 /*-----------------------------------------------------------------*/
6935 static void genGenPointerGet (operand *left,
6936 operand *result, iCode *ic)
6939 link *retype = getSpec(operandType(result));
6941 aopOp(left,ic,FALSE, TRUE);
6943 /* if the operand is already in dptr
6944 then we do nothing else we move the value to dptr */
6945 if (AOP_TYPE(left) != AOP_STR) {
6946 /* if this is remateriazable */
6947 if (AOP_TYPE(left) == AOP_IMMD) {
6948 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6949 emitcode("mov","b,#%d",pointerCode(retype));
6951 else { /* we need to get it byte by byte */
6952 _startLazyDPSEvaluation();
6953 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6954 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6955 if (options.model == MODEL_FLAT24)
6957 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6958 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
6962 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6964 _endLazyDPSEvaluation();
6967 /* so dptr know contains the address */
6968 freeAsmop(left,NULL,ic,TRUE);
6969 aopOp(result,ic,FALSE, TRUE);
6971 /* if bit then unpack */
6972 if (IS_BITVAR(retype))
6973 genUnpackBits(result,"dptr",GPOINTER);
6975 size = AOP_SIZE(result);
6979 emitcode("lcall","__gptrget");
6980 aopPut(AOP(result),"a",offset++);
6982 emitcode("inc","dptr");
6986 freeAsmop(result,NULL,ic,TRUE);
6989 /*-----------------------------------------------------------------*/
6990 /* genPointerGet - generate code for pointer get */
6991 /*-----------------------------------------------------------------*/
6992 static void genPointerGet (iCode *ic)
6994 operand *left, *result ;
6998 D(emitcode(";", "genPointerGet "););
7001 result = IC_RESULT(ic) ;
7003 /* depending on the type of pointer we need to
7004 move it to the correct pointer register */
7005 type = operandType(left);
7006 etype = getSpec(type);
7007 /* if left is of type of pointer then it is simple */
7008 if (IS_PTR(type) && !IS_FUNC(type->next))
7009 p_type = DCL_TYPE(type);
7011 /* we have to go by the storage class */
7012 p_type = PTR_TYPE(SPEC_OCLS(etype));
7014 /* if (SPEC_OCLS(etype)->codesp ) { */
7015 /* p_type = CPOINTER ; */
7018 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7019 /* p_type = FPOINTER ; */
7021 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7022 /* p_type = PPOINTER; */
7024 /* if (SPEC_OCLS(etype) == idata ) */
7025 /* p_type = IPOINTER; */
7027 /* p_type = POINTER ; */
7030 /* now that we have the pointer type we assign
7031 the pointer values */
7036 genNearPointerGet (left,result,ic);
7040 genPagedPointerGet(left,result,ic);
7044 genFarPointerGet (left,result,ic);
7048 emitcodePointerGet (left,result,ic);
7052 genGenPointerGet (left,result,ic);
7058 /*-----------------------------------------------------------------*/
7059 /* genPackBits - generates code for packed bit storage */
7060 /*-----------------------------------------------------------------*/
7061 static void genPackBits (link *etype ,
7063 char *rname, int p_type)
7071 blen = SPEC_BLEN(etype);
7072 bstr = SPEC_BSTR(etype);
7074 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7077 /* if the bit lenth is less than or */
7078 /* it exactly fits a byte then */
7079 if (SPEC_BLEN(etype) <= 8 ) {
7080 shCount = SPEC_BSTR(etype) ;
7082 /* shift left acc */
7085 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7090 emitcode ("mov","b,a");
7091 emitcode("mov","a,@%s",rname);
7095 emitcode ("mov","b,a");
7096 emitcode("movx","a,@dptr");
7100 emitcode ("push","b");
7101 emitcode ("push","acc");
7102 emitcode ("lcall","__gptrget");
7103 emitcode ("pop","b");
7107 emitcode ("anl","a,#0x%02x",(unsigned char)
7108 ((unsigned char)(0xFF << (blen+bstr)) |
7109 (unsigned char)(0xFF >> (8-bstr)) ) );
7110 emitcode ("orl","a,b");
7111 if (p_type == GPOINTER)
7112 emitcode("pop","b");
7118 emitcode("mov","@%s,a",rname);
7122 emitcode("movx","@dptr,a");
7126 emitcode("lcall","__gptrput");
7131 if ( SPEC_BLEN(etype) <= 8 )
7134 emitcode("inc","%s",rname);
7135 rLen = SPEC_BLEN(etype) ;
7137 /* now generate for lengths greater than one byte */
7140 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7150 emitcode("mov","@%s,a",rname);
7152 emitcode("mov","@%s,%s",rname,l);
7157 emitcode("movx","@dptr,a");
7162 emitcode("lcall","__gptrput");
7165 emitcode ("inc","%s",rname);
7170 /* last last was not complete */
7172 /* save the byte & read byte */
7175 emitcode ("mov","b,a");
7176 emitcode("mov","a,@%s",rname);
7180 emitcode ("mov","b,a");
7181 emitcode("movx","a,@dptr");
7185 emitcode ("push","b");
7186 emitcode ("push","acc");
7187 emitcode ("lcall","__gptrget");
7188 emitcode ("pop","b");
7192 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7193 emitcode ("orl","a,b");
7196 if (p_type == GPOINTER)
7197 emitcode("pop","b");
7202 emitcode("mov","@%s,a",rname);
7206 emitcode("movx","@dptr,a");
7210 emitcode("lcall","__gptrput");
7214 /*-----------------------------------------------------------------*/
7215 /* genDataPointerSet - remat pointer to data space */
7216 /*-----------------------------------------------------------------*/
7217 static void genDataPointerSet(operand *right,
7221 int size, offset = 0 ;
7222 char *l, buffer[256];
7224 aopOp(right,ic,FALSE, FALSE);
7226 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7227 size = AOP_SIZE(right);
7230 sprintf(buffer,"(%s + %d)",l+1,offset);
7232 sprintf(buffer,"%s",l+1);
7233 emitcode("mov","%s,%s",buffer,
7234 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7237 freeAsmop(right,NULL,ic,TRUE);
7238 freeAsmop(result,NULL,ic,TRUE);
7241 /*-----------------------------------------------------------------*/
7242 /* genNearPointerSet - emitcode for near pointer put */
7243 /*-----------------------------------------------------------------*/
7244 static void genNearPointerSet (operand *right,
7252 link *ptype = operandType(result);
7254 retype= getSpec(operandType(right));
7256 aopOp(result,ic,FALSE, FALSE);
7258 /* if the result is rematerializable &
7259 in data space & not a bit variable */
7260 if (AOP_TYPE(result) == AOP_IMMD &&
7261 DCL_TYPE(ptype) == POINTER &&
7262 !IS_BITVAR(retype)) {
7263 genDataPointerSet (right,result,ic);
7267 /* if the value is already in a pointer register
7268 then don't need anything more */
7269 if (!AOP_INPREG(AOP(result))) {
7270 /* otherwise get a free pointer register */
7272 preg = getFreePtr(ic,&aop,FALSE);
7273 emitcode("mov","%s,%s",
7275 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7276 rname = preg->name ;
7278 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7280 freeAsmop(result,NULL,ic,TRUE);
7281 aopOp (right,ic,FALSE, FALSE);
7283 /* if bitfield then unpack the bits */
7284 if (IS_BITVAR(retype))
7285 genPackBits (retype,right,rname,POINTER);
7287 /* we have can just get the values */
7288 int size = AOP_SIZE(right);
7292 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7295 emitcode("mov","@%s,a",rname);
7297 emitcode("mov","@%s,%s",rname,l);
7299 emitcode("inc","%s",rname);
7304 /* now some housekeeping stuff */
7306 /* we had to allocate for this iCode */
7307 freeAsmop(NULL,aop,ic,TRUE);
7309 /* we did not allocate which means left
7310 already in a pointer register, then
7311 if size > 0 && this could be used again
7312 we have to point it back to where it
7314 if (AOP_SIZE(right) > 1 &&
7315 !OP_SYMBOL(result)->remat &&
7316 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7318 int size = AOP_SIZE(right) - 1;
7320 emitcode("dec","%s",rname);
7325 freeAsmop(right,NULL,ic,TRUE);
7330 /*-----------------------------------------------------------------*/
7331 /* genPagedPointerSet - emitcode for Paged pointer put */
7332 /*-----------------------------------------------------------------*/
7333 static void genPagedPointerSet (operand *right,
7342 retype= getSpec(operandType(right));
7344 aopOp(result,ic,FALSE, FALSE);
7346 /* if the value is already in a pointer register
7347 then don't need anything more */
7348 if (!AOP_INPREG(AOP(result))) {
7349 /* otherwise get a free pointer register */
7351 preg = getFreePtr(ic,&aop,FALSE);
7352 emitcode("mov","%s,%s",
7354 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7355 rname = preg->name ;
7357 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7359 freeAsmop(result,NULL,ic,TRUE);
7360 aopOp (right,ic,FALSE, FALSE);
7362 /* if bitfield then unpack the bits */
7363 if (IS_BITVAR(retype))
7364 genPackBits (retype,right,rname,PPOINTER);
7366 /* we have can just get the values */
7367 int size = AOP_SIZE(right);
7371 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7374 emitcode("movx","@%s,a",rname);
7377 emitcode("inc","%s",rname);
7383 /* now some housekeeping stuff */
7385 /* we had to allocate for this iCode */
7386 freeAsmop(NULL,aop,ic,TRUE);
7388 /* we did not allocate which means left
7389 already in a pointer register, then
7390 if size > 0 && this could be used again
7391 we have to point it back to where it
7393 if (AOP_SIZE(right) > 1 &&
7394 !OP_SYMBOL(result)->remat &&
7395 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7397 int size = AOP_SIZE(right) - 1;
7399 emitcode("dec","%s",rname);
7404 freeAsmop(right,NULL,ic,TRUE);
7409 /*-----------------------------------------------------------------*/
7410 /* genFarPointerSet - set value from far space */
7411 /*-----------------------------------------------------------------*/
7412 static void genFarPointerSet (operand *right,
7413 operand *result, iCode *ic)
7416 link *retype = getSpec(operandType(right));
7418 aopOp(result,ic,FALSE, FALSE);
7420 /* if the operand is already in dptr
7421 then we do nothing else we move the value to dptr */
7422 if (AOP_TYPE(result) != AOP_STR) {
7423 /* if this is remateriazable */
7424 if (AOP_TYPE(result) == AOP_IMMD)
7425 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7428 /* we need to get it byte by byte */
7429 _startLazyDPSEvaluation();
7430 if (AOP_TYPE(result) != AOP_DPTR)
7432 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7433 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7434 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7438 /* We need to generate a load to DPTR indirect through DPTR. */
7439 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7440 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7441 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7442 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7443 emitcode("pop", "dph");
7444 emitcode("pop", "dpl");
7446 _endLazyDPSEvaluation();
7449 /* so dptr know contains the address */
7450 freeAsmop(result,NULL,ic,TRUE);
7451 aopOp(right,ic,FALSE, TRUE);
7453 /* if bit then unpack */
7454 if (IS_BITVAR(retype))
7455 genPackBits(retype,right,"dptr",FPOINTER);
7457 size = AOP_SIZE(right);
7460 _startLazyDPSEvaluation();
7462 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7468 emitcode("movx","@dptr,a");
7470 emitcode("inc","dptr");
7472 _endLazyDPSEvaluation();
7475 freeAsmop(right,NULL,ic,TRUE);
7478 /*-----------------------------------------------------------------*/
7479 /* genGenPointerSet - set value from generic pointer space */
7480 /*-----------------------------------------------------------------*/
7481 static void genGenPointerSet (operand *right,
7482 operand *result, iCode *ic)
7485 link *retype = getSpec(operandType(right));
7487 aopOp(result,ic,FALSE, TRUE);
7489 /* if the operand is already in dptr
7490 then we do nothing else we move the value to dptr */
7491 if (AOP_TYPE(result) != AOP_STR) {
7492 _startLazyDPSEvaluation();
7493 /* if this is remateriazable */
7494 if (AOP_TYPE(result) == AOP_IMMD) {
7495 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7496 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7498 else { /* we need to get it byte by byte */
7499 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7500 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7501 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7502 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7504 _endLazyDPSEvaluation();
7506 /* so dptr know contains the address */
7507 freeAsmop(result,NULL,ic,TRUE);
7508 aopOp(right,ic,FALSE, TRUE);
7510 /* if bit then unpack */
7511 if (IS_BITVAR(retype))
7512 genPackBits(retype,right,"dptr",GPOINTER);
7514 size = AOP_SIZE(right);
7517 _startLazyDPSEvaluation();
7519 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7525 emitcode("lcall","__gptrput");
7527 emitcode("inc","dptr");
7529 _endLazyDPSEvaluation();
7532 freeAsmop(right,NULL,ic,TRUE);
7535 /*-----------------------------------------------------------------*/
7536 /* genPointerSet - stores the value into a pointer location */
7537 /*-----------------------------------------------------------------*/
7538 static void genPointerSet (iCode *ic)
7540 operand *right, *result ;
7544 D(emitcode(";", "genPointerSet "););
7546 right = IC_RIGHT(ic);
7547 result = IC_RESULT(ic) ;
7549 /* depending on the type of pointer we need to
7550 move it to the correct pointer register */
7551 type = operandType(result);
7552 etype = getSpec(type);
7553 /* if left is of type of pointer then it is simple */
7554 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7555 p_type = DCL_TYPE(type);
7558 /* we have to go by the storage class */
7559 p_type = PTR_TYPE(SPEC_OCLS(etype));
7561 /* if (SPEC_OCLS(etype)->codesp ) { */
7562 /* p_type = CPOINTER ; */
7565 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7566 /* p_type = FPOINTER ; */
7568 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7569 /* p_type = PPOINTER ; */
7571 /* if (SPEC_OCLS(etype) == idata ) */
7572 /* p_type = IPOINTER ; */
7574 /* p_type = POINTER ; */
7577 /* now that we have the pointer type we assign
7578 the pointer values */
7583 genNearPointerSet (right,result,ic);
7587 genPagedPointerSet (right,result,ic);
7591 genFarPointerSet (right,result,ic);
7595 genGenPointerSet (right,result,ic);
7601 /*-----------------------------------------------------------------*/
7602 /* genIfx - generate code for Ifx statement */
7603 /*-----------------------------------------------------------------*/
7604 static void genIfx (iCode *ic, iCode *popIc)
7606 operand *cond = IC_COND(ic);
7609 D(emitcode(";", "genIfx "););
7611 aopOp(cond,ic,FALSE, FALSE);
7613 /* get the value into acc */
7614 if (AOP_TYPE(cond) != AOP_CRY)
7618 /* the result is now in the accumulator */
7619 freeAsmop(cond,NULL,ic,TRUE);
7621 /* if there was something to be popped then do it */
7625 /* if the condition is a bit variable */
7626 if (isbit && IS_ITEMP(cond) &&
7628 genIfxJump(ic,SPIL_LOC(cond)->rname);
7630 if (isbit && !IS_ITEMP(cond))
7631 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7638 /*-----------------------------------------------------------------*/
7639 /* genAddrOf - generates code for address of */
7640 /*-----------------------------------------------------------------*/
7641 static void genAddrOf (iCode *ic)
7643 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7646 D(emitcode(";", "genAddrOf "););
7648 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7650 /* if the operand is on the stack then we
7651 need to get the stack offset of this
7654 /* if it has an offset then we need to compute
7657 emitcode("mov","a,_bp");
7658 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7659 aopPut(AOP(IC_RESULT(ic)),"a",0);
7661 /* we can just move _bp */
7662 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7664 /* fill the result with zero */
7665 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7668 if (options.stack10bit && size < (FPTRSIZE - 1))
7671 "*** warning: pointer to stack var truncated.\n");
7678 if (options.stack10bit && offset == 2)
7680 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7684 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7691 /* object not on stack then we need the name */
7692 size = AOP_SIZE(IC_RESULT(ic));
7696 char s[SDCC_NAME_MAX];
7698 sprintf(s,"#(%s >> %d)",
7702 sprintf(s,"#%s",sym->rname);
7703 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7707 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7711 /*-----------------------------------------------------------------*/
7712 /* genFarFarAssign - assignment when both are in far space */
7713 /*-----------------------------------------------------------------*/
7714 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7716 int size = AOP_SIZE(right);
7723 /* This is a net loss for size == 1, but a big gain
7726 D(emitcode(";", "genFarFarAssign (improved)"););
7728 aopOp(result,ic,TRUE, TRUE);
7730 _startLazyDPSEvaluation();
7734 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7738 _endLazyDPSEvaluation();
7739 freeAsmop(result,NULL,ic,FALSE);
7740 freeAsmop(right,NULL,ic,FALSE);
7745 D(emitcode(";", "genFarFarAssign "););
7747 /* first push the right side on to the stack */
7748 _startLazyDPSEvaluation();
7750 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7752 emitcode ("push","acc");
7755 freeAsmop(right,NULL,ic,FALSE);
7756 /* now assign DPTR to result */
7757 aopOp(result,ic,FALSE, FALSE);
7758 size = AOP_SIZE(result);
7760 emitcode ("pop","acc");
7761 aopPut(AOP(result),"a",--offset);
7763 freeAsmop(result,NULL,ic,FALSE);
7764 _endLazyDPSEvaluation();
7768 /*-----------------------------------------------------------------*/
7769 /* genAssign - generate code for assignment */
7770 /*-----------------------------------------------------------------*/
7771 static void genAssign (iCode *ic)
7773 operand *result, *right;
7775 unsigned long lit = 0L;
7777 D(emitcode(";", "genAssign "););
7779 result = IC_RESULT(ic);
7780 right = IC_RIGHT(ic) ;
7782 /* if they are the same */
7783 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7786 aopOp(right,ic,FALSE, FALSE);
7788 emitcode(";", "genAssign: resultIsFar = %s",
7789 isOperandInFarSpace(result) ?
7792 /* special case both in far space */
7793 if ((AOP_TYPE(right) == AOP_DPTR ||
7794 AOP_TYPE(right) == AOP_DPTR2) &&
7795 /* IS_TRUE_SYMOP(result) && */
7796 isOperandInFarSpace(result)) {
7798 genFarFarAssign (result,right,ic);
7802 aopOp(result,ic,TRUE, FALSE);
7804 /* if they are the same registers */
7805 if (sameRegs(AOP(right),AOP(result)))
7808 /* if the result is a bit */
7809 if (AOP_TYPE(result) == AOP_CRY) {
7811 /* if the right size is a literal then
7812 we know what the value is */
7813 if (AOP_TYPE(right) == AOP_LIT) {
7814 if (((int) operandLitValue(right)))
7815 aopPut(AOP(result),one,0);
7817 aopPut(AOP(result),zero,0);
7821 /* the right is also a bit variable */
7822 if (AOP_TYPE(right) == AOP_CRY) {
7823 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7824 aopPut(AOP(result),"c",0);
7830 aopPut(AOP(result),"a",0);
7834 /* bit variables done */
7836 size = AOP_SIZE(result);
7838 if(AOP_TYPE(right) == AOP_LIT)
7839 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7842 (AOP_TYPE(result) != AOP_REG) &&
7843 (AOP_TYPE(right) == AOP_LIT) &&
7844 !IS_FLOAT(operandType(right))
7845 #ifndef LAZY_DPS_OPT
7851 D(emitcode(";", "Kevin's better literal load code"););
7852 _startLazyDPSEvaluation();
7853 while (size && ((unsigned int)((lit >> (offset*8)) & 0xff) != 0))
7856 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
7861 /* And now fill the rest with zeros. */
7864 emitcode("clr","a");
7868 aopPut(AOP(result), "a", offset++);
7870 _endLazyDPSEvaluation();
7872 emitcode("clr","a");
7874 _startLazyDPSEvaluation();
7877 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7878 aopPut(AOP(result),"a",size);
7881 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
7884 _endLazyDPSEvaluation();
7889 _startLazyDPSEvaluation();
7893 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7897 _endLazyDPSEvaluation();
7901 freeAsmop (right,NULL,ic,FALSE);
7902 freeAsmop (result,NULL,ic,TRUE);
7905 /*-----------------------------------------------------------------*/
7906 /* genJumpTab - generates code for jump table */
7907 /*-----------------------------------------------------------------*/
7908 static void genJumpTab (iCode *ic)
7913 D(emitcode(";", "genJumpTab "););
7915 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7916 /* get the condition into accumulator */
7917 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
7919 /* multiply by four! */
7920 emitcode("add","a,acc");
7921 emitcode("add","a,acc");
7922 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7924 jtab = newiTempLabel(NULL);
7925 emitcode("mov","dptr,#%05d$",jtab->key+100);
7926 emitcode("jmp","@a+dptr");
7927 emitcode("","%05d$:",jtab->key+100);
7928 /* now generate the jump labels */
7929 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7930 jtab = setNextItem(IC_JTLABELS(ic)))
7931 emitcode("ljmp","%05d$",jtab->key+100);
7935 /*-----------------------------------------------------------------*/
7936 /* genCast - gen code for casting */
7937 /*-----------------------------------------------------------------*/
7938 static void genCast (iCode *ic)
7940 operand *result = IC_RESULT(ic);
7941 link *ctype = operandType(IC_LEFT(ic));
7942 link *rtype = operandType(IC_RIGHT(ic));
7943 operand *right = IC_RIGHT(ic);
7946 D(emitcode(";", "genCast "););
7948 /* if they are equivalent then do nothing */
7949 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7952 aopOp(right,ic,FALSE, FALSE) ;
7953 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7955 /* if the result is a bit */
7956 if (AOP_TYPE(result) == AOP_CRY) {
7957 /* if the right size is a literal then
7958 we know what the value is */
7959 if (AOP_TYPE(right) == AOP_LIT) {
7960 if (((int) operandLitValue(right)))
7961 aopPut(AOP(result),one,0);
7963 aopPut(AOP(result),zero,0);
7968 /* the right is also a bit variable */
7969 if (AOP_TYPE(right) == AOP_CRY) {
7970 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7971 aopPut(AOP(result),"c",0);
7977 aopPut(AOP(result),"a",0);
7981 /* if they are the same size : or less */
7982 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7984 /* if they are in the same place */
7985 if (sameRegs(AOP(right),AOP(result)))
7988 /* if they in different places then copy */
7989 size = AOP_SIZE(result);
7991 _startLazyDPSEvaluation();
7994 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7998 _endLazyDPSEvaluation();
8003 /* if the result is of type pointer */
8004 if (IS_PTR(ctype)) {
8007 link *type = operandType(right);
8009 /* pointer to generic pointer */
8010 if (IS_GENPTR(ctype)) {
8015 p_type = DCL_TYPE(type);
8019 #if OLD_CAST_BEHAVIOR
8020 /* KV: we are converting a non-pointer type to
8021 * a generic pointer. This (ifdef'd out) code
8022 * says that the resulting generic pointer
8023 * should have the same class as the storage
8024 * location of the non-pointer variable.
8026 * For example, converting an int (which happens
8027 * to be stored in DATA space) to a pointer results
8028 * in a DATA generic pointer; if the original int
8029 * in XDATA space, so will be the resulting pointer.
8031 * I don't like that behavior, and thus this change:
8032 * all such conversions will be forced to XDATA and
8033 * throw a warning. If you want some non-XDATA
8034 * type, or you want to suppress the warning, you
8035 * must go through an intermediate cast, like so:
8037 * char _generic *gp = (char _xdata *)(intVar);
8039 link *etype = getSpec(type);
8041 /* we have to go by the storage class */
8042 if (SPEC_OCLS(etype) != generic)
8044 p_type = PTR_TYPE(SPEC_OCLS(etype));
8049 /* Converting unknown class (i.e. register variable)
8050 * to generic pointer. This is not good, but
8051 * we'll make a guess (and throw a warning).
8054 werror(W_INT_TO_GEN_PTR_CAST);
8058 /* the first two bytes are known */
8059 size = GPTRSIZE - 1;
8061 _startLazyDPSEvaluation();
8064 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8068 _endLazyDPSEvaluation();
8070 /* the last byte depending on type */
8087 /* this should never happen */
8088 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8089 "got unknown pointer type");
8092 aopPut(AOP(result),l, GPTRSIZE - 1);
8096 /* just copy the pointers */
8097 size = AOP_SIZE(result);
8099 _startLazyDPSEvaluation();
8102 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8106 _endLazyDPSEvaluation();
8110 /* so we now know that the size of destination is greater
8111 than the size of the source */
8112 /* we move to result for the size of source */
8113 size = AOP_SIZE(right);
8115 _startLazyDPSEvaluation();
8118 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8122 _endLazyDPSEvaluation();
8124 /* now depending on the sign of the source && destination */
8125 size = AOP_SIZE(result) - AOP_SIZE(right);
8126 /* if unsigned or not an integral type */
8127 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
8129 aopPut(AOP(result),zero,offset++);
8131 /* we need to extend the sign :{ */
8132 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8135 emitcode("rlc","a");
8136 emitcode("subb","a,acc");
8138 aopPut(AOP(result),"a",offset++);
8141 /* we are done hurray !!!! */
8144 freeAsmop(right,NULL,ic,TRUE);
8145 freeAsmop(result,NULL,ic,TRUE);
8149 /*-----------------------------------------------------------------*/
8150 /* genDjnz - generate decrement & jump if not zero instrucion */
8151 /*-----------------------------------------------------------------*/
8152 static int genDjnz (iCode *ic, iCode *ifx)
8158 /* if the if condition has a false label
8159 then we cannot save */
8163 /* if the minus is not of the form
8165 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8166 !IS_OP_LITERAL(IC_RIGHT(ic)))
8169 if (operandLitValue(IC_RIGHT(ic)) != 1)
8172 /* if the size of this greater than one then no
8174 if (getSize(operandType(IC_RESULT(ic))) > 1)
8177 /* otherwise we can save BIG */
8178 lbl = newiTempLabel(NULL);
8179 lbl1= newiTempLabel(NULL);
8181 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8183 if (IS_AOP_PREG(IC_RESULT(ic))) {
8184 emitcode("dec","%s",
8185 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8186 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8187 emitcode("jnz","%05d$",lbl->key+100);
8189 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8192 emitcode ("sjmp","%05d$",lbl1->key+100);
8193 emitcode ("","%05d$:",lbl->key+100);
8194 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8195 emitcode ("","%05d$:",lbl1->key+100);
8197 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8202 /*-----------------------------------------------------------------*/
8203 /* genReceive - generate code for a receive iCode */
8204 /*-----------------------------------------------------------------*/
8205 static void genReceive (iCode *ic)
8208 D(emitcode(";", "genReceive "););
8210 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8211 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8212 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8213 int size = getSize(operandType(IC_RESULT(ic)));
8214 int offset = fReturnSize_390 - size;
8216 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8217 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8220 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8221 size = AOP_SIZE(IC_RESULT(ic));
8224 emitcode ("pop","acc");
8225 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8230 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8232 assignResultValue(IC_RESULT(ic));
8235 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8238 /*-----------------------------------------------------------------*/
8239 /* gen390Code - generate code for 8051 based controllers */
8240 /*-----------------------------------------------------------------*/
8241 void gen390Code (iCode *lic)
8246 lineHead = lineCurr = NULL;
8248 /* print the allocation information */
8250 printAllocInfo( currFunc, codeOutFile);
8251 /* if debug information required */
8252 /* if (options.debug && currFunc) { */
8254 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8256 if (IS_STATIC(currFunc->etype))
8257 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8259 emitcode("","G$%s$0$0 ==.",currFunc->name);
8262 /* stack pointer name */
8263 if (options.useXstack)
8269 for (ic = lic ; ic ; ic = ic->next ) {
8271 if ( cln != ic->lineno ) {
8272 if ( options.debug ) {
8274 emitcode("","C$%s$%d$%d$%d ==.",
8275 ic->filename,ic->lineno,
8276 ic->level,ic->block);
8279 emitcode(";","%s %d",ic->filename,ic->lineno);
8282 /* if the result is marked as
8283 spilt and rematerializable or code for
8284 this has already been generated then
8286 if (resultRemat(ic) || ic->generated )
8289 /* depending on the operation */
8308 /* IPOP happens only when trying to restore a
8309 spilt live range, if there is an ifx statement
8310 following this pop then the if statement might
8311 be using some of the registers being popped which
8312 would destory the contents of the register so
8313 we need to check for this condition and handle it */
8315 ic->next->op == IFX &&
8316 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8317 genIfx (ic->next,ic);
8335 genEndFunction (ic);
8355 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8372 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8376 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8383 /* note these two are xlated by algebraic equivalence
8384 during parsing SDCC.y */
8385 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8386 "got '>=' or '<=' shouldn't have come here");
8390 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8402 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8406 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8410 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8437 case GET_VALUE_AT_ADDRESS:
8442 if (POINTER_SET(ic))
8469 addSet(&_G.sendSet,ic);
8474 /* piCode(ic,stdout); */
8480 /* now we are ready to call the
8481 peep hole optimizer */
8482 if (!options.nopeep)
8483 peepHole (&lineHead);
8485 /* now do the actual printing */
8486 printLine (lineHead,codeOutFile);