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...
2037 #define FAR_RETURN_OPT
2038 #ifdef FAR_RETURN_OPT
2039 if (isOperandInFarSpace(IC_RESULT(ic))
2040 && getSize(operandType(IC_RESULT(ic))) <= 2)
2042 int size = getSize(operandType(IC_RESULT(ic)));
2044 /* Special case for 1 or 2 byte return in far space. */
2045 emitcode(";", "Kevin function call abuse #1");
2050 emitcode("mov", "b,%s", fReturn[1]);
2053 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2054 aopPut(AOP(IC_RESULT(ic)),"a",0);
2058 aopPut(AOP(IC_RESULT(ic)),"b",1);
2060 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2066 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2069 assignResultValue(IC_RESULT(ic));
2071 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2074 if (!isOperandInFarSpace(IC_RESULT(ic)))
2077 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2080 assignResultValue(IC_RESULT(ic));
2082 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2086 /* Result is in far space, and requires DPTR to access
2087 * it. Push the result onto the stack and restore from
2090 int size = getSize(operandType(IC_RESULT(ic)));
2091 int offset = size - 1;
2094 emitcode(";", "Kevin function call abuse #1");
2096 /* first push the right side on to the stack */
2097 /* NB: this relies on the fact that "a" is the last
2098 * register in fReturn. If it were not, the MOVA
2099 * would potentially clobber a returned byte in A.
2102 l = fReturn[offset--];
2104 emitcode ("push","acc");
2107 /* now assign DPTR to result */
2108 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2109 size = AOP_SIZE(IC_RESULT(ic));
2110 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
2112 emitcode ("pop","acc");
2113 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
2115 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2120 /* adjust the stack for parameters if
2122 if (IC_LEFT(ic)->parmBytes) {
2124 if (IC_LEFT(ic)->parmBytes > 3) {
2125 emitcode("mov","a,%s",spname);
2126 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2127 emitcode("mov","%s,a",spname);
2129 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2130 emitcode("dec","%s",spname);
2134 /* if register bank was saved then pop them */
2136 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2138 /* if we hade saved some registers then unsave them */
2139 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2140 unsaveRegisters (ic);
2145 /*-----------------------------------------------------------------*/
2146 /* genPcall - generates a call by pointer statement */
2147 /*-----------------------------------------------------------------*/
2148 static void genPcall (iCode *ic)
2151 symbol *rlbl = newiTempLabel(NULL);
2153 D(emitcode(";", "genPcall "););
2156 /* if caller saves & we have not saved then */
2160 /* if we are calling a function that is not using
2161 the same register bank then we need to save the
2162 destination registers on the stack */
2163 detype = getSpec(operandType(IC_LEFT(ic)));
2165 IS_ISR(currFunc->etype) &&
2166 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2167 saverbank(SPEC_BANK(detype),ic,TRUE);
2170 /* push the return address on to the stack */
2171 emitcode("mov","a,#%05d$",(rlbl->key+100));
2172 emitcode("push","acc");
2173 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2174 emitcode("push","acc");
2176 if (options.model == MODEL_FLAT24)
2178 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2179 emitcode("push","acc");
2182 /* now push the calling address */
2183 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2185 pushSide(IC_LEFT(ic), FPTRSIZE);
2187 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2189 /* if send set is not empty the assign */
2193 for (sic = setFirstItem(_G.sendSet) ; sic ;
2194 sic = setNextItem(_G.sendSet))
2196 int size, offset = 0;
2198 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2199 size = AOP_SIZE(IC_LEFT(sic));
2200 _startLazyDPSEvaluation();
2203 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2205 if (strcmp(l,fReturn[offset]))
2207 emitcode("mov","%s,%s",
2213 _endLazyDPSEvaluation();
2214 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2220 emitcode("","%05d$:",(rlbl->key+100));
2223 /* if we need assign a result value */
2224 if ((IS_ITEMP(IC_RESULT(ic)) &&
2225 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2226 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2227 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2230 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2233 assignResultValue(IC_RESULT(ic));
2235 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2238 /* adjust the stack for parameters if
2240 if (IC_LEFT(ic)->parmBytes) {
2242 if (IC_LEFT(ic)->parmBytes > 3) {
2243 emitcode("mov","a,%s",spname);
2244 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2245 emitcode("mov","%s,a",spname);
2247 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2248 emitcode("dec","%s",spname);
2252 /* if register bank was saved then unsave them */
2254 (SPEC_BANK(currFunc->etype) !=
2256 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2258 /* if we hade saved some registers then
2261 unsaveRegisters (ic);
2265 /*-----------------------------------------------------------------*/
2266 /* resultRemat - result is rematerializable */
2267 /*-----------------------------------------------------------------*/
2268 static int resultRemat (iCode *ic)
2270 if (SKIP_IC(ic) || ic->op == IFX)
2273 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2274 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2275 if (sym->remat && !POINTER_SET(ic))
2283 #define STRCASECMP stricmp
2285 #define STRCASECMP strcasecmp
2288 /*-----------------------------------------------------------------*/
2289 /* inExcludeList - return 1 if the string is in exclude Reg list */
2290 /*-----------------------------------------------------------------*/
2291 static bool inExcludeList(char *s)
2295 if (options.excludeRegs[i] &&
2296 STRCASECMP(options.excludeRegs[i],"none") == 0)
2299 for ( i = 0 ; options.excludeRegs[i]; i++) {
2300 if (options.excludeRegs[i] &&
2301 STRCASECMP(s,options.excludeRegs[i]) == 0)
2307 /*-----------------------------------------------------------------*/
2308 /* genFunction - generated code for function entry */
2309 /*-----------------------------------------------------------------*/
2310 static void genFunction (iCode *ic)
2315 D(emitcode(";", "genFunction "););
2318 /* create the function header */
2319 emitcode(";","-----------------------------------------");
2320 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2321 emitcode(";","-----------------------------------------");
2323 emitcode("","%s:",sym->rname);
2324 fetype = getSpec(operandType(IC_LEFT(ic)));
2326 /* if critical function then turn interrupts off */
2327 if (SPEC_CRTCL(fetype))
2328 emitcode("clr","ea");
2330 /* here we need to generate the equates for the
2331 register bank if required */
2332 if (SPEC_BANK(fetype) != rbank) {
2335 rbank = SPEC_BANK(fetype);
2336 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2337 if (strcmp(regs390[i].base,"0") == 0)
2338 emitcode("","%s = 0x%02x",
2340 8*rbank+regs390[i].offset);
2342 emitcode ("","%s = %s + 0x%02x",
2345 8*rbank+regs390[i].offset);
2349 /* if this is an interrupt service routine then
2350 save acc, b, dpl, dph */
2351 if (IS_ISR(sym->etype)) {
2353 if (!inExcludeList("acc"))
2354 emitcode ("push","acc");
2355 if (!inExcludeList("b"))
2356 emitcode ("push","b");
2357 if (!inExcludeList("dpl"))
2358 emitcode ("push","dpl");
2359 if (!inExcludeList("dph"))
2360 emitcode ("push","dph");
2361 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2363 emitcode ("push", "dpx");
2364 /* Make sure we're using standard DPTR */
2365 emitcode ("push", "dps");
2366 emitcode ("mov", "dps, #0x00");
2367 if (options.stack10bit)
2369 /* This ISR could conceivably use DPTR2. Better save it. */
2370 emitcode ("push", "dpl1");
2371 emitcode ("push", "dph1");
2372 emitcode ("push", "dpx1");
2373 emitcode ("push", "ap");
2376 /* if this isr has no bank i.e. is going to
2377 run with bank 0 , then we need to save more
2379 if (!SPEC_BANK(sym->etype)) {
2381 /* if this function does not call any other
2382 function then we can be economical and
2383 save only those registers that are used */
2384 if (! sym->hasFcall) {
2387 /* if any registers used */
2388 if (sym->regsUsed) {
2389 /* save the registers used */
2390 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2391 if (bitVectBitValue(sym->regsUsed,i) ||
2392 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2393 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2398 /* this function has a function call cannot
2399 determines register usage so we will have the
2401 saverbank(0,ic,FALSE);
2405 /* if callee-save to be used for this function
2406 then save the registers being used in this function */
2407 if (sym->calleeSave) {
2410 /* if any registers used */
2411 if (sym->regsUsed) {
2412 /* save the registers used */
2413 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2414 if (bitVectBitValue(sym->regsUsed,i) ||
2415 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2416 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2424 /* set the register bank to the desired value */
2425 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2426 emitcode("push","psw");
2427 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2430 if (IS_RENT(sym->etype) || options.stackAuto) {
2432 if (options.useXstack) {
2433 emitcode("mov","r0,%s",spname);
2434 emitcode("mov","a,_bp");
2435 emitcode("movx","@r0,a");
2436 emitcode("inc","%s",spname);
2440 /* set up the stack */
2441 emitcode ("push","_bp"); /* save the callers stack */
2443 emitcode ("mov","_bp,%s",spname);
2446 /* adjust the stack for the function */
2451 werror(W_STACK_OVERFLOW,sym->name);
2453 if (i > 3 && sym->recvSize < 4) {
2455 emitcode ("mov","a,sp");
2456 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2457 emitcode ("mov","sp,a");
2462 emitcode("inc","sp");
2467 emitcode ("mov","a,_spx");
2468 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2469 emitcode ("mov","_spx,a");
2474 /*-----------------------------------------------------------------*/
2475 /* genEndFunction - generates epilogue for functions */
2476 /*-----------------------------------------------------------------*/
2477 static void genEndFunction (iCode *ic)
2479 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2481 D(emitcode(";", "genEndFunction "););
2483 if (IS_RENT(sym->etype) || options.stackAuto)
2485 emitcode ("mov","%s,_bp",spname);
2488 /* if use external stack but some variables were
2489 added to the local stack then decrement the
2491 if (options.useXstack && sym->stack) {
2492 emitcode("mov","a,sp");
2493 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2494 emitcode("mov","sp,a");
2498 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2499 if (options.useXstack) {
2500 emitcode("mov","r0,%s",spname);
2501 emitcode("movx","a,@r0");
2502 emitcode("mov","_bp,a");
2503 emitcode("dec","%s",spname);
2507 emitcode ("pop","_bp");
2511 /* restore the register bank */
2512 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2513 emitcode ("pop","psw");
2515 if (IS_ISR(sym->etype)) {
2517 /* now we need to restore the registers */
2518 /* if this isr has no bank i.e. is going to
2519 run with bank 0 , then we need to save more
2521 if (!SPEC_BANK(sym->etype)) {
2523 /* if this function does not call any other
2524 function then we can be economical and
2525 save only those registers that are used */
2526 if (! sym->hasFcall) {
2529 /* if any registers used */
2530 if (sym->regsUsed) {
2531 /* save the registers used */
2532 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2533 if (bitVectBitValue(sym->regsUsed,i) ||
2534 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2535 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2540 /* this function has a function call cannot
2541 determines register usage so we will have the
2543 unsaverbank(0,ic,FALSE);
2547 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2549 if (options.stack10bit)
2551 emitcode ("pop", "ap");
2552 emitcode ("pop", "dpx1");
2553 emitcode ("pop", "dph1");
2554 emitcode ("pop", "dpl1");
2556 emitcode ("pop", "dps");
2557 emitcode ("pop", "dpx");
2559 if (!inExcludeList("dph"))
2560 emitcode ("pop","dph");
2561 if (!inExcludeList("dpl"))
2562 emitcode ("pop","dpl");
2563 if (!inExcludeList("b"))
2564 emitcode ("pop","b");
2565 if (!inExcludeList("acc"))
2566 emitcode ("pop","acc");
2568 if (SPEC_CRTCL(sym->etype))
2569 emitcode("setb","ea");
2571 /* if debug then send end of function */
2572 /* if (options.debug && currFunc) { */
2575 emitcode("","C$%s$%d$%d$%d ==.",
2576 ic->filename,currFunc->lastLine,
2577 ic->level,ic->block);
2578 if (IS_STATIC(currFunc->etype))
2579 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2581 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2585 emitcode ("reti","");
2588 if (SPEC_CRTCL(sym->etype))
2589 emitcode("setb","ea");
2591 if (sym->calleeSave) {
2594 /* if any registers used */
2595 if (sym->regsUsed) {
2596 /* save the registers used */
2597 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2598 if (bitVectBitValue(sym->regsUsed,i) ||
2599 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2600 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2606 /* if debug then send end of function */
2609 emitcode("","C$%s$%d$%d$%d ==.",
2610 ic->filename,currFunc->lastLine,
2611 ic->level,ic->block);
2612 if (IS_STATIC(currFunc->etype))
2613 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2615 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2619 emitcode ("ret","");
2624 /*-----------------------------------------------------------------*/
2625 /* genRet - generate code for return statement */
2626 /*-----------------------------------------------------------------*/
2627 static void genRet (iCode *ic)
2629 int size,offset = 0 , pushed = 0;
2631 D(emitcode(";", "genRet "););
2633 /* if we have no return value then
2634 just generate the "ret" */
2638 /* we have something to return then
2639 move the return value into place */
2640 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2641 size = AOP_SIZE(IC_LEFT(ic));
2643 _startLazyDPSEvaluation();
2646 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2647 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2649 emitcode("push","%s",l);
2652 l = aopGet(AOP(IC_LEFT(ic)),offset,
2654 if (strcmp(fReturn[offset],l))
2655 emitcode("mov","%s,%s",fReturn[offset++],l);
2658 _endLazyDPSEvaluation();
2663 if (strcmp(fReturn[pushed],"a"))
2664 emitcode("pop",fReturn[pushed]);
2666 emitcode("pop","acc");
2669 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2672 /* generate a jump to the return label
2673 if the next is not the return statement */
2674 if (!(ic->next && ic->next->op == LABEL &&
2675 IC_LABEL(ic->next) == returnLabel))
2677 emitcode("ljmp","%05d$",(returnLabel->key+100));
2681 /*-----------------------------------------------------------------*/
2682 /* genLabel - generates a label */
2683 /*-----------------------------------------------------------------*/
2684 static void genLabel (iCode *ic)
2686 /* special case never generate */
2687 if (IC_LABEL(ic) == entryLabel)
2690 D(emitcode(";", "genLabel "););
2692 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2695 /*-----------------------------------------------------------------*/
2696 /* genGoto - generates a ljmp */
2697 /*-----------------------------------------------------------------*/
2698 static void genGoto (iCode *ic)
2700 D(emitcode(";", "genGoto "););
2701 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2704 /*-----------------------------------------------------------------*/
2705 /* findLabelBackwards: walks back through the iCode chain looking */
2706 /* for the given label. Returns number of iCode instructions */
2707 /* between that label and given ic. */
2708 /* Returns zero if label not found. */
2709 /*-----------------------------------------------------------------*/
2710 static int findLabelBackwards(iCode *ic, int key)
2719 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2721 /* printf("findLabelBackwards = %d\n", count); */
2729 /*-----------------------------------------------------------------*/
2730 /* genPlusIncr :- does addition with increment if possible */
2731 /*-----------------------------------------------------------------*/
2732 static bool genPlusIncr (iCode *ic)
2734 unsigned int icount ;
2735 unsigned int size = getDataSize(IC_RESULT(ic));
2737 /* will try to generate an increment */
2738 /* if the right side is not a literal
2740 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2743 /* if the literal value of the right hand side
2744 is greater than 4 then it is not worth it */
2745 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2748 /* if increment 16 bits in register */
2750 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2751 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2752 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2759 /* If the next instruction is a goto and the goto target
2760 * is <= 5 instructions previous to this, we can generate
2761 * jumps straight to that target.
2763 if (ic->next && ic->next->op == GOTO
2764 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2765 && labelRange <= 5 )
2767 emitcode(";", "tail increment optimized (range %d)", labelRange);
2768 tlbl = IC_LABEL(ic->next);
2773 tlbl = newiTempLabel(NULL);
2776 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2777 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2778 IS_AOP_PREG(IC_RESULT(ic)))
2779 emitcode("cjne","%s,#0x00,%05d$"
2780 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2783 emitcode("clr","a");
2784 emitcode("cjne","a,%s,%05d$"
2785 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2789 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2792 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2793 IS_AOP_PREG(IC_RESULT(ic)))
2794 emitcode("cjne","%s,#0x00,%05d$"
2795 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2798 emitcode("cjne","a,%s,%05d$"
2799 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2802 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2806 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2807 IS_AOP_PREG(IC_RESULT(ic)))
2808 emitcode("cjne","%s,#0x00,%05d$"
2809 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2812 emitcode("cjne","a,%s,%05d$"
2813 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2816 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2821 emitcode("","%05d$:",tlbl->key+100);
2826 /* if the sizes are greater than 1 then we cannot */
2827 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2828 AOP_SIZE(IC_LEFT(ic)) > 1 )
2831 /* we can if the aops of the left & result match or
2832 if they are in registers and the registers are the
2835 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2836 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2837 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2840 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2841 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2842 aopPut(AOP(IC_RESULT(ic)),"a",0);
2845 _startLazyDPSEvaluation();
2848 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2850 _endLazyDPSEvaluation();
2859 /*-----------------------------------------------------------------*/
2860 /* outBitAcc - output a bit in acc */
2861 /*-----------------------------------------------------------------*/
2862 static void outBitAcc(operand *result)
2864 symbol *tlbl = newiTempLabel(NULL);
2865 /* if the result is a bit */
2866 if (AOP_TYPE(result) == AOP_CRY){
2867 aopPut(AOP(result),"a",0);
2870 emitcode("jz","%05d$",tlbl->key+100);
2871 emitcode("mov","a,%s",one);
2872 emitcode("","%05d$:",tlbl->key+100);
2877 /*-----------------------------------------------------------------*/
2878 /* genPlusBits - generates code for addition of two bits */
2879 /*-----------------------------------------------------------------*/
2880 static void genPlusBits (iCode *ic)
2882 D(emitcode(";", "genPlusBits "););
2883 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2884 symbol *lbl = newiTempLabel(NULL);
2885 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2886 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2887 emitcode("cpl","c");
2888 emitcode("","%05d$:",(lbl->key+100));
2889 outBitC(IC_RESULT(ic));
2892 emitcode("clr","a");
2893 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2894 emitcode("rlc","a");
2895 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2896 emitcode("addc","a,#0x00");
2897 outAcc(IC_RESULT(ic));
2901 static void adjustArithmeticResult(iCode *ic)
2903 if (opIsGptr(IC_RESULT(ic)) &&
2904 opIsGptr(IC_LEFT(ic)) &&
2905 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2907 aopPut(AOP(IC_RESULT(ic)),
2908 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2912 if (opIsGptr(IC_RESULT(ic)) &&
2913 opIsGptr(IC_RIGHT(ic)) &&
2914 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2916 aopPut(AOP(IC_RESULT(ic)),
2917 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2921 if (opIsGptr(IC_RESULT(ic)) &&
2922 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2923 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2924 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2925 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2927 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2928 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2932 #define AOP_OP_3(ic) \
2933 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2934 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2935 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2936 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2937 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2939 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2941 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2944 #define AOP_SET_LOCALS(ic) \
2945 left = IC_LEFT(ic); \
2946 right = IC_RIGHT(ic); \
2947 result = IC_RESULT(ic);
2949 /*-----------------------------------------------------------------*/
2950 /* genPlus - generates code for addition */
2951 /*-----------------------------------------------------------------*/
2952 static void genPlus (iCode *ic)
2954 int size, offset = 0;
2955 bool pushResult = FALSE;
2958 D(emitcode(";", "genPlus "););
2960 /* special cases :- */
2963 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2964 aopOp (IC_LEFT(ic),ic,FALSE,
2965 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
2967 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2968 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2970 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2971 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2977 aopOp (IC_RESULT(ic),ic,TRUE,
2978 ((AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)
2979 || (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR)));
2981 /* if literal, literal on the right or
2982 if left requires ACC or right is already
2984 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2985 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2986 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2987 operand *t = IC_RIGHT(ic);
2988 IC_RIGHT(ic) = IC_LEFT(ic);
2992 /* if both left & right are in bit
2994 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2995 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3000 /* if left in bit space & right literal */
3001 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3002 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3003 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3004 /* if result in bit space */
3005 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3006 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
3007 emitcode("cpl","c");
3008 outBitC(IC_RESULT(ic));
3010 size = getDataSize(IC_RESULT(ic));
3011 _startLazyDPSEvaluation();
3013 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3014 emitcode("addc","a,#00");
3015 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3017 _endLazyDPSEvaluation();
3022 /* if I can do an increment instead
3023 of add then GOOD for ME */
3024 if (genPlusIncr (ic) == TRUE)
3028 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3030 _startLazyDPSEvaluation();
3033 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3035 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3037 emitcode("add","a,%s",
3038 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3040 emitcode("addc","a,%s",
3041 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3043 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3045 emitcode("add","a,%s",
3046 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3048 emitcode("addc","a,%s",
3049 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3053 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3057 emitcode("push", "acc");
3061 _endLazyDPSEvaluation();
3065 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3067 size = getDataSize(IC_LEFT(ic));
3068 rSize = getDataSize(IC_RESULT(ic));
3070 /* If the pushed data is bigger than the result,
3071 * simply discard unused bytes. Icky, but works.
3073 * Should we throw a warning here? We're losing data...
3075 while (size > rSize)
3077 D(emitcode(";", "discarding unused result byte."););
3078 emitcode("pop", "acc");
3084 emitcode("clr", "a");
3085 /* Conversly, we haven't pushed enough here.
3086 * just zero-pad, and all is well.
3088 while (size < rSize)
3090 emitcode("push", "acc");
3096 _startLazyDPSEvaluation();
3099 emitcode("pop", "acc");
3100 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3102 _endLazyDPSEvaluation();
3105 adjustArithmeticResult(ic);
3108 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3109 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3110 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3113 /*-----------------------------------------------------------------*/
3114 /* genMinusDec :- does subtraction with deccrement if possible */
3115 /*-----------------------------------------------------------------*/
3116 static bool genMinusDec (iCode *ic)
3118 unsigned int icount ;
3119 unsigned int size = getDataSize(IC_RESULT(ic));
3121 /* will try to generate an increment */
3122 /* if the right side is not a literal
3124 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3127 /* if the literal value of the right hand side
3128 is greater than 4 then it is not worth it */
3129 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3132 /* if decrement 16 bits in register */
3133 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3134 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3135 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3142 /* If the next instruction is a goto and the goto target
3143 * is <= 5 instructions previous to this, we can generate
3144 * jumps straight to that target.
3146 if (ic->next && ic->next->op == GOTO
3147 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3148 && labelRange <= 5 )
3150 emitcode(";", "tail decrement optimized (range %d)", labelRange);
3151 tlbl = IC_LABEL(ic->next);
3156 tlbl = newiTempLabel(NULL);
3160 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3161 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3162 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3163 IS_AOP_PREG(IC_RESULT(ic)))
3164 emitcode("cjne","%s,#0xff,%05d$"
3165 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3168 emitcode("mov","a,#0xff");
3169 emitcode("cjne","a,%s,%05d$"
3170 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3173 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3176 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3177 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3178 IS_AOP_PREG(IC_RESULT(ic)))
3179 emitcode("cjne","%s,#0xff,%05d$"
3180 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3183 emitcode("cjne","a,%s,%05d$"
3184 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3187 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3191 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3192 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3193 IS_AOP_PREG(IC_RESULT(ic)))
3194 emitcode("cjne","%s,#0xff,%05d$"
3195 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3198 emitcode("cjne","a,%s,%05d$"
3199 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3202 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3206 emitcode("","%05d$:",tlbl->key+100);
3211 /* if the sizes are greater than 1 then we cannot */
3212 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3213 AOP_SIZE(IC_LEFT(ic)) > 1 )
3216 /* we can if the aops of the left & result match or
3217 if they are in registers and the registers are the
3220 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3221 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3222 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3224 _startLazyDPSEvaluation();
3227 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3229 _endLazyDPSEvaluation();
3237 /*-----------------------------------------------------------------*/
3238 /* addSign - complete with sign */
3239 /*-----------------------------------------------------------------*/
3240 static void addSign(operand *result, int offset, int sign)
3242 int size = (getDataSize(result) - offset);
3245 emitcode("rlc","a");
3246 emitcode("subb","a,acc");
3248 aopPut(AOP(result),"a",offset++);
3251 aopPut(AOP(result),zero,offset++);
3255 /*-----------------------------------------------------------------*/
3256 /* genMinusBits - generates code for subtraction of two bits */
3257 /*-----------------------------------------------------------------*/
3258 static void genMinusBits (iCode *ic)
3260 symbol *lbl = newiTempLabel(NULL);
3262 D(emitcode(";", "genMinusBits "););
3264 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3265 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3266 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3267 emitcode("cpl","c");
3268 emitcode("","%05d$:",(lbl->key+100));
3269 outBitC(IC_RESULT(ic));
3272 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3273 emitcode("subb","a,acc");
3274 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3275 emitcode("inc","a");
3276 emitcode("","%05d$:",(lbl->key+100));
3277 aopPut(AOP(IC_RESULT(ic)),"a",0);
3278 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3282 /*-----------------------------------------------------------------*/
3283 /* genMinus - generates code for subtraction */
3284 /*-----------------------------------------------------------------*/
3285 static void genMinus (iCode *ic)
3287 int size, offset = 0;
3289 unsigned long lit = 0L;
3290 bool pushResult = FALSE;
3292 D(emitcode(";", "genMinus "););
3294 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3295 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3296 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3297 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3303 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3305 /* special cases :- */
3306 /* if both left & right are in bit space */
3307 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3308 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3313 /* if I can do an decrement instead
3314 of subtract then GOOD for ME */
3315 if (genMinusDec (ic) == TRUE)
3320 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3322 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3326 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3331 /* if literal, add a,#-lit, else normal subb */
3332 _startLazyDPSEvaluation();
3334 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3335 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3336 emitcode("subb","a,%s",
3337 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3339 /* first add without previous c */
3341 emitcode("add","a,#0x%02x",
3342 (unsigned int)(lit & 0x0FFL));
3344 emitcode("addc","a,#0x%02x",
3345 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3350 emitcode("push", "acc");
3354 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3358 _endLazyDPSEvaluation();
3362 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3364 size = getDataSize(IC_LEFT(ic));
3365 rSize = getDataSize(IC_RESULT(ic));
3367 /* If the pushed data is bigger than the result,
3368 * simply discard unused bytes. Icky, but works.
3370 * Should we throw a warning here? We're losing data...
3372 while (size > getDataSize(IC_RESULT(ic)))
3374 emitcode(";", "discarding unused result byte.");
3375 emitcode("pop", "acc");
3381 emitcode("clr", "a");
3382 /* Conversly, we haven't pushed enough here.
3383 * just zero-pad, and all is well.
3385 while (size < rSize)
3387 emitcode("push", "acc");
3395 emitcode("pop", "acc");
3396 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3400 adjustArithmeticResult(ic);
3403 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3404 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3405 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3409 /*-----------------------------------------------------------------*/
3410 /* genMultbits :- multiplication of bits */
3411 /*-----------------------------------------------------------------*/
3412 static void genMultbits (operand *left,
3416 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3417 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3422 /*-----------------------------------------------------------------*/
3423 /* genMultOneByte : 8 bit multiplication & division */
3424 /*-----------------------------------------------------------------*/
3425 static void genMultOneByte (operand *left,
3429 link *opetype = operandType(result);
3434 /* (if two literals, the value is computed before) */
3435 /* if one literal, literal on the right */
3436 if (AOP_TYPE(left) == AOP_LIT){
3442 size = AOP_SIZE(result);
3443 /* signed or unsigned */
3444 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3445 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3447 emitcode("mul","ab");
3448 /* if result size = 1, mul signed = mul unsigned */
3449 aopPut(AOP(result),"a",0);
3451 if (SPEC_USIGN(opetype)){
3452 aopPut(AOP(result),"b",1);
3454 /* for filling the MSBs */
3455 emitcode("clr","a");
3458 emitcode("mov","a,b");
3460 /* adjust the MSB if left or right neg */
3462 /* if one literal */
3463 if (AOP_TYPE(right) == AOP_LIT){
3464 /* AND literal negative */
3465 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3466 /* adjust MSB (c==0 after mul) */
3467 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3471 lbl = newiTempLabel(NULL);
3472 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3473 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3474 emitcode("","%05d$:",(lbl->key+100));
3475 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3476 lbl = newiTempLabel(NULL);
3477 emitcode("jc","%05d$",(lbl->key+100));
3478 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3479 emitcode("","%05d$:",(lbl->key+100));
3482 lbl = newiTempLabel(NULL);
3483 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3484 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3485 emitcode("","%05d$:",(lbl->key+100));
3486 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3487 lbl = newiTempLabel(NULL);
3488 emitcode("jc","%05d$",(lbl->key+100));
3489 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3490 emitcode("","%05d$:",(lbl->key+100));
3492 aopPut(AOP(result),"a",1);
3495 emitcode("rlc","a");
3496 emitcode("subb","a,acc");
3503 aopPut(AOP(result),"a",offset++);
3507 /*-----------------------------------------------------------------*/
3508 /* genMult - generates code for multiplication */
3509 /*-----------------------------------------------------------------*/
3510 static void genMult (iCode *ic)
3512 operand *left = IC_LEFT(ic);
3513 operand *right = IC_RIGHT(ic);
3514 operand *result= IC_RESULT(ic);
3516 D(emitcode(";", "genMult "););
3518 /* assign the amsops */
3521 aopOp (left,ic,FALSE, FALSE);
3522 aopOp (right,ic,FALSE, TRUE);
3523 aopOp (result,ic,TRUE, FALSE);
3526 /* special cases first */
3528 if (AOP_TYPE(left) == AOP_CRY &&
3529 AOP_TYPE(right)== AOP_CRY) {
3530 genMultbits(left,right,result);
3534 /* if both are of size == 1 */
3535 if (AOP_SIZE(left) == 1 &&
3536 AOP_SIZE(right) == 1 ) {
3537 genMultOneByte(left,right,result);
3541 /* should have been converted to function call */
3545 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3546 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3547 freeAsmop(result,NULL,ic,TRUE);
3550 /*-----------------------------------------------------------------*/
3551 /* genDivbits :- division of bits */
3552 /*-----------------------------------------------------------------*/
3553 static void genDivbits (operand *left,
3560 /* the result must be bit */
3561 LOAD_AB_FOR_DIV(left, right, l);
3562 emitcode("div","ab");
3563 emitcode("rrc","a");
3564 aopPut(AOP(result),"c",0);
3567 /*-----------------------------------------------------------------*/
3568 /* genDivOneByte : 8 bit division */
3569 /*-----------------------------------------------------------------*/
3570 static void genDivOneByte (operand *left,
3574 link *opetype = operandType(result);
3579 size = AOP_SIZE(result) - 1;
3581 /* signed or unsigned */
3582 if (SPEC_USIGN(opetype)) {
3583 /* unsigned is easy */
3584 LOAD_AB_FOR_DIV(left, right, l);
3585 emitcode("div","ab");
3586 aopPut(AOP(result),"a",0);
3588 aopPut(AOP(result),zero,offset++);
3592 /* signed is a little bit more difficult */
3594 /* save the signs of the operands */
3595 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3597 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3598 emitcode("push","acc"); /* save it on the stack */
3600 /* now sign adjust for both left & right */
3601 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3603 lbl = newiTempLabel(NULL);
3604 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3605 emitcode("cpl","a");
3606 emitcode("inc","a");
3607 emitcode("","%05d$:",(lbl->key+100));
3608 emitcode("mov","b,a");
3610 /* sign adjust left side */
3611 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3614 lbl = newiTempLabel(NULL);
3615 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3616 emitcode("cpl","a");
3617 emitcode("inc","a");
3618 emitcode("","%05d$:",(lbl->key+100));
3620 /* now the division */
3621 emitcode("nop", "; workaround for DS80C390 div bug.");
3622 emitcode("div","ab");
3623 /* we are interested in the lower order
3625 emitcode("mov","b,a");
3626 lbl = newiTempLabel(NULL);
3627 emitcode("pop","acc");
3628 /* if there was an over flow we don't
3629 adjust the sign of the result */
3630 emitcode("jb","ov,%05d$",(lbl->key+100));
3631 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3633 emitcode("clr","a");
3634 emitcode("subb","a,b");
3635 emitcode("mov","b,a");
3636 emitcode("","%05d$:",(lbl->key+100));
3638 /* now we are done */
3639 aopPut(AOP(result),"b",0);
3641 emitcode("mov","c,b.7");
3642 emitcode("subb","a,acc");
3645 aopPut(AOP(result),"a",offset++);
3649 /*-----------------------------------------------------------------*/
3650 /* genDiv - generates code for division */
3651 /*-----------------------------------------------------------------*/
3652 static void genDiv (iCode *ic)
3654 operand *left = IC_LEFT(ic);
3655 operand *right = IC_RIGHT(ic);
3656 operand *result= IC_RESULT(ic);
3658 D(emitcode(";", "genDiv "););
3660 /* assign the amsops */
3663 aopOp (left,ic,FALSE, FALSE);
3664 aopOp (right,ic,FALSE, TRUE);
3665 aopOp (result,ic,TRUE, FALSE);
3668 /* special cases first */
3670 if (AOP_TYPE(left) == AOP_CRY &&
3671 AOP_TYPE(right)== AOP_CRY) {
3672 genDivbits(left,right,result);
3676 /* if both are of size == 1 */
3677 if (AOP_SIZE(left) == 1 &&
3678 AOP_SIZE(right) == 1 ) {
3679 genDivOneByte(left,right,result);
3683 /* should have been converted to function call */
3686 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3687 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3688 freeAsmop(result,NULL,ic,TRUE);
3691 /*-----------------------------------------------------------------*/
3692 /* genModbits :- modulus of bits */
3693 /*-----------------------------------------------------------------*/
3694 static void genModbits (operand *left,
3701 /* the result must be bit */
3702 LOAD_AB_FOR_DIV(left, right, l);
3703 emitcode("div","ab");
3704 emitcode("mov","a,b");
3705 emitcode("rrc","a");
3706 aopPut(AOP(result),"c",0);
3709 /*-----------------------------------------------------------------*/
3710 /* genModOneByte : 8 bit modulus */
3711 /*-----------------------------------------------------------------*/
3712 static void genModOneByte (operand *left,
3716 link *opetype = operandType(result);
3720 /* signed or unsigned */
3721 if (SPEC_USIGN(opetype)) {
3722 /* unsigned is easy */
3723 LOAD_AB_FOR_DIV(left, right, l);
3724 emitcode("div","ab");
3725 aopPut(AOP(result),"b",0);
3729 /* signed is a little bit more difficult */
3731 /* save the signs of the operands */
3732 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3735 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3736 emitcode("push","acc"); /* save it on the stack */
3738 /* now sign adjust for both left & right */
3739 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3742 lbl = newiTempLabel(NULL);
3743 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3744 emitcode("cpl","a");
3745 emitcode("inc","a");
3746 emitcode("","%05d$:",(lbl->key+100));
3747 emitcode("mov","b,a");
3749 /* sign adjust left side */
3750 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3753 lbl = newiTempLabel(NULL);
3754 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3755 emitcode("cpl","a");
3756 emitcode("inc","a");
3757 emitcode("","%05d$:",(lbl->key+100));
3759 /* now the multiplication */
3760 emitcode("nop", "; workaround for DS80C390 div bug.");
3761 emitcode("div","ab");
3762 /* we are interested in the lower order
3764 lbl = newiTempLabel(NULL);
3765 emitcode("pop","acc");
3766 /* if there was an over flow we don't
3767 adjust the sign of the result */
3768 emitcode("jb","ov,%05d$",(lbl->key+100));
3769 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3771 emitcode("clr","a");
3772 emitcode("subb","a,b");
3773 emitcode("mov","b,a");
3774 emitcode("","%05d$:",(lbl->key+100));
3776 /* now we are done */
3777 aopPut(AOP(result),"b",0);
3781 /*-----------------------------------------------------------------*/
3782 /* genMod - generates code for division */
3783 /*-----------------------------------------------------------------*/
3784 static void genMod (iCode *ic)
3786 operand *left = IC_LEFT(ic);
3787 operand *right = IC_RIGHT(ic);
3788 operand *result= IC_RESULT(ic);
3790 D(emitcode(";", "genMod "););
3792 /* assign the amsops */
3795 aopOp (left,ic,FALSE, FALSE);
3796 aopOp (right,ic,FALSE, TRUE);
3797 aopOp (result,ic,TRUE, FALSE);
3800 /* special cases first */
3802 if (AOP_TYPE(left) == AOP_CRY &&
3803 AOP_TYPE(right)== AOP_CRY) {
3804 genModbits(left,right,result);
3808 /* if both are of size == 1 */
3809 if (AOP_SIZE(left) == 1 &&
3810 AOP_SIZE(right) == 1 ) {
3811 genModOneByte(left,right,result);
3815 /* should have been converted to function call */
3819 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3820 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3821 freeAsmop(result,NULL,ic,TRUE);
3824 /*-----------------------------------------------------------------*/
3825 /* genIfxJump :- will create a jump depending on the ifx */
3826 /*-----------------------------------------------------------------*/
3827 static void genIfxJump (iCode *ic, char *jval)
3830 symbol *tlbl = newiTempLabel(NULL);
3833 D(emitcode(";", "genIfxJump "););
3835 /* if true label then we jump if condition
3837 if ( IC_TRUE(ic) ) {
3839 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3840 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3843 /* false label is present */
3844 jlbl = IC_FALSE(ic) ;
3845 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3846 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3848 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3849 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3851 emitcode(inst,"%05d$",tlbl->key+100);
3852 emitcode("ljmp","%05d$",jlbl->key+100);
3853 emitcode("","%05d$:",tlbl->key+100);
3855 /* mark the icode as generated */
3859 /*-----------------------------------------------------------------*/
3860 /* genCmp :- greater or less than comparison */
3861 /*-----------------------------------------------------------------*/
3862 static void genCmp (operand *left,operand *right,
3863 operand *result, iCode *ifx, int sign)
3865 int size, offset = 0 ;
3866 unsigned long lit = 0L;
3867 bool swappedOps = FALSE;
3869 D(emitcode(";", "genCmp"););
3872 /* If left if lit and right isn't, swap 'em. */
3873 if (AOP_TYPE(left) == AOP_LIT &&
3874 AOP_TYPE(right) != AOP_LIT)
3876 operand *tmp = left;
3879 D(emitcode(";", "kevin literal hack"););
3880 swappedOps = !swappedOps;
3883 if (AOP_NEEDSACC(right))
3885 if (AOP_NEEDSACC(left))
3887 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3888 "both CMP operands need ACC!");
3893 operand *tmp = left;
3896 D(emitcode(";", "kevin ACC hack"););
3897 swappedOps = !swappedOps;
3902 /* if left & right are bit variables */
3903 if (AOP_TYPE(left) == AOP_CRY &&
3904 AOP_TYPE(right) == AOP_CRY ) {
3905 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3906 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3908 /* subtract right from left if at the
3909 end the carry flag is set then we know that
3910 left is greater than right */
3911 size = max(AOP_SIZE(left),AOP_SIZE(right));
3913 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3914 if((size == 1) && !sign &&
3915 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3916 symbol *lbl = newiTempLabel(NULL);
3917 emitcode("cjne","%s,%s,%05d$",
3918 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3919 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3921 emitcode("","%05d$:",lbl->key+100);
3923 if(AOP_TYPE(right) == AOP_LIT){
3924 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3925 /* optimize if(x < 0) or if(x >= 0) */
3931 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3932 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3933 genIfxJump (ifx,"acc.7");
3937 emitcode("rlc","a");
3945 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3946 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3947 emitcode(";", "genCmp #2");
3948 if (sign && (size == 0))
3950 emitcode(";", "genCmp #3");
3951 emitcode("xrl","a,#0x80");
3952 if (AOP_TYPE(right) == AOP_LIT)
3954 unsigned long lit = (unsigned long)
3955 floatFromVal(AOP(right)->aopu.aop_lit);
3956 emitcode(";", "genCmp #3.1");
3957 emitcode("subb","a,#0x%02x",
3958 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3962 emitcode(";", "genCmp #3.2");
3963 if (AOP_NEEDSACC(right))
3965 emitcode("push", "acc");
3967 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3968 FALSE,FALSE,FALSE));
3969 emitcode("xrl","b,#0x80");
3970 if (AOP_NEEDSACC(right))
3972 emitcode("pop", "acc");
3974 emitcode("subb","a,b");
3981 emitcode(";", "genCmp #4");
3982 if (AOP_NEEDSACC(right))
3985 emitcode(";", "genCmp #4.1");
3986 emitcode("xch", "a, b");
3987 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3988 emitcode("xch", "a, b");
3993 emitcode(";", "genCmp #4.2");
3994 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
3997 emitcode("subb","a,%s",s);
4006 D(emitcode(";","kevHack: flip carry."););
4007 emitcode("cpl", "c");
4010 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4013 /* if the result is used in the next
4014 ifx conditional branch then generate
4015 code a little differently */
4017 genIfxJump (ifx,"c");
4020 /* leave the result in acc */
4024 /*-----------------------------------------------------------------*/
4025 /* genCmpGt :- greater than comparison */
4026 /*-----------------------------------------------------------------*/
4027 static void genCmpGt (iCode *ic, iCode *ifx)
4029 operand *left, *right, *result;
4030 link *letype , *retype;
4033 D(emitcode(";", "genCmpGt "););
4036 right= IC_RIGHT(ic);
4037 result = IC_RESULT(ic);
4039 letype = getSpec(operandType(left));
4040 retype =getSpec(operandType(right));
4041 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4042 /* assign the amsops */
4045 aopOp (left,ic,FALSE, TRUE);
4046 aopOp (right,ic,FALSE, FALSE);
4047 aopOp (result,ic,TRUE, FALSE);
4050 genCmp(right, left, result, ifx, sign);
4052 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4053 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4054 freeAsmop(result,NULL,ic,TRUE);
4057 /*-----------------------------------------------------------------*/
4058 /* genCmpLt - less than comparisons */
4059 /*-----------------------------------------------------------------*/
4060 static void genCmpLt (iCode *ic, iCode *ifx)
4062 operand *left, *right, *result;
4063 link *letype , *retype;
4066 D(emitcode(";", "genCmpLt "););
4069 right= IC_RIGHT(ic);
4070 result = IC_RESULT(ic);
4072 letype = getSpec(operandType(left));
4073 retype =getSpec(operandType(right));
4074 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4076 /* assign the amsops */
4079 aopOp (left,ic,FALSE, FALSE);
4080 aopOp (right,ic,FALSE, TRUE);
4081 aopOp (result,ic,TRUE, FALSE);
4084 genCmp(left, right, result, ifx, sign);
4086 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4087 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4088 freeAsmop(result,NULL,ic,TRUE);
4091 /*-----------------------------------------------------------------*/
4092 /* gencjneshort - compare and jump if not equal */
4093 /*-----------------------------------------------------------------*/
4094 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4096 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4098 unsigned long lit = 0L;
4100 D(emitcode(";", "gencjneshort"););
4102 /* if the left side is a literal or
4103 if the right is in a pointer register and left
4105 if ((AOP_TYPE(left) == AOP_LIT) ||
4106 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4112 if(AOP_TYPE(right) == AOP_LIT)
4113 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4115 if (opIsGptr(left) || opIsGptr(right))
4117 /* We are comparing a generic pointer to something.
4118 * Exclude the generic type byte from the comparison.
4121 D(emitcode(";", "cjneshort: generic ptr special case.");)
4125 /* if the right side is a literal then anything goes */
4126 if (AOP_TYPE(right) == AOP_LIT &&
4127 AOP_TYPE(left) != AOP_DIR ) {
4129 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4131 emitcode("cjne","a,%s,%05d$",
4132 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4138 /* if the right side is in a register or in direct space or
4139 if the left is a pointer register & right is not */
4140 else if (AOP_TYPE(right) == AOP_REG ||
4141 AOP_TYPE(right) == AOP_DIR ||
4142 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4143 (IS_AOP_PREG(left) && !IS_AOP_PREG(right)))
4147 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4148 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4149 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4150 emitcode("jnz","%05d$",lbl->key+100);
4152 emitcode("cjne","a,%s,%05d$",
4153 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4158 /* right is a pointer reg need both a & b */
4160 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4162 emitcode("mov","b,%s",l);
4163 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4164 emitcode("cjne","a,b,%05d$",lbl->key+100);
4170 /*-----------------------------------------------------------------*/
4171 /* gencjne - compare and jump if not equal */
4172 /*-----------------------------------------------------------------*/
4173 static void gencjne(operand *left, operand *right, symbol *lbl)
4175 symbol *tlbl = newiTempLabel(NULL);
4177 D(emitcode(";", "gencjne"););
4179 gencjneshort(left, right, lbl);
4181 emitcode("mov","a,%s",one);
4182 emitcode("sjmp","%05d$",tlbl->key+100);
4183 emitcode("","%05d$:",lbl->key+100);
4184 emitcode("clr","a");
4185 emitcode("","%05d$:",tlbl->key+100);
4188 /*-----------------------------------------------------------------*/
4189 /* genCmpEq - generates code for equal to */
4190 /*-----------------------------------------------------------------*/
4191 static void genCmpEq (iCode *ic, iCode *ifx)
4193 operand *left, *right, *result;
4195 D(emitcode(";", "genCmpEq "););
4200 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4201 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4202 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4205 /* if literal, literal on the right or
4206 if the right is in a pointer register and left
4208 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4209 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4210 operand *t = IC_RIGHT(ic);
4211 IC_RIGHT(ic) = IC_LEFT(ic);
4215 if(ifx && !AOP_SIZE(result)){
4217 /* if they are both bit variables */
4218 if (AOP_TYPE(left) == AOP_CRY &&
4219 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4220 if(AOP_TYPE(right) == AOP_LIT){
4221 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4223 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4224 emitcode("cpl","c");
4225 } else if(lit == 1L) {
4226 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4228 emitcode("clr","c");
4230 /* AOP_TYPE(right) == AOP_CRY */
4232 symbol *lbl = newiTempLabel(NULL);
4233 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4234 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4235 emitcode("cpl","c");
4236 emitcode("","%05d$:",(lbl->key+100));
4238 /* if true label then we jump if condition
4240 tlbl = newiTempLabel(NULL);
4241 if ( IC_TRUE(ifx) ) {
4242 emitcode("jnc","%05d$",tlbl->key+100);
4243 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4245 emitcode("jc","%05d$",tlbl->key+100);
4246 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4248 emitcode("","%05d$:",tlbl->key+100);
4250 tlbl = newiTempLabel(NULL);
4251 gencjneshort(left, right, tlbl);
4252 if ( IC_TRUE(ifx) ) {
4253 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4254 emitcode("","%05d$:",tlbl->key+100);
4256 symbol *lbl = newiTempLabel(NULL);
4257 emitcode("sjmp","%05d$",lbl->key+100);
4258 emitcode("","%05d$:",tlbl->key+100);
4259 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4260 emitcode("","%05d$:",lbl->key+100);
4263 /* mark the icode as generated */
4268 /* if they are both bit variables */
4269 if (AOP_TYPE(left) == AOP_CRY &&
4270 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4271 if(AOP_TYPE(right) == AOP_LIT){
4272 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4274 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4275 emitcode("cpl","c");
4276 } else if(lit == 1L) {
4277 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4279 emitcode("clr","c");
4281 /* AOP_TYPE(right) == AOP_CRY */
4283 symbol *lbl = newiTempLabel(NULL);
4284 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4285 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4286 emitcode("cpl","c");
4287 emitcode("","%05d$:",(lbl->key+100));
4290 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4295 genIfxJump (ifx,"c");
4298 /* if the result is used in an arithmetic operation
4299 then put the result in place */
4302 gencjne(left,right,newiTempLabel(NULL));
4303 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4304 aopPut(AOP(result),"a",0);
4308 genIfxJump (ifx,"a");
4311 /* if the result is used in an arithmetic operation
4312 then put the result in place */
4313 if (AOP_TYPE(result) != AOP_CRY)
4315 /* leave the result in acc */
4319 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4320 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4321 freeAsmop(result,NULL,ic,TRUE);
4324 /*-----------------------------------------------------------------*/
4325 /* ifxForOp - returns the icode containing the ifx for operand */
4326 /*-----------------------------------------------------------------*/
4327 static iCode *ifxForOp ( operand *op, iCode *ic )
4329 /* if true symbol then needs to be assigned */
4330 if (IS_TRUE_SYMOP(op))
4333 /* if this has register type condition and
4334 the next instruction is ifx with the same operand
4335 and live to of the operand is upto the ifx only then */
4337 ic->next->op == IFX &&
4338 IC_COND(ic->next)->key == op->key &&
4339 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4344 /*-----------------------------------------------------------------*/
4345 /* genAndOp - for && operation */
4346 /*-----------------------------------------------------------------*/
4347 static void genAndOp (iCode *ic)
4349 operand *left,*right, *result;
4352 D(emitcode(";", "genAndOp "););
4354 /* note here that && operations that are in an
4355 if statement are taken away by backPatchLabels
4356 only those used in arthmetic operations remain */
4360 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4361 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4362 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4365 /* if both are bit variables */
4366 if (AOP_TYPE(left) == AOP_CRY &&
4367 AOP_TYPE(right) == AOP_CRY ) {
4368 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4369 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4372 tlbl = newiTempLabel(NULL);
4374 emitcode("jz","%05d$",tlbl->key+100);
4376 emitcode("","%05d$:",tlbl->key+100);
4380 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4381 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4382 freeAsmop(result,NULL,ic,TRUE);
4386 /*-----------------------------------------------------------------*/
4387 /* genOrOp - for || operation */
4388 /*-----------------------------------------------------------------*/
4389 static void genOrOp (iCode *ic)
4391 operand *left,*right, *result;
4394 D(emitcode(";", "genOrOp "););
4396 /* note here that || operations that are in an
4397 if statement are taken away by backPatchLabels
4398 only those used in arthmetic operations remain */
4402 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4403 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4404 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4407 /* if both are bit variables */
4408 if (AOP_TYPE(left) == AOP_CRY &&
4409 AOP_TYPE(right) == AOP_CRY ) {
4410 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4411 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4414 tlbl = newiTempLabel(NULL);
4416 emitcode("jnz","%05d$",tlbl->key+100);
4418 emitcode("","%05d$:",tlbl->key+100);
4422 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4423 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4424 freeAsmop(result,NULL,ic,TRUE);
4427 /*-----------------------------------------------------------------*/
4428 /* isLiteralBit - test if lit == 2^n */
4429 /*-----------------------------------------------------------------*/
4430 static int isLiteralBit(unsigned long lit)
4432 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4433 0x100L,0x200L,0x400L,0x800L,
4434 0x1000L,0x2000L,0x4000L,0x8000L,
4435 0x10000L,0x20000L,0x40000L,0x80000L,
4436 0x100000L,0x200000L,0x400000L,0x800000L,
4437 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4438 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4441 for(idx = 0; idx < 32; idx++)
4447 /*-----------------------------------------------------------------*/
4448 /* continueIfTrue - */
4449 /*-----------------------------------------------------------------*/
4450 static void continueIfTrue (iCode *ic)
4453 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4457 /*-----------------------------------------------------------------*/
4459 /*-----------------------------------------------------------------*/
4460 static void jumpIfTrue (iCode *ic)
4463 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4467 /*-----------------------------------------------------------------*/
4468 /* jmpTrueOrFalse - */
4469 /*-----------------------------------------------------------------*/
4470 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4472 // ugly but optimized by peephole
4474 symbol *nlbl = newiTempLabel(NULL);
4475 emitcode("sjmp","%05d$",nlbl->key+100);
4476 emitcode("","%05d$:",tlbl->key+100);
4477 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4478 emitcode("","%05d$:",nlbl->key+100);
4481 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4482 emitcode("","%05d$:",tlbl->key+100);
4487 /*-----------------------------------------------------------------*/
4488 /* genAnd - code for and */
4489 /*-----------------------------------------------------------------*/
4490 static void genAnd (iCode *ic, iCode *ifx)
4492 operand *left, *right, *result;
4494 unsigned long lit = 0L;
4498 D(emitcode(";", "genAnd "););
4503 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4504 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4505 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4509 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4511 AOP_TYPE(left), AOP_TYPE(right));
4512 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4514 AOP_SIZE(left), AOP_SIZE(right));
4517 /* if left is a literal & right is not then exchange them */
4518 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4519 AOP_NEEDSACC(left)) {
4520 operand *tmp = right ;
4525 /* if result = right then exchange them */
4526 if(sameRegs(AOP(result),AOP(right))){
4527 operand *tmp = right ;
4532 /* if right is bit then exchange them */
4533 if (AOP_TYPE(right) == AOP_CRY &&
4534 AOP_TYPE(left) != AOP_CRY){
4535 operand *tmp = right ;
4539 if(AOP_TYPE(right) == AOP_LIT)
4540 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4542 size = AOP_SIZE(result);
4545 // result = bit & yy;
4546 if (AOP_TYPE(left) == AOP_CRY){
4547 // c = bit & literal;
4548 if(AOP_TYPE(right) == AOP_LIT){
4550 if(size && sameRegs(AOP(result),AOP(left)))
4553 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4556 if(size && (AOP_TYPE(result) == AOP_CRY)){
4557 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4560 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4564 emitcode("clr","c");
4567 if (AOP_TYPE(right) == AOP_CRY){
4569 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4570 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4573 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4575 emitcode("rrc","a");
4576 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4584 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4585 genIfxJump(ifx, "c");
4589 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4590 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4591 if((AOP_TYPE(right) == AOP_LIT) &&
4592 (AOP_TYPE(result) == AOP_CRY) &&
4593 (AOP_TYPE(left) != AOP_CRY)){
4594 int posbit = isLiteralBit(lit);
4598 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4601 emitcode("mov","c,acc.%d",posbit&0x07);
4605 sprintf(buffer,"acc.%d",posbit&0x07);
4606 genIfxJump(ifx, buffer);
4611 symbol *tlbl = newiTempLabel(NULL);
4612 int sizel = AOP_SIZE(left);
4614 emitcode("setb","c");
4616 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4617 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4619 if((posbit = isLiteralBit(bytelit)) != 0)
4620 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4622 if(bytelit != 0x0FFL)
4623 emitcode("anl","a,%s",
4624 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4625 emitcode("jnz","%05d$",tlbl->key+100);
4630 // bit = left & literal
4632 emitcode("clr","c");
4633 emitcode("","%05d$:",tlbl->key+100);
4635 // if(left & literal)
4638 jmpTrueOrFalse(ifx, tlbl);
4646 /* if left is same as result */
4647 if(sameRegs(AOP(result),AOP(left))){
4648 for(;size--; offset++) {
4649 if(AOP_TYPE(right) == AOP_LIT){
4650 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4654 aopPut(AOP(result),zero,offset);
4656 if (IS_AOP_PREG(result)) {
4657 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4658 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4659 aopPut(AOP(result),"a",offset);
4661 emitcode("anl","%s,%s",
4662 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4663 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4665 if (AOP_TYPE(left) == AOP_ACC)
4666 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4668 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4669 if (IS_AOP_PREG(result)) {
4670 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4671 aopPut(AOP(result),"a",offset);
4674 emitcode("anl","%s,a",
4675 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4680 // left & result in different registers
4681 if(AOP_TYPE(result) == AOP_CRY){
4683 // if(size), result in bit
4684 // if(!size && ifx), conditional oper: if(left & right)
4685 symbol *tlbl = newiTempLabel(NULL);
4686 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4688 emitcode("setb","c");
4690 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4691 emitcode("anl","a,%s",
4692 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4693 emitcode("jnz","%05d$",tlbl->key+100);
4698 emitcode("","%05d$:",tlbl->key+100);
4701 jmpTrueOrFalse(ifx, tlbl);
4703 for(;(size--);offset++) {
4705 // result = left & right
4706 if(AOP_TYPE(right) == AOP_LIT){
4707 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4709 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4712 } else if(bytelit == 0){
4713 aopPut(AOP(result),zero,offset);
4717 // faster than result <- left, anl result,right
4718 // and better if result is SFR
4719 if (AOP_TYPE(left) == AOP_ACC)
4720 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4722 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4723 emitcode("anl","a,%s",
4724 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4726 aopPut(AOP(result),"a",offset);
4732 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4733 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4734 freeAsmop(result,NULL,ic,TRUE);
4737 /*-----------------------------------------------------------------*/
4738 /* genOr - code for or */
4739 /*-----------------------------------------------------------------*/
4740 static void genOr (iCode *ic, iCode *ifx)
4742 operand *left, *right, *result;
4744 unsigned long lit = 0L;
4746 D(emitcode(";", "genOr "););
4751 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4752 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4753 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4757 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4759 AOP_TYPE(left), AOP_TYPE(right));
4760 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4762 AOP_SIZE(left), AOP_SIZE(right));
4765 /* if left is a literal & right is not then exchange them */
4766 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4767 AOP_NEEDSACC(left)) {
4768 operand *tmp = right ;
4773 /* if result = right then exchange them */
4774 if(sameRegs(AOP(result),AOP(right))){
4775 operand *tmp = right ;
4780 /* if right is bit then exchange them */
4781 if (AOP_TYPE(right) == AOP_CRY &&
4782 AOP_TYPE(left) != AOP_CRY){
4783 operand *tmp = right ;
4787 if(AOP_TYPE(right) == AOP_LIT)
4788 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4790 size = AOP_SIZE(result);
4794 if (AOP_TYPE(left) == AOP_CRY){
4795 if(AOP_TYPE(right) == AOP_LIT){
4796 // c = bit & literal;
4798 // lit != 0 => result = 1
4799 if(AOP_TYPE(result) == AOP_CRY){
4801 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4803 continueIfTrue(ifx);
4806 emitcode("setb","c");
4808 // lit == 0 => result = left
4809 if(size && sameRegs(AOP(result),AOP(left)))
4811 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4814 if (AOP_TYPE(right) == AOP_CRY){
4816 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4817 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4821 symbol *tlbl = newiTempLabel(NULL);
4822 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4823 emitcode("setb","c");
4824 emitcode("jb","%s,%05d$",
4825 AOP(left)->aopu.aop_dir,tlbl->key+100);
4827 emitcode("jnz","%05d$",tlbl->key+100);
4828 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4829 jmpTrueOrFalse(ifx, tlbl);
4833 emitcode("","%05d$:",tlbl->key+100);
4842 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4843 genIfxJump(ifx, "c");
4847 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4848 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4849 if((AOP_TYPE(right) == AOP_LIT) &&
4850 (AOP_TYPE(result) == AOP_CRY) &&
4851 (AOP_TYPE(left) != AOP_CRY)){
4855 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4857 continueIfTrue(ifx);
4860 // lit = 0, result = boolean(left)
4862 emitcode("setb","c");
4865 symbol *tlbl = newiTempLabel(NULL);
4866 emitcode("jnz","%05d$",tlbl->key+100);
4868 emitcode("","%05d$:",tlbl->key+100);
4870 genIfxJump (ifx,"a");
4878 /* if left is same as result */
4879 if(sameRegs(AOP(result),AOP(left))){
4880 for(;size--; offset++) {
4881 if(AOP_TYPE(right) == AOP_LIT){
4882 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4885 if (IS_AOP_PREG(left)) {
4886 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4887 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4888 aopPut(AOP(result),"a",offset);
4890 emitcode("orl","%s,%s",
4891 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4892 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4894 if (AOP_TYPE(left) == AOP_ACC)
4895 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4897 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4898 if (IS_AOP_PREG(left)) {
4899 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4900 aopPut(AOP(result),"a",offset);
4902 emitcode("orl","%s,a",
4903 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4908 // left & result in different registers
4909 if(AOP_TYPE(result) == AOP_CRY){
4911 // if(size), result in bit
4912 // if(!size && ifx), conditional oper: if(left | right)
4913 symbol *tlbl = newiTempLabel(NULL);
4914 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4916 emitcode("setb","c");
4918 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4919 emitcode("orl","a,%s",
4920 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4921 emitcode("jnz","%05d$",tlbl->key+100);
4926 emitcode("","%05d$:",tlbl->key+100);
4929 jmpTrueOrFalse(ifx, tlbl);
4930 } else for(;(size--);offset++){
4932 // result = left & right
4933 if(AOP_TYPE(right) == AOP_LIT){
4934 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4936 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4941 // faster than result <- left, anl result,right
4942 // and better if result is SFR
4943 if (AOP_TYPE(left) == AOP_ACC)
4944 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4946 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4947 emitcode("orl","a,%s",
4948 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4950 aopPut(AOP(result),"a",offset);
4955 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4956 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4957 freeAsmop(result,NULL,ic,TRUE);
4960 /*-----------------------------------------------------------------*/
4961 /* genXor - code for xclusive or */
4962 /*-----------------------------------------------------------------*/
4963 static void genXor (iCode *ic, iCode *ifx)
4965 operand *left, *right, *result;
4967 unsigned long lit = 0L;
4969 D(emitcode(";", "genXor "););
4974 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4975 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4976 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4980 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4982 AOP_TYPE(left), AOP_TYPE(right));
4983 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4985 AOP_SIZE(left), AOP_SIZE(right));
4988 /* if left is a literal & right is not ||
4989 if left needs acc & right does not */
4990 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4991 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4992 operand *tmp = right ;
4997 /* if result = right then exchange them */
4998 if(sameRegs(AOP(result),AOP(right))){
4999 operand *tmp = right ;
5004 /* if right is bit then exchange them */
5005 if (AOP_TYPE(right) == AOP_CRY &&
5006 AOP_TYPE(left) != AOP_CRY){
5007 operand *tmp = right ;
5011 if(AOP_TYPE(right) == AOP_LIT)
5012 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5014 size = AOP_SIZE(result);
5018 if (AOP_TYPE(left) == AOP_CRY){
5019 if(AOP_TYPE(right) == AOP_LIT){
5020 // c = bit & literal;
5022 // lit>>1 != 0 => result = 1
5023 if(AOP_TYPE(result) == AOP_CRY){
5025 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5027 continueIfTrue(ifx);
5030 emitcode("setb","c");
5034 // lit == 0, result = left
5035 if(size && sameRegs(AOP(result),AOP(left)))
5037 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5039 // lit == 1, result = not(left)
5040 if(size && sameRegs(AOP(result),AOP(left))){
5041 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5044 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5045 emitcode("cpl","c");
5052 symbol *tlbl = newiTempLabel(NULL);
5053 if (AOP_TYPE(right) == AOP_CRY){
5055 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5058 int sizer = AOP_SIZE(right);
5060 // if val>>1 != 0, result = 1
5061 emitcode("setb","c");
5063 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5065 // test the msb of the lsb
5066 emitcode("anl","a,#0xfe");
5067 emitcode("jnz","%05d$",tlbl->key+100);
5071 emitcode("rrc","a");
5073 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5074 emitcode("cpl","c");
5075 emitcode("","%05d$:",(tlbl->key+100));
5082 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5083 genIfxJump(ifx, "c");
5087 if(sameRegs(AOP(result),AOP(left))){
5088 /* if left is same as result */
5089 for(;size--; offset++) {
5090 if(AOP_TYPE(right) == AOP_LIT){
5091 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5094 if (IS_AOP_PREG(left)) {
5095 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5096 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5097 aopPut(AOP(result),"a",offset);
5099 emitcode("xrl","%s,%s",
5100 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5101 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5103 if (AOP_TYPE(left) == AOP_ACC)
5104 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5106 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5107 if (IS_AOP_PREG(left)) {
5108 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5109 aopPut(AOP(result),"a",offset);
5111 emitcode("xrl","%s,a",
5112 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5117 // left & result in different registers
5118 if(AOP_TYPE(result) == AOP_CRY){
5120 // if(size), result in bit
5121 // if(!size && ifx), conditional oper: if(left ^ right)
5122 symbol *tlbl = newiTempLabel(NULL);
5123 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5125 emitcode("setb","c");
5127 if((AOP_TYPE(right) == AOP_LIT) &&
5128 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5129 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5131 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5132 emitcode("xrl","a,%s",
5133 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5135 emitcode("jnz","%05d$",tlbl->key+100);
5140 emitcode("","%05d$:",tlbl->key+100);
5143 jmpTrueOrFalse(ifx, tlbl);
5144 } else for(;(size--);offset++){
5146 // result = left & right
5147 if(AOP_TYPE(right) == AOP_LIT){
5148 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
5150 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5155 // faster than result <- left, anl result,right
5156 // and better if result is SFR
5157 if (AOP_TYPE(left) == AOP_ACC)
5158 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5160 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5161 emitcode("xrl","a,%s",
5162 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5164 aopPut(AOP(result),"a",offset);
5169 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5170 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5171 freeAsmop(result,NULL,ic,TRUE);
5174 /*-----------------------------------------------------------------*/
5175 /* genInline - write the inline code out */
5176 /*-----------------------------------------------------------------*/
5177 static void genInline (iCode *ic)
5179 char buffer[MAX_INLINEASM];
5183 D(emitcode(";", "genInline "););
5185 _G.inLine += (!options.asmpeep);
5186 strcpy(buffer,IC_INLINE(ic));
5188 /* emit each line as a code */
5207 /* emitcode("",buffer); */
5208 _G.inLine -= (!options.asmpeep);
5211 /*-----------------------------------------------------------------*/
5212 /* genRRC - rotate right with carry */
5213 /*-----------------------------------------------------------------*/
5214 static void genRRC (iCode *ic)
5216 operand *left , *result ;
5217 int size, offset = 0;
5220 D(emitcode(";", "genRRC "););
5222 /* rotate right with carry */
5224 result=IC_RESULT(ic);
5225 aopOp (left,ic,FALSE, FALSE);
5226 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5228 /* move it to the result */
5229 size = AOP_SIZE(result);
5233 _startLazyDPSEvaluation();
5235 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5237 emitcode("rrc","a");
5238 if (AOP_SIZE(result) > 1)
5239 aopPut(AOP(result),"a",offset--);
5241 _endLazyDPSEvaluation();
5243 /* now we need to put the carry into the
5244 highest order byte of the result */
5245 if (AOP_SIZE(result) > 1) {
5246 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5249 emitcode("mov","acc.7,c");
5250 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5251 freeAsmop(left,NULL,ic,TRUE);
5252 freeAsmop(result,NULL,ic,TRUE);
5255 /*-----------------------------------------------------------------*/
5256 /* genRLC - generate code for rotate left with carry */
5257 /*-----------------------------------------------------------------*/
5258 static void genRLC (iCode *ic)
5260 operand *left , *result ;
5261 int size, offset = 0;
5264 D(emitcode(";", "genRLC "););
5266 /* rotate right with carry */
5268 result=IC_RESULT(ic);
5269 aopOp (left,ic,FALSE, FALSE);
5270 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5272 /* move it to the result */
5273 size = AOP_SIZE(result);
5276 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5278 emitcode("add","a,acc");
5279 if (AOP_SIZE(result) > 1)
5281 aopPut(AOP(result),"a",offset++);
5284 _startLazyDPSEvaluation();
5286 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5288 emitcode("rlc","a");
5289 if (AOP_SIZE(result) > 1)
5290 aopPut(AOP(result),"a",offset++);
5292 _endLazyDPSEvaluation();
5294 /* now we need to put the carry into the
5295 highest order byte of the result */
5296 if (AOP_SIZE(result) > 1) {
5297 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5300 emitcode("mov","acc.0,c");
5301 aopPut(AOP(result),"a",0);
5302 freeAsmop(left,NULL,ic,TRUE);
5303 freeAsmop(result,NULL,ic,TRUE);
5306 /*-----------------------------------------------------------------*/
5307 /* genGetHbit - generates code get highest order bit */
5308 /*-----------------------------------------------------------------*/
5309 static void genGetHbit (iCode *ic)
5311 operand *left, *result;
5313 result=IC_RESULT(ic);
5314 aopOp (left,ic,FALSE, FALSE);
5315 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5317 D(emitcode(";", "genGetHbit "););
5319 /* get the highest order byte into a */
5320 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5321 if(AOP_TYPE(result) == AOP_CRY){
5322 emitcode("rlc","a");
5327 emitcode("anl","a,#0x01");
5332 freeAsmop(left,NULL,ic,TRUE);
5333 freeAsmop(result,NULL,ic,TRUE);
5336 /*-----------------------------------------------------------------*/
5337 /* AccRol - rotate left accumulator by known count */
5338 /*-----------------------------------------------------------------*/
5339 static void AccRol (int shCount)
5341 shCount &= 0x0007; // shCount : 0..7
5353 emitcode("swap","a");
5357 emitcode("swap","a");
5360 emitcode("swap","a");
5373 /*-----------------------------------------------------------------*/
5374 /* AccLsh - left shift accumulator by known count */
5375 /*-----------------------------------------------------------------*/
5376 static void AccLsh (int shCount)
5380 emitcode("add","a,acc");
5383 emitcode("add","a,acc");
5384 emitcode("add","a,acc");
5386 /* rotate left accumulator */
5388 /* and kill the lower order bits */
5389 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5394 /*-----------------------------------------------------------------*/
5395 /* AccRsh - right shift accumulator by known count */
5396 /*-----------------------------------------------------------------*/
5397 static void AccRsh (int shCount)
5402 emitcode("rrc","a");
5404 /* rotate right accumulator */
5405 AccRol(8 - shCount);
5406 /* and kill the higher order bits */
5407 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5412 /*-----------------------------------------------------------------*/
5413 /* AccSRsh - signed right shift accumulator by known count */
5414 /*-----------------------------------------------------------------*/
5415 static void AccSRsh (int shCount)
5420 emitcode("mov","c,acc.7");
5421 emitcode("rrc","a");
5422 } else if(shCount == 2){
5423 emitcode("mov","c,acc.7");
5424 emitcode("rrc","a");
5425 emitcode("mov","c,acc.7");
5426 emitcode("rrc","a");
5428 tlbl = newiTempLabel(NULL);
5429 /* rotate right accumulator */
5430 AccRol(8 - shCount);
5431 /* and kill the higher order bits */
5432 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5433 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5434 emitcode("orl","a,#0x%02x",
5435 (unsigned char)~SRMask[shCount]);
5436 emitcode("","%05d$:",tlbl->key+100);
5441 /*-----------------------------------------------------------------*/
5442 /* shiftR1Left2Result - shift right one byte from left to result */
5443 /*-----------------------------------------------------------------*/
5444 static void shiftR1Left2Result (operand *left, int offl,
5445 operand *result, int offr,
5446 int shCount, int sign)
5448 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5449 /* shift right accumulator */
5454 aopPut(AOP(result),"a",offr);
5457 /*-----------------------------------------------------------------*/
5458 /* shiftL1Left2Result - shift left one byte from left to result */
5459 /*-----------------------------------------------------------------*/
5460 static void shiftL1Left2Result (operand *left, int offl,
5461 operand *result, int offr, int shCount)
5464 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5466 /* shift left accumulator */
5468 aopPut(AOP(result),"a",offr);
5471 /*-----------------------------------------------------------------*/
5472 /* movLeft2Result - move byte from left to result */
5473 /*-----------------------------------------------------------------*/
5474 static void movLeft2Result (operand *left, int offl,
5475 operand *result, int offr, int sign)
5478 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5479 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5481 if (*l == '@' && (IS_AOP_PREG(result))) {
5482 emitcode("mov","a,%s",l);
5483 aopPut(AOP(result),"a",offr);
5486 aopPut(AOP(result),l,offr);
5488 /* MSB sign in acc.7 ! */
5489 if(getDataSize(left) == offl+1){
5490 emitcode("mov","a,%s",l);
5491 aopPut(AOP(result),"a",offr);
5498 /*-----------------------------------------------------------------*/
5499 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5500 /*-----------------------------------------------------------------*/
5501 static void AccAXRrl1 (char *x)
5503 emitcode("rrc","a");
5504 emitcode("xch","a,%s", x);
5505 emitcode("rrc","a");
5506 emitcode("xch","a,%s", x);
5509 /*-----------------------------------------------------------------*/
5510 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5511 /*-----------------------------------------------------------------*/
5512 static void AccAXLrl1 (char *x)
5514 emitcode("xch","a,%s",x);
5515 emitcode("rlc","a");
5516 emitcode("xch","a,%s",x);
5517 emitcode("rlc","a");
5520 /*-----------------------------------------------------------------*/
5521 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5522 /*-----------------------------------------------------------------*/
5523 static void AccAXLsh1 (char *x)
5525 emitcode("xch","a,%s",x);
5526 emitcode("add","a,acc");
5527 emitcode("xch","a,%s",x);
5528 emitcode("rlc","a");
5531 /*-----------------------------------------------------------------*/
5532 /* AccAXLsh - left shift a:x by known count (0..7) */
5533 /*-----------------------------------------------------------------*/
5534 static void AccAXLsh (char *x, int shCount)
5548 case 5 : // AAAAABBB:CCCCCDDD
5549 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5550 emitcode("anl","a,#0x%02x",
5551 SLMask[shCount]); // BBB00000:CCCCCDDD
5552 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5553 AccRol(shCount); // DDDCCCCC:BBB00000
5554 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5555 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5556 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5557 emitcode("anl","a,#0x%02x",
5558 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5559 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5560 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5562 case 6 : // AAAAAABB:CCCCCCDD
5563 emitcode("anl","a,#0x%02x",
5564 SRMask[shCount]); // 000000BB:CCCCCCDD
5565 emitcode("mov","c,acc.0"); // c = B
5566 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5567 AccAXRrl1(x); // BCCCCCCD:D000000B
5568 AccAXRrl1(x); // BBCCCCCC:DD000000
5570 case 7 : // a:x <<= 7
5571 emitcode("anl","a,#0x%02x",
5572 SRMask[shCount]); // 0000000B:CCCCCCCD
5573 emitcode("mov","c,acc.0"); // c = B
5574 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5575 AccAXRrl1(x); // BCCCCCCC:D0000000
5582 /*-----------------------------------------------------------------*/
5583 /* AccAXRsh - right shift a:x known count (0..7) */
5584 /*-----------------------------------------------------------------*/
5585 static void AccAXRsh (char *x, int shCount)
5592 AccAXRrl1(x); // 0->a:x
5596 AccAXRrl1(x); // 0->a:x
5598 AccAXRrl1(x); // 0->a:x
5602 case 5 : // AAAAABBB:CCCCCDDD = a:x
5603 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5604 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5605 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5606 emitcode("anl","a,#0x%02x",
5607 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5608 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5609 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5610 emitcode("anl","a,#0x%02x",
5611 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5612 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5613 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5614 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5616 case 6 : // AABBBBBB:CCDDDDDD
5617 emitcode("mov","c,acc.7");
5618 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5619 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5620 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5621 emitcode("anl","a,#0x%02x",
5622 SRMask[shCount]); // 000000AA:BBBBBBCC
5624 case 7 : // ABBBBBBB:CDDDDDDD
5625 emitcode("mov","c,acc.7"); // c = A
5626 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5627 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5628 emitcode("anl","a,#0x%02x",
5629 SRMask[shCount]); // 0000000A:BBBBBBBC
5636 /*-----------------------------------------------------------------*/
5637 /* AccAXRshS - right shift signed a:x known count (0..7) */
5638 /*-----------------------------------------------------------------*/
5639 static void AccAXRshS (char *x, int shCount)
5646 emitcode("mov","c,acc.7");
5647 AccAXRrl1(x); // s->a:x
5650 emitcode("mov","c,acc.7");
5651 AccAXRrl1(x); // s->a:x
5652 emitcode("mov","c,acc.7");
5653 AccAXRrl1(x); // s->a:x
5657 case 5 : // AAAAABBB:CCCCCDDD = a:x
5658 tlbl = newiTempLabel(NULL);
5659 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5660 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5661 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5662 emitcode("anl","a,#0x%02x",
5663 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5664 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5665 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5666 emitcode("anl","a,#0x%02x",
5667 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5668 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5669 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5670 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5671 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5672 emitcode("orl","a,#0x%02x",
5673 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5674 emitcode("","%05d$:",tlbl->key+100);
5675 break; // SSSSAAAA:BBBCCCCC
5676 case 6 : // AABBBBBB:CCDDDDDD
5677 tlbl = newiTempLabel(NULL);
5678 emitcode("mov","c,acc.7");
5679 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5680 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5681 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5682 emitcode("anl","a,#0x%02x",
5683 SRMask[shCount]); // 000000AA:BBBBBBCC
5684 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5685 emitcode("orl","a,#0x%02x",
5686 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5687 emitcode("","%05d$:",tlbl->key+100);
5689 case 7 : // ABBBBBBB:CDDDDDDD
5690 tlbl = newiTempLabel(NULL);
5691 emitcode("mov","c,acc.7"); // c = A
5692 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5693 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5694 emitcode("anl","a,#0x%02x",
5695 SRMask[shCount]); // 0000000A:BBBBBBBC
5696 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5697 emitcode("orl","a,#0x%02x",
5698 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5699 emitcode("","%05d$:",tlbl->key+100);
5706 /*-----------------------------------------------------------------*/
5707 /* shiftL2Left2Result - shift left two bytes from left to result */
5708 /*-----------------------------------------------------------------*/
5709 static void shiftL2Left2Result (operand *left, int offl,
5710 operand *result, int offr, int shCount)
5712 if(sameRegs(AOP(result), AOP(left)) &&
5713 ((offl + MSB16) == offr)){
5714 /* don't crash result[offr] */
5715 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5716 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5718 movLeft2Result(left,offl, result, offr, 0);
5719 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5721 /* ax << shCount (x = lsb(result))*/
5722 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5723 aopPut(AOP(result),"a",offr+MSB16);
5727 /*-----------------------------------------------------------------*/
5728 /* shiftR2Left2Result - shift right two bytes from left to result */
5729 /*-----------------------------------------------------------------*/
5730 static void shiftR2Left2Result (operand *left, int offl,
5731 operand *result, int offr,
5732 int shCount, int sign)
5734 if(sameRegs(AOP(result), AOP(left)) &&
5735 ((offl + MSB16) == offr)){
5736 /* don't crash result[offr] */
5737 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5738 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5740 movLeft2Result(left,offl, result, offr, 0);
5741 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5743 /* a:x >> shCount (x = lsb(result))*/
5745 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5747 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5748 if(getDataSize(result) > 1)
5749 aopPut(AOP(result),"a",offr+MSB16);
5752 /*-----------------------------------------------------------------*/
5753 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5754 /*-----------------------------------------------------------------*/
5755 static void shiftLLeftOrResult (operand *left, int offl,
5756 operand *result, int offr, int shCount)
5758 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5759 /* shift left accumulator */
5761 /* or with result */
5762 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5763 /* back to result */
5764 aopPut(AOP(result),"a",offr);
5767 /*-----------------------------------------------------------------*/
5768 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5769 /*-----------------------------------------------------------------*/
5770 static void shiftRLeftOrResult (operand *left, int offl,
5771 operand *result, int offr, int shCount)
5773 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5774 /* shift right accumulator */
5776 /* or with result */
5777 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5778 /* back to result */
5779 aopPut(AOP(result),"a",offr);
5782 /*-----------------------------------------------------------------*/
5783 /* genlshOne - left shift a one byte quantity by known count */
5784 /*-----------------------------------------------------------------*/
5785 static void genlshOne (operand *result, operand *left, int shCount)
5787 D(emitcode(";", "genlshOne "););
5788 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5791 /*-----------------------------------------------------------------*/
5792 /* genlshTwo - left shift two bytes by known amount != 0 */
5793 /*-----------------------------------------------------------------*/
5794 static void genlshTwo (operand *result,operand *left, int shCount)
5798 D(emitcode(";", "genlshTwo "););
5800 size = getDataSize(result);
5802 /* if shCount >= 8 */
5808 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5810 movLeft2Result(left, LSB, result, MSB16, 0);
5812 aopPut(AOP(result),zero,LSB);
5815 /* 1 <= shCount <= 7 */
5818 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5820 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5824 /*-----------------------------------------------------------------*/
5825 /* shiftLLong - shift left one long from left to result */
5826 /* offl = LSB or MSB16 */
5827 /*-----------------------------------------------------------------*/
5828 static void shiftLLong (operand *left, operand *result, int offr )
5831 int size = AOP_SIZE(result);
5833 if(size >= LSB+offr){
5834 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5836 emitcode("add","a,acc");
5837 if (sameRegs(AOP(left),AOP(result)) &&
5838 size >= MSB16+offr && offr != LSB )
5839 emitcode("xch","a,%s",
5840 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5842 aopPut(AOP(result),"a",LSB+offr);
5845 if(size >= MSB16+offr){
5846 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5847 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5850 emitcode("rlc","a");
5851 if (sameRegs(AOP(left),AOP(result)) &&
5852 size >= MSB24+offr && offr != LSB)
5853 emitcode("xch","a,%s",
5854 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5856 aopPut(AOP(result),"a",MSB16+offr);
5859 if(size >= MSB24+offr){
5860 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5861 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5864 emitcode("rlc","a");
5865 if (sameRegs(AOP(left),AOP(result)) &&
5866 size >= MSB32+offr && offr != LSB )
5867 emitcode("xch","a,%s",
5868 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5870 aopPut(AOP(result),"a",MSB24+offr);
5873 if(size > MSB32+offr){
5874 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5875 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5878 emitcode("rlc","a");
5879 aopPut(AOP(result),"a",MSB32+offr);
5882 aopPut(AOP(result),zero,LSB);
5885 /*-----------------------------------------------------------------*/
5886 /* genlshFour - shift four byte by a known amount != 0 */
5887 /*-----------------------------------------------------------------*/
5888 static void genlshFour (operand *result, operand *left, int shCount)
5892 D(emitcode(";", "genlshFour "););
5894 size = AOP_SIZE(result);
5896 /* if shifting more that 3 bytes */
5897 if (shCount >= 24 ) {
5900 /* lowest order of left goes to the highest
5901 order of the destination */
5902 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5904 movLeft2Result(left, LSB, result, MSB32, 0);
5905 aopPut(AOP(result),zero,LSB);
5906 aopPut(AOP(result),zero,MSB16);
5907 aopPut(AOP(result),zero,MSB32);
5911 /* more than two bytes */
5912 else if ( shCount >= 16 ) {
5913 /* lower order two bytes goes to higher order two bytes */
5915 /* if some more remaining */
5917 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5919 movLeft2Result(left, MSB16, result, MSB32, 0);
5920 movLeft2Result(left, LSB, result, MSB24, 0);
5922 aopPut(AOP(result),zero,MSB16);
5923 aopPut(AOP(result),zero,LSB);
5927 /* if more than 1 byte */
5928 else if ( shCount >= 8 ) {
5929 /* lower order three bytes goes to higher order three bytes */
5933 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5935 movLeft2Result(left, LSB, result, MSB16, 0);
5937 else{ /* size = 4 */
5939 movLeft2Result(left, MSB24, result, MSB32, 0);
5940 movLeft2Result(left, MSB16, result, MSB24, 0);
5941 movLeft2Result(left, LSB, result, MSB16, 0);
5942 aopPut(AOP(result),zero,LSB);
5944 else if(shCount == 1)
5945 shiftLLong(left, result, MSB16);
5947 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5948 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5949 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5950 aopPut(AOP(result),zero,LSB);
5955 /* 1 <= shCount <= 7 */
5956 else if(shCount <= 2){
5957 shiftLLong(left, result, LSB);
5959 shiftLLong(result, result, LSB);
5961 /* 3 <= shCount <= 7, optimize */
5963 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5964 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5965 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5969 /*-----------------------------------------------------------------*/
5970 /* genLeftShiftLiteral - left shifting by known count */
5971 /*-----------------------------------------------------------------*/
5972 static void genLeftShiftLiteral (operand *left,
5977 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5980 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5982 freeAsmop(right,NULL,ic,TRUE);
5984 aopOp(left,ic,FALSE, FALSE);
5985 aopOp(result,ic,FALSE, TRUE);
5987 size = getSize(operandType(result));
5990 emitcode("; shift left ","result %d, left %d",size,
5994 /* I suppose that the left size >= result size */
5997 movLeft2Result(left, size, result, size, 0);
6001 else if(shCount >= (size * 8))
6003 aopPut(AOP(result),zero,size);
6007 genlshOne (result,left,shCount);
6011 case 3: /* bug: this is for generic pointers, I bet. */
6012 genlshTwo (result,left,shCount);
6016 genlshFour (result,left,shCount);
6020 freeAsmop(left,NULL,ic,TRUE);
6021 freeAsmop(result,NULL,ic,TRUE);
6024 /*-----------------------------------------------------------------*/
6025 /* genLeftShift - generates code for left shifting */
6026 /*-----------------------------------------------------------------*/
6027 static void genLeftShift (iCode *ic)
6029 operand *left,*right, *result;
6032 symbol *tlbl , *tlbl1;
6034 D(emitcode(";", "genLeftShift "););
6036 right = IC_RIGHT(ic);
6038 result = IC_RESULT(ic);
6040 aopOp(right,ic,FALSE, FALSE);
6043 /* if the shift count is known then do it
6044 as efficiently as possible */
6045 if (AOP_TYPE(right) == AOP_LIT) {
6046 genLeftShiftLiteral (left,right,result,ic);
6051 /* shift count is unknown then we have to form
6052 a loop get the loop count in B : Note: we take
6053 only the lower order byte since shifting
6054 more that 32 bits make no sense anyway, ( the
6055 largest size of an object can be only 32 bits ) */
6057 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6058 emitcode("inc","b");
6059 freeAsmop (right,NULL,ic,TRUE);
6060 aopOp(left,ic,FALSE, FALSE);
6061 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6063 /* now move the left to the result if they are not the
6065 if (!sameRegs(AOP(left),AOP(result)) &&
6066 AOP_SIZE(result) > 1) {
6068 size = AOP_SIZE(result);
6070 _startLazyDPSEvaluation();
6072 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6073 if (*l == '@' && (IS_AOP_PREG(result))) {
6075 emitcode("mov","a,%s",l);
6076 aopPut(AOP(result),"a",offset);
6078 aopPut(AOP(result),l,offset);
6081 _endLazyDPSEvaluation();
6084 tlbl = newiTempLabel(NULL);
6085 size = AOP_SIZE(result);
6087 tlbl1 = newiTempLabel(NULL);
6089 /* if it is only one byte then */
6091 symbol *tlbl1 = newiTempLabel(NULL);
6093 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6095 emitcode("sjmp","%05d$",tlbl1->key+100);
6096 emitcode("","%05d$:",tlbl->key+100);
6097 emitcode("add","a,acc");
6098 emitcode("","%05d$:",tlbl1->key+100);
6099 emitcode("djnz","b,%05d$",tlbl->key+100);
6100 aopPut(AOP(result),"a",0);
6104 reAdjustPreg(AOP(result));
6106 emitcode("sjmp","%05d$",tlbl1->key+100);
6107 emitcode("","%05d$:",tlbl->key+100);
6108 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6110 emitcode("add","a,acc");
6111 aopPut(AOP(result),"a",offset++);
6112 _startLazyDPSEvaluation();
6114 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6116 emitcode("rlc","a");
6117 aopPut(AOP(result),"a",offset++);
6119 _endLazyDPSEvaluation();
6120 reAdjustPreg(AOP(result));
6122 emitcode("","%05d$:",tlbl1->key+100);
6123 emitcode("djnz","b,%05d$",tlbl->key+100);
6125 freeAsmop(left,NULL,ic,TRUE);
6126 freeAsmop(result,NULL,ic,TRUE);
6129 /*-----------------------------------------------------------------*/
6130 /* genrshOne - right shift a one byte quantity by known count */
6131 /*-----------------------------------------------------------------*/
6132 static void genrshOne (operand *result, operand *left,
6133 int shCount, int sign)
6135 D(emitcode(";", "genrshOne"););
6136 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6139 /*-----------------------------------------------------------------*/
6140 /* genrshTwo - right shift two bytes by known amount != 0 */
6141 /*-----------------------------------------------------------------*/
6142 static void genrshTwo (operand *result,operand *left,
6143 int shCount, int sign)
6145 D(emitcode(";", "genrshTwo"););
6147 /* if shCount >= 8 */
6151 shiftR1Left2Result(left, MSB16, result, LSB,
6154 movLeft2Result(left, MSB16, result, LSB, sign);
6155 addSign(result, MSB16, sign);
6158 /* 1 <= shCount <= 7 */
6160 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6163 /*-----------------------------------------------------------------*/
6164 /* shiftRLong - shift right one long from left to result */
6165 /* offl = LSB or MSB16 */
6166 /*-----------------------------------------------------------------*/
6167 static void shiftRLong (operand *left, int offl,
6168 operand *result, int sign)
6171 emitcode("clr","c");
6172 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6174 emitcode("mov","c,acc.7");
6175 emitcode("rrc","a");
6176 aopPut(AOP(result),"a",MSB32-offl);
6178 /* add sign of "a" */
6179 addSign(result, MSB32, sign);
6181 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6182 emitcode("rrc","a");
6183 aopPut(AOP(result),"a",MSB24-offl);
6185 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6186 emitcode("rrc","a");
6187 aopPut(AOP(result),"a",MSB16-offl);
6190 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6191 emitcode("rrc","a");
6192 aopPut(AOP(result),"a",LSB);
6196 /*-----------------------------------------------------------------*/
6197 /* genrshFour - shift four byte by a known amount != 0 */
6198 /*-----------------------------------------------------------------*/
6199 static void genrshFour (operand *result, operand *left,
6200 int shCount, int sign)
6202 D(emitcode(";", "genrshFour"););
6204 /* if shifting more that 3 bytes */
6205 if(shCount >= 24 ) {
6208 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6210 movLeft2Result(left, MSB32, result, LSB, sign);
6211 addSign(result, MSB16, sign);
6213 else if(shCount >= 16){
6216 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6218 movLeft2Result(left, MSB24, result, LSB, 0);
6219 movLeft2Result(left, MSB32, result, MSB16, sign);
6221 addSign(result, MSB24, sign);
6223 else if(shCount >= 8){
6226 shiftRLong(left, MSB16, result, sign);
6227 else if(shCount == 0){
6228 movLeft2Result(left, MSB16, result, LSB, 0);
6229 movLeft2Result(left, MSB24, result, MSB16, 0);
6230 movLeft2Result(left, MSB32, result, MSB24, sign);
6231 addSign(result, MSB32, sign);
6234 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6235 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6236 /* the last shift is signed */
6237 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6238 addSign(result, MSB32, sign);
6241 else{ /* 1 <= shCount <= 7 */
6243 shiftRLong(left, LSB, result, sign);
6245 shiftRLong(result, LSB, result, sign);
6248 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6249 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6250 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6255 /*-----------------------------------------------------------------*/
6256 /* genRightShiftLiteral - right shifting by known count */
6257 /*-----------------------------------------------------------------*/
6258 static void genRightShiftLiteral (operand *left,
6264 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6267 D(emitcode(";", "genRightShiftLiteral"););
6269 freeAsmop(right,NULL,ic,TRUE);
6271 aopOp(left,ic,FALSE, FALSE);
6272 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6275 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6279 size = getDataSize(left);
6280 /* test the LEFT size !!! */
6282 /* I suppose that the left size >= result size */
6284 size = getDataSize(result);
6286 movLeft2Result(left, size, result, size, 0);
6289 else if(shCount >= (size * 8)){
6291 /* get sign in acc.7 */
6292 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6293 addSign(result, LSB, sign);
6297 genrshOne (result,left,shCount,sign);
6301 genrshTwo (result,left,shCount,sign);
6305 genrshFour (result,left,shCount,sign);
6311 freeAsmop(left,NULL,ic,TRUE);
6312 freeAsmop(result,NULL,ic,TRUE);
6316 /*-----------------------------------------------------------------*/
6317 /* genSignedRightShift - right shift of signed number */
6318 /*-----------------------------------------------------------------*/
6319 static void genSignedRightShift (iCode *ic)
6321 operand *right, *left, *result;
6324 symbol *tlbl, *tlbl1 ;
6326 D(emitcode(";", "genSignedRightShift "););
6328 /* we do it the hard way put the shift count in b
6329 and loop thru preserving the sign */
6331 right = IC_RIGHT(ic);
6333 result = IC_RESULT(ic);
6335 aopOp(right,ic,FALSE, FALSE);
6338 if ( AOP_TYPE(right) == AOP_LIT) {
6339 genRightShiftLiteral (left,right,result,ic,1);
6343 /* shift count is unknown then we have to form
6344 a loop get the loop count in B : Note: we take
6345 only the lower order byte since shifting
6346 more that 32 bits make no sense anyway, ( the
6347 largest size of an object can be only 32 bits ) */
6349 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6350 emitcode("inc","b");
6351 freeAsmop (right,NULL,ic,TRUE);
6352 aopOp(left,ic,FALSE, FALSE);
6353 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6355 /* now move the left to the result if they are not the
6357 if (!sameRegs(AOP(left),AOP(result)) &&
6358 AOP_SIZE(result) > 1) {
6360 size = AOP_SIZE(result);
6362 _startLazyDPSEvaluation();
6364 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6365 if (*l == '@' && IS_AOP_PREG(result)) {
6367 emitcode("mov","a,%s",l);
6368 aopPut(AOP(result),"a",offset);
6370 aopPut(AOP(result),l,offset);
6373 _endLazyDPSEvaluation();
6376 /* mov the highest order bit to OVR */
6377 tlbl = newiTempLabel(NULL);
6378 tlbl1= newiTempLabel(NULL);
6380 size = AOP_SIZE(result);
6382 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6383 emitcode("rlc","a");
6384 emitcode("mov","ov,c");
6385 /* if it is only one byte then */
6387 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6389 emitcode("sjmp","%05d$",tlbl1->key+100);
6390 emitcode("","%05d$:",tlbl->key+100);
6391 emitcode("mov","c,ov");
6392 emitcode("rrc","a");
6393 emitcode("","%05d$:",tlbl1->key+100);
6394 emitcode("djnz","b,%05d$",tlbl->key+100);
6395 aopPut(AOP(result),"a",0);
6399 reAdjustPreg(AOP(result));
6400 emitcode("sjmp","%05d$",tlbl1->key+100);
6401 emitcode("","%05d$:",tlbl->key+100);
6402 emitcode("mov","c,ov");
6403 _startLazyDPSEvaluation();
6405 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6407 emitcode("rrc","a");
6408 aopPut(AOP(result),"a",offset--);
6410 _endLazyDPSEvaluation();
6411 reAdjustPreg(AOP(result));
6412 emitcode("","%05d$:",tlbl1->key+100);
6413 emitcode("djnz","b,%05d$",tlbl->key+100);
6416 freeAsmop(left,NULL,ic,TRUE);
6417 freeAsmop(result,NULL,ic,TRUE);
6420 /*-----------------------------------------------------------------*/
6421 /* genRightShift - generate code for right shifting */
6422 /*-----------------------------------------------------------------*/
6423 static void genRightShift (iCode *ic)
6425 operand *right, *left, *result;
6429 symbol *tlbl, *tlbl1 ;
6431 D(emitcode(";", "genRightShift "););
6433 /* if signed then we do it the hard way preserve the
6434 sign bit moving it inwards */
6435 retype = getSpec(operandType(IC_RESULT(ic)));
6437 if (!SPEC_USIGN(retype)) {
6438 genSignedRightShift (ic);
6442 /* signed & unsigned types are treated the same : i.e. the
6443 signed is NOT propagated inwards : quoting from the
6444 ANSI - standard : "for E1 >> E2, is equivalent to division
6445 by 2**E2 if unsigned or if it has a non-negative value,
6446 otherwise the result is implementation defined ", MY definition
6447 is that the sign does not get propagated */
6449 right = IC_RIGHT(ic);
6451 result = IC_RESULT(ic);
6453 aopOp(right,ic,FALSE, FALSE);
6456 /* if the shift count is known then do it
6457 as efficiently as possible */
6458 if (AOP_TYPE(right) == AOP_LIT) {
6459 genRightShiftLiteral (left,right,result,ic, 0);
6464 /* shift count is unknown then we have to form
6465 a loop get the loop count in B : Note: we take
6466 only the lower order byte since shifting
6467 more that 32 bits make no sense anyway, ( the
6468 largest size of an object can be only 32 bits ) */
6470 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6471 emitcode("inc","b");
6472 freeAsmop (right,NULL,ic,TRUE);
6473 aopOp(left,ic,FALSE, FALSE);
6474 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6476 /* now move the left to the result if they are not the
6478 if (!sameRegs(AOP(left),AOP(result)) &&
6479 AOP_SIZE(result) > 1) {
6481 size = AOP_SIZE(result);
6483 _startLazyDPSEvaluation();
6485 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6486 if (*l == '@' && IS_AOP_PREG(result)) {
6488 emitcode("mov","a,%s",l);
6489 aopPut(AOP(result),"a",offset);
6491 aopPut(AOP(result),l,offset);
6494 _endLazyDPSEvaluation();
6497 tlbl = newiTempLabel(NULL);
6498 tlbl1= newiTempLabel(NULL);
6499 size = AOP_SIZE(result);
6502 /* if it is only one byte then */
6504 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6506 emitcode("sjmp","%05d$",tlbl1->key+100);
6507 emitcode("","%05d$:",tlbl->key+100);
6509 emitcode("rrc","a");
6510 emitcode("","%05d$:",tlbl1->key+100);
6511 emitcode("djnz","b,%05d$",tlbl->key+100);
6512 aopPut(AOP(result),"a",0);
6516 reAdjustPreg(AOP(result));
6517 emitcode("sjmp","%05d$",tlbl1->key+100);
6518 emitcode("","%05d$:",tlbl->key+100);
6520 _startLazyDPSEvaluation();
6522 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6524 emitcode("rrc","a");
6525 aopPut(AOP(result),"a",offset--);
6527 _endLazyDPSEvaluation();
6528 reAdjustPreg(AOP(result));
6530 emitcode("","%05d$:",tlbl1->key+100);
6531 emitcode("djnz","b,%05d$",tlbl->key+100);
6534 freeAsmop(left,NULL,ic,TRUE);
6535 freeAsmop(result,NULL,ic,TRUE);
6538 /*-----------------------------------------------------------------*/
6539 /* genUnpackBits - generates code for unpacking bits */
6540 /*-----------------------------------------------------------------*/
6541 static void genUnpackBits (operand *result, char *rname, int ptype)
6548 D(emitcode(";", "genUnpackBits "););
6550 etype = getSpec(operandType(result));
6552 /* read the first byte */
6557 emitcode("mov","a,@%s",rname);
6561 emitcode("movx","a,@%s",rname);
6565 emitcode("movx","a,@dptr");
6569 emitcode("clr","a");
6570 emitcode("movc","a","@a+dptr");
6574 emitcode("lcall","__gptrget");
6578 /* if we have bitdisplacement then it fits */
6579 /* into this byte completely or if length is */
6580 /* less than a byte */
6581 if ((shCnt = SPEC_BSTR(etype)) ||
6582 (SPEC_BLEN(etype) <= 8)) {
6584 /* shift right acc */
6587 emitcode("anl","a,#0x%02x",
6588 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6589 aopPut(AOP(result),"a",offset);
6593 /* bit field did not fit in a byte */
6594 rlen = SPEC_BLEN(etype) - 8;
6595 aopPut(AOP(result),"a",offset++);
6602 emitcode("inc","%s",rname);
6603 emitcode("mov","a,@%s",rname);
6607 emitcode("inc","%s",rname);
6608 emitcode("movx","a,@%s",rname);
6612 emitcode("inc","dptr");
6613 emitcode("movx","a,@dptr");
6617 emitcode("clr","a");
6618 emitcode("inc","dptr");
6619 emitcode("movc","a","@a+dptr");
6623 emitcode("inc","dptr");
6624 emitcode("lcall","__gptrget");
6629 /* if we are done */
6633 aopPut(AOP(result),"a",offset++);
6638 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6639 aopPut(AOP(result),"a",offset);
6646 /*-----------------------------------------------------------------*/
6647 /* genDataPointerGet - generates code when ptr offset is known */
6648 /*-----------------------------------------------------------------*/
6649 static void genDataPointerGet (operand *left,
6655 int size , offset = 0;
6656 aopOp(result,ic,TRUE, FALSE);
6658 /* get the string representation of the name */
6659 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6660 size = AOP_SIZE(result);
6661 _startLazyDPSEvaluation();
6664 sprintf(buffer,"(%s + %d)",l+1,offset);
6666 sprintf(buffer,"%s",l+1);
6667 aopPut(AOP(result),buffer,offset++);
6669 _endLazyDPSEvaluation();
6671 freeAsmop(left,NULL,ic,TRUE);
6672 freeAsmop(result,NULL,ic,TRUE);
6675 /*-----------------------------------------------------------------*/
6676 /* genNearPointerGet - emitcode for near pointer fetch */
6677 /*-----------------------------------------------------------------*/
6678 static void genNearPointerGet (operand *left,
6685 link *rtype, *retype;
6686 link *ltype = operandType(left);
6689 rtype = operandType(result);
6690 retype= getSpec(rtype);
6692 aopOp(left,ic,FALSE, FALSE);
6694 /* if left is rematerialisable and
6695 result is not bit variable type and
6696 the left is pointer to data space i.e
6697 lower 128 bytes of space */
6698 if (AOP_TYPE(left) == AOP_IMMD &&
6699 !IS_BITVAR(retype) &&
6700 DCL_TYPE(ltype) == POINTER) {
6701 genDataPointerGet (left,result,ic);
6705 /* if the value is already in a pointer register
6706 then don't need anything more */
6707 if (!AOP_INPREG(AOP(left))) {
6708 /* otherwise get a free pointer register */
6710 preg = getFreePtr(ic,&aop,FALSE);
6711 emitcode("mov","%s,%s",
6713 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6714 rname = preg->name ;
6716 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6718 freeAsmop(left,NULL,ic,TRUE);
6719 aopOp (result,ic,FALSE, FALSE);
6721 /* if bitfield then unpack the bits */
6722 if (IS_BITVAR(retype))
6723 genUnpackBits (result,rname,POINTER);
6725 /* we have can just get the values */
6726 int size = AOP_SIZE(result);
6730 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6732 emitcode("mov","a,@%s",rname);
6733 aopPut(AOP(result),"a",offset);
6735 sprintf(buffer,"@%s",rname);
6736 aopPut(AOP(result),buffer,offset);
6740 emitcode("inc","%s",rname);
6744 /* now some housekeeping stuff */
6746 /* we had to allocate for this iCode */
6747 freeAsmop(NULL,aop,ic,TRUE);
6749 /* we did not allocate which means left
6750 already in a pointer register, then
6751 if size > 0 && this could be used again
6752 we have to point it back to where it
6754 if (AOP_SIZE(result) > 1 &&
6755 !OP_SYMBOL(left)->remat &&
6756 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6758 int size = AOP_SIZE(result) - 1;
6760 emitcode("dec","%s",rname);
6765 freeAsmop(result,NULL,ic,TRUE);
6769 /*-----------------------------------------------------------------*/
6770 /* genPagedPointerGet - emitcode for paged pointer fetch */
6771 /*-----------------------------------------------------------------*/
6772 static void genPagedPointerGet (operand *left,
6779 link *rtype, *retype;
6781 rtype = operandType(result);
6782 retype= getSpec(rtype);
6784 aopOp(left,ic,FALSE, FALSE);
6786 /* if the value is already in a pointer register
6787 then don't need anything more */
6788 if (!AOP_INPREG(AOP(left))) {
6789 /* otherwise get a free pointer register */
6791 preg = getFreePtr(ic,&aop,FALSE);
6792 emitcode("mov","%s,%s",
6794 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6795 rname = preg->name ;
6797 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6799 freeAsmop(left,NULL,ic,TRUE);
6800 aopOp (result,ic,FALSE, FALSE);
6802 /* if bitfield then unpack the bits */
6803 if (IS_BITVAR(retype))
6804 genUnpackBits (result,rname,PPOINTER);
6806 /* we have can just get the values */
6807 int size = AOP_SIZE(result);
6812 emitcode("movx","a,@%s",rname);
6813 aopPut(AOP(result),"a",offset);
6818 emitcode("inc","%s",rname);
6822 /* now some housekeeping stuff */
6824 /* we had to allocate for this iCode */
6825 freeAsmop(NULL,aop,ic,TRUE);
6827 /* we did not allocate which means left
6828 already in a pointer register, then
6829 if size > 0 && this could be used again
6830 we have to point it back to where it
6832 if (AOP_SIZE(result) > 1 &&
6833 !OP_SYMBOL(left)->remat &&
6834 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6836 int size = AOP_SIZE(result) - 1;
6838 emitcode("dec","%s",rname);
6843 freeAsmop(result,NULL,ic,TRUE);
6848 /*-----------------------------------------------------------------*/
6849 /* genFarPointerGet - gget value from far space */
6850 /*-----------------------------------------------------------------*/
6851 static void genFarPointerGet (operand *left,
6852 operand *result, iCode *ic)
6855 link *retype = getSpec(operandType(result));
6857 D(emitcode(";", "genFarPointerGet"););
6859 aopOp(left,ic,FALSE, FALSE);
6861 /* if the operand is already in dptr
6862 then we do nothing else we move the value to dptr */
6863 if (AOP_TYPE(left) != AOP_STR) {
6864 /* if this is remateriazable */
6865 if (AOP_TYPE(left) == AOP_IMMD)
6867 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6871 /* we need to get it byte by byte */
6872 _startLazyDPSEvaluation();
6873 if (AOP_TYPE(left) != AOP_DPTR)
6875 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6876 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6877 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6881 /* We need to generate a load to DPTR indirect through DPTR. */
6882 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6883 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6884 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6885 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6886 emitcode("pop", "dph");
6887 emitcode("pop", "dpl");
6889 _endLazyDPSEvaluation();
6892 /* so dptr know contains the address */
6893 freeAsmop(left,NULL,ic,TRUE);
6894 aopOp(result,ic,FALSE, TRUE);
6896 /* if bit then unpack */
6897 if (IS_BITVAR(retype))
6898 genUnpackBits(result,"dptr",FPOINTER);
6900 size = AOP_SIZE(result);
6903 _startLazyDPSEvaluation();
6909 emitcode("movx","a,@dptr");
6910 aopPut(AOP(result),"a",offset++);
6912 emitcode("inc","dptr");
6914 _endLazyDPSEvaluation();
6917 freeAsmop(result,NULL,ic,TRUE);
6920 /*-----------------------------------------------------------------*/
6921 /* emitcodePointerGet - gget value from code space */
6922 /*-----------------------------------------------------------------*/
6923 static void emitcodePointerGet (operand *left,
6924 operand *result, iCode *ic)
6927 link *retype = getSpec(operandType(result));
6929 aopOp(left,ic,FALSE, FALSE);
6931 /* if the operand is already in dptr
6932 then we do nothing else we move the value to dptr */
6933 if (AOP_TYPE(left) != AOP_STR) {
6934 /* if this is remateriazable */
6935 if (AOP_TYPE(left) == AOP_IMMD)
6936 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6937 else { /* we need to get it byte by byte */
6938 _startLazyDPSEvaluation();
6939 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6940 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6941 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6942 _endLazyDPSEvaluation();
6945 /* so dptr know contains the address */
6946 freeAsmop(left,NULL,ic,TRUE);
6947 aopOp(result,ic,FALSE, FALSE);
6949 /* if bit then unpack */
6950 if (IS_BITVAR(retype))
6951 genUnpackBits(result,"dptr",CPOINTER);
6953 size = AOP_SIZE(result);
6957 emitcode("clr","a");
6958 emitcode("movc","a,@a+dptr");
6959 aopPut(AOP(result),"a",offset++);
6961 emitcode("inc","dptr");
6965 freeAsmop(result,NULL,ic,TRUE);
6968 /*-----------------------------------------------------------------*/
6969 /* genGenPointerGet - gget value from generic pointer space */
6970 /*-----------------------------------------------------------------*/
6971 static void genGenPointerGet (operand *left,
6972 operand *result, iCode *ic)
6975 link *retype = getSpec(operandType(result));
6977 aopOp(left,ic,FALSE, TRUE);
6979 /* if the operand is already in dptr
6980 then we do nothing else we move the value to dptr */
6981 if (AOP_TYPE(left) != AOP_STR) {
6982 /* if this is remateriazable */
6983 if (AOP_TYPE(left) == AOP_IMMD) {
6984 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6985 emitcode("mov","b,#%d",pointerCode(retype));
6987 else { /* we need to get it byte by byte */
6988 _startLazyDPSEvaluation();
6989 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6990 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6991 if (options.model == MODEL_FLAT24)
6993 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6994 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
6998 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7000 _endLazyDPSEvaluation();
7003 /* so dptr know contains the address */
7004 freeAsmop(left,NULL,ic,TRUE);
7005 aopOp(result,ic,FALSE, TRUE);
7007 /* if bit then unpack */
7008 if (IS_BITVAR(retype))
7009 genUnpackBits(result,"dptr",GPOINTER);
7011 size = AOP_SIZE(result);
7015 emitcode("lcall","__gptrget");
7016 aopPut(AOP(result),"a",offset++);
7018 emitcode("inc","dptr");
7022 freeAsmop(result,NULL,ic,TRUE);
7025 /*-----------------------------------------------------------------*/
7026 /* genPointerGet - generate code for pointer get */
7027 /*-----------------------------------------------------------------*/
7028 static void genPointerGet (iCode *ic)
7030 operand *left, *result ;
7034 D(emitcode(";", "genPointerGet "););
7037 result = IC_RESULT(ic) ;
7039 /* depending on the type of pointer we need to
7040 move it to the correct pointer register */
7041 type = operandType(left);
7042 etype = getSpec(type);
7043 /* if left is of type of pointer then it is simple */
7044 if (IS_PTR(type) && !IS_FUNC(type->next))
7045 p_type = DCL_TYPE(type);
7047 /* we have to go by the storage class */
7048 p_type = PTR_TYPE(SPEC_OCLS(etype));
7050 /* if (SPEC_OCLS(etype)->codesp ) { */
7051 /* p_type = CPOINTER ; */
7054 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7055 /* p_type = FPOINTER ; */
7057 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7058 /* p_type = PPOINTER; */
7060 /* if (SPEC_OCLS(etype) == idata ) */
7061 /* p_type = IPOINTER; */
7063 /* p_type = POINTER ; */
7066 /* now that we have the pointer type we assign
7067 the pointer values */
7072 genNearPointerGet (left,result,ic);
7076 genPagedPointerGet(left,result,ic);
7080 genFarPointerGet (left,result,ic);
7084 emitcodePointerGet (left,result,ic);
7088 genGenPointerGet (left,result,ic);
7094 /*-----------------------------------------------------------------*/
7095 /* genPackBits - generates code for packed bit storage */
7096 /*-----------------------------------------------------------------*/
7097 static void genPackBits (link *etype ,
7099 char *rname, int p_type)
7107 blen = SPEC_BLEN(etype);
7108 bstr = SPEC_BSTR(etype);
7110 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7113 /* if the bit lenth is less than or */
7114 /* it exactly fits a byte then */
7115 if (SPEC_BLEN(etype) <= 8 ) {
7116 shCount = SPEC_BSTR(etype) ;
7118 /* shift left acc */
7121 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7126 emitcode ("mov","b,a");
7127 emitcode("mov","a,@%s",rname);
7131 emitcode ("mov","b,a");
7132 emitcode("movx","a,@dptr");
7136 emitcode ("push","b");
7137 emitcode ("push","acc");
7138 emitcode ("lcall","__gptrget");
7139 emitcode ("pop","b");
7143 emitcode ("anl","a,#0x%02x",(unsigned char)
7144 ((unsigned char)(0xFF << (blen+bstr)) |
7145 (unsigned char)(0xFF >> (8-bstr)) ) );
7146 emitcode ("orl","a,b");
7147 if (p_type == GPOINTER)
7148 emitcode("pop","b");
7154 emitcode("mov","@%s,a",rname);
7158 emitcode("movx","@dptr,a");
7162 emitcode("lcall","__gptrput");
7167 if ( SPEC_BLEN(etype) <= 8 )
7170 emitcode("inc","%s",rname);
7171 rLen = SPEC_BLEN(etype) ;
7173 /* now generate for lengths greater than one byte */
7176 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7186 emitcode("mov","@%s,a",rname);
7188 emitcode("mov","@%s,%s",rname,l);
7193 emitcode("movx","@dptr,a");
7198 emitcode("lcall","__gptrput");
7201 emitcode ("inc","%s",rname);
7206 /* last last was not complete */
7208 /* save the byte & read byte */
7211 emitcode ("mov","b,a");
7212 emitcode("mov","a,@%s",rname);
7216 emitcode ("mov","b,a");
7217 emitcode("movx","a,@dptr");
7221 emitcode ("push","b");
7222 emitcode ("push","acc");
7223 emitcode ("lcall","__gptrget");
7224 emitcode ("pop","b");
7228 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7229 emitcode ("orl","a,b");
7232 if (p_type == GPOINTER)
7233 emitcode("pop","b");
7238 emitcode("mov","@%s,a",rname);
7242 emitcode("movx","@dptr,a");
7246 emitcode("lcall","__gptrput");
7250 /*-----------------------------------------------------------------*/
7251 /* genDataPointerSet - remat pointer to data space */
7252 /*-----------------------------------------------------------------*/
7253 static void genDataPointerSet(operand *right,
7257 int size, offset = 0 ;
7258 char *l, buffer[256];
7260 aopOp(right,ic,FALSE, FALSE);
7262 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7263 size = AOP_SIZE(right);
7266 sprintf(buffer,"(%s + %d)",l+1,offset);
7268 sprintf(buffer,"%s",l+1);
7269 emitcode("mov","%s,%s",buffer,
7270 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7273 freeAsmop(right,NULL,ic,TRUE);
7274 freeAsmop(result,NULL,ic,TRUE);
7277 /*-----------------------------------------------------------------*/
7278 /* genNearPointerSet - emitcode for near pointer put */
7279 /*-----------------------------------------------------------------*/
7280 static void genNearPointerSet (operand *right,
7288 link *ptype = operandType(result);
7290 retype= getSpec(operandType(right));
7292 aopOp(result,ic,FALSE, FALSE);
7294 /* if the result is rematerializable &
7295 in data space & not a bit variable */
7296 if (AOP_TYPE(result) == AOP_IMMD &&
7297 DCL_TYPE(ptype) == POINTER &&
7298 !IS_BITVAR(retype)) {
7299 genDataPointerSet (right,result,ic);
7303 /* if the value is already in a pointer register
7304 then don't need anything more */
7305 if (!AOP_INPREG(AOP(result))) {
7306 /* otherwise get a free pointer register */
7308 preg = getFreePtr(ic,&aop,FALSE);
7309 emitcode("mov","%s,%s",
7311 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7312 rname = preg->name ;
7314 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7316 freeAsmop(result,NULL,ic,TRUE);
7317 aopOp (right,ic,FALSE, FALSE);
7319 /* if bitfield then unpack the bits */
7320 if (IS_BITVAR(retype))
7321 genPackBits (retype,right,rname,POINTER);
7323 /* we have can just get the values */
7324 int size = AOP_SIZE(right);
7328 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7331 emitcode("mov","@%s,a",rname);
7333 emitcode("mov","@%s,%s",rname,l);
7335 emitcode("inc","%s",rname);
7340 /* now some housekeeping stuff */
7342 /* we had to allocate for this iCode */
7343 freeAsmop(NULL,aop,ic,TRUE);
7345 /* we did not allocate which means left
7346 already in a pointer register, then
7347 if size > 0 && this could be used again
7348 we have to point it back to where it
7350 if (AOP_SIZE(right) > 1 &&
7351 !OP_SYMBOL(result)->remat &&
7352 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7354 int size = AOP_SIZE(right) - 1;
7356 emitcode("dec","%s",rname);
7361 freeAsmop(right,NULL,ic,TRUE);
7366 /*-----------------------------------------------------------------*/
7367 /* genPagedPointerSet - emitcode for Paged pointer put */
7368 /*-----------------------------------------------------------------*/
7369 static void genPagedPointerSet (operand *right,
7378 retype= getSpec(operandType(right));
7380 aopOp(result,ic,FALSE, FALSE);
7382 /* if the value is already in a pointer register
7383 then don't need anything more */
7384 if (!AOP_INPREG(AOP(result))) {
7385 /* otherwise get a free pointer register */
7387 preg = getFreePtr(ic,&aop,FALSE);
7388 emitcode("mov","%s,%s",
7390 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7391 rname = preg->name ;
7393 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7395 freeAsmop(result,NULL,ic,TRUE);
7396 aopOp (right,ic,FALSE, FALSE);
7398 /* if bitfield then unpack the bits */
7399 if (IS_BITVAR(retype))
7400 genPackBits (retype,right,rname,PPOINTER);
7402 /* we have can just get the values */
7403 int size = AOP_SIZE(right);
7407 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7410 emitcode("movx","@%s,a",rname);
7413 emitcode("inc","%s",rname);
7419 /* now some housekeeping stuff */
7421 /* we had to allocate for this iCode */
7422 freeAsmop(NULL,aop,ic,TRUE);
7424 /* we did not allocate which means left
7425 already in a pointer register, then
7426 if size > 0 && this could be used again
7427 we have to point it back to where it
7429 if (AOP_SIZE(right) > 1 &&
7430 !OP_SYMBOL(result)->remat &&
7431 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7433 int size = AOP_SIZE(right) - 1;
7435 emitcode("dec","%s",rname);
7440 freeAsmop(right,NULL,ic,TRUE);
7445 /*-----------------------------------------------------------------*/
7446 /* genFarPointerSet - set value from far space */
7447 /*-----------------------------------------------------------------*/
7448 static void genFarPointerSet (operand *right,
7449 operand *result, iCode *ic)
7452 link *retype = getSpec(operandType(right));
7454 aopOp(result,ic,FALSE, FALSE);
7456 /* if the operand is already in dptr
7457 then we do nothing else we move the value to dptr */
7458 if (AOP_TYPE(result) != AOP_STR) {
7459 /* if this is remateriazable */
7460 if (AOP_TYPE(result) == AOP_IMMD)
7461 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7464 /* we need to get it byte by byte */
7465 _startLazyDPSEvaluation();
7466 if (AOP_TYPE(result) != AOP_DPTR)
7468 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7469 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7470 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7474 /* We need to generate a load to DPTR indirect through DPTR. */
7475 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7476 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7477 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7478 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7479 emitcode("pop", "dph");
7480 emitcode("pop", "dpl");
7482 _endLazyDPSEvaluation();
7485 /* so dptr know contains the address */
7486 freeAsmop(result,NULL,ic,TRUE);
7487 aopOp(right,ic,FALSE, TRUE);
7489 /* if bit then unpack */
7490 if (IS_BITVAR(retype))
7491 genPackBits(retype,right,"dptr",FPOINTER);
7493 size = AOP_SIZE(right);
7496 _startLazyDPSEvaluation();
7498 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7504 emitcode("movx","@dptr,a");
7506 emitcode("inc","dptr");
7508 _endLazyDPSEvaluation();
7511 freeAsmop(right,NULL,ic,TRUE);
7514 /*-----------------------------------------------------------------*/
7515 /* genGenPointerSet - set value from generic pointer space */
7516 /*-----------------------------------------------------------------*/
7517 static void genGenPointerSet (operand *right,
7518 operand *result, iCode *ic)
7521 link *retype = getSpec(operandType(right));
7523 aopOp(result,ic,FALSE, TRUE);
7525 /* if the operand is already in dptr
7526 then we do nothing else we move the value to dptr */
7527 if (AOP_TYPE(result) != AOP_STR) {
7528 _startLazyDPSEvaluation();
7529 /* if this is remateriazable */
7530 if (AOP_TYPE(result) == AOP_IMMD) {
7531 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7532 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7534 else { /* we need to get it byte by byte */
7535 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7536 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7537 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7538 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7540 _endLazyDPSEvaluation();
7542 /* so dptr know contains the address */
7543 freeAsmop(result,NULL,ic,TRUE);
7544 aopOp(right,ic,FALSE, TRUE);
7546 /* if bit then unpack */
7547 if (IS_BITVAR(retype))
7548 genPackBits(retype,right,"dptr",GPOINTER);
7550 size = AOP_SIZE(right);
7553 _startLazyDPSEvaluation();
7555 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7561 emitcode("lcall","__gptrput");
7563 emitcode("inc","dptr");
7565 _endLazyDPSEvaluation();
7568 freeAsmop(right,NULL,ic,TRUE);
7571 /*-----------------------------------------------------------------*/
7572 /* genPointerSet - stores the value into a pointer location */
7573 /*-----------------------------------------------------------------*/
7574 static void genPointerSet (iCode *ic)
7576 operand *right, *result ;
7580 D(emitcode(";", "genPointerSet "););
7582 right = IC_RIGHT(ic);
7583 result = IC_RESULT(ic) ;
7585 /* depending on the type of pointer we need to
7586 move it to the correct pointer register */
7587 type = operandType(result);
7588 etype = getSpec(type);
7589 /* if left is of type of pointer then it is simple */
7590 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7591 p_type = DCL_TYPE(type);
7594 /* we have to go by the storage class */
7595 p_type = PTR_TYPE(SPEC_OCLS(etype));
7597 /* if (SPEC_OCLS(etype)->codesp ) { */
7598 /* p_type = CPOINTER ; */
7601 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7602 /* p_type = FPOINTER ; */
7604 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7605 /* p_type = PPOINTER ; */
7607 /* if (SPEC_OCLS(etype) == idata ) */
7608 /* p_type = IPOINTER ; */
7610 /* p_type = POINTER ; */
7613 /* now that we have the pointer type we assign
7614 the pointer values */
7619 genNearPointerSet (right,result,ic);
7623 genPagedPointerSet (right,result,ic);
7627 genFarPointerSet (right,result,ic);
7631 genGenPointerSet (right,result,ic);
7637 /*-----------------------------------------------------------------*/
7638 /* genIfx - generate code for Ifx statement */
7639 /*-----------------------------------------------------------------*/
7640 static void genIfx (iCode *ic, iCode *popIc)
7642 operand *cond = IC_COND(ic);
7645 D(emitcode(";", "genIfx "););
7647 aopOp(cond,ic,FALSE, FALSE);
7649 /* get the value into acc */
7650 if (AOP_TYPE(cond) != AOP_CRY)
7654 /* the result is now in the accumulator */
7655 freeAsmop(cond,NULL,ic,TRUE);
7657 /* if there was something to be popped then do it */
7661 /* if the condition is a bit variable */
7662 if (isbit && IS_ITEMP(cond) &&
7664 genIfxJump(ic,SPIL_LOC(cond)->rname);
7666 if (isbit && !IS_ITEMP(cond))
7667 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7674 /*-----------------------------------------------------------------*/
7675 /* genAddrOf - generates code for address of */
7676 /*-----------------------------------------------------------------*/
7677 static void genAddrOf (iCode *ic)
7679 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7682 D(emitcode(";", "genAddrOf "););
7684 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7686 /* if the operand is on the stack then we
7687 need to get the stack offset of this
7690 /* if it has an offset then we need to compute
7693 emitcode("mov","a,_bp");
7694 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7695 aopPut(AOP(IC_RESULT(ic)),"a",0);
7697 /* we can just move _bp */
7698 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7700 /* fill the result with zero */
7701 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7704 if (options.stack10bit && size < (FPTRSIZE - 1))
7707 "*** warning: pointer to stack var truncated.\n");
7714 if (options.stack10bit && offset == 2)
7716 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7720 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7727 /* object not on stack then we need the name */
7728 size = AOP_SIZE(IC_RESULT(ic));
7732 char s[SDCC_NAME_MAX];
7734 sprintf(s,"#(%s >> %d)",
7738 sprintf(s,"#%s",sym->rname);
7739 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7743 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7747 /*-----------------------------------------------------------------*/
7748 /* genFarFarAssign - assignment when both are in far space */
7749 /*-----------------------------------------------------------------*/
7750 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7752 int size = AOP_SIZE(right);
7759 /* This is a net loss for size == 1, but a big gain
7762 D(emitcode(";", "genFarFarAssign (improved)"););
7764 aopOp(result,ic,TRUE, TRUE);
7766 _startLazyDPSEvaluation();
7770 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7774 _endLazyDPSEvaluation();
7775 freeAsmop(result,NULL,ic,FALSE);
7776 freeAsmop(right,NULL,ic,FALSE);
7781 D(emitcode(";", "genFarFarAssign "););
7783 /* first push the right side on to the stack */
7784 _startLazyDPSEvaluation();
7786 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7788 emitcode ("push","acc");
7791 freeAsmop(right,NULL,ic,FALSE);
7792 /* now assign DPTR to result */
7793 aopOp(result,ic,FALSE, FALSE);
7794 size = AOP_SIZE(result);
7796 emitcode ("pop","acc");
7797 aopPut(AOP(result),"a",--offset);
7799 freeAsmop(result,NULL,ic,FALSE);
7800 _endLazyDPSEvaluation();
7804 /*-----------------------------------------------------------------*/
7805 /* genAssign - generate code for assignment */
7806 /*-----------------------------------------------------------------*/
7807 static void genAssign (iCode *ic)
7809 operand *result, *right;
7811 unsigned long lit = 0L;
7813 D(emitcode(";", "genAssign "););
7815 result = IC_RESULT(ic);
7816 right = IC_RIGHT(ic) ;
7818 /* if they are the same */
7819 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7822 aopOp(right,ic,FALSE, FALSE);
7824 emitcode(";", "genAssign: resultIsFar = %s",
7825 isOperandInFarSpace(result) ?
7828 /* special case both in far space */
7829 if ((AOP_TYPE(right) == AOP_DPTR ||
7830 AOP_TYPE(right) == AOP_DPTR2) &&
7831 /* IS_TRUE_SYMOP(result) && */
7832 isOperandInFarSpace(result)) {
7834 genFarFarAssign (result,right,ic);
7838 aopOp(result,ic,TRUE, FALSE);
7840 /* if they are the same registers */
7841 if (sameRegs(AOP(right),AOP(result)))
7844 /* if the result is a bit */
7845 if (AOP_TYPE(result) == AOP_CRY) {
7847 /* if the right size is a literal then
7848 we know what the value is */
7849 if (AOP_TYPE(right) == AOP_LIT) {
7850 if (((int) operandLitValue(right)))
7851 aopPut(AOP(result),one,0);
7853 aopPut(AOP(result),zero,0);
7857 /* the right is also a bit variable */
7858 if (AOP_TYPE(right) == AOP_CRY) {
7859 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7860 aopPut(AOP(result),"c",0);
7866 aopPut(AOP(result),"a",0);
7870 /* bit variables done */
7872 size = AOP_SIZE(result);
7874 if(AOP_TYPE(right) == AOP_LIT)
7875 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7878 (AOP_TYPE(result) != AOP_REG) &&
7879 (AOP_TYPE(right) == AOP_LIT) &&
7880 !IS_FLOAT(operandType(right))
7881 #ifndef LAZY_DPS_OPT
7887 D(emitcode(";", "Kevin's better literal load code"););
7888 _startLazyDPSEvaluation();
7889 while (size && ((unsigned int)((lit >> (offset*8)) & 0xff) != 0))
7892 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
7897 /* And now fill the rest with zeros. */
7900 emitcode("clr","a");
7904 aopPut(AOP(result), "a", offset++);
7906 _endLazyDPSEvaluation();
7908 emitcode("clr","a");
7910 _startLazyDPSEvaluation();
7913 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7914 aopPut(AOP(result),"a",size);
7917 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
7920 _endLazyDPSEvaluation();
7925 _startLazyDPSEvaluation();
7929 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7933 _endLazyDPSEvaluation();
7937 freeAsmop (right,NULL,ic,FALSE);
7938 freeAsmop (result,NULL,ic,TRUE);
7941 /*-----------------------------------------------------------------*/
7942 /* genJumpTab - generates code for jump table */
7943 /*-----------------------------------------------------------------*/
7944 static void genJumpTab (iCode *ic)
7949 D(emitcode(";", "genJumpTab "););
7951 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7952 /* get the condition into accumulator */
7953 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
7955 /* multiply by four! */
7956 emitcode("add","a,acc");
7957 emitcode("add","a,acc");
7958 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7960 jtab = newiTempLabel(NULL);
7961 emitcode("mov","dptr,#%05d$",jtab->key+100);
7962 emitcode("jmp","@a+dptr");
7963 emitcode("","%05d$:",jtab->key+100);
7964 /* now generate the jump labels */
7965 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7966 jtab = setNextItem(IC_JTLABELS(ic)))
7967 emitcode("ljmp","%05d$",jtab->key+100);
7971 /*-----------------------------------------------------------------*/
7972 /* genCast - gen code for casting */
7973 /*-----------------------------------------------------------------*/
7974 static void genCast (iCode *ic)
7976 operand *result = IC_RESULT(ic);
7977 link *ctype = operandType(IC_LEFT(ic));
7978 link *rtype = operandType(IC_RIGHT(ic));
7979 operand *right = IC_RIGHT(ic);
7982 D(emitcode(";", "genCast "););
7984 /* if they are equivalent then do nothing */
7985 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7988 aopOp(right,ic,FALSE, FALSE) ;
7989 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7991 /* if the result is a bit */
7992 if (AOP_TYPE(result) == AOP_CRY) {
7993 /* if the right size is a literal then
7994 we know what the value is */
7995 if (AOP_TYPE(right) == AOP_LIT) {
7996 if (((int) operandLitValue(right)))
7997 aopPut(AOP(result),one,0);
7999 aopPut(AOP(result),zero,0);
8004 /* the right is also a bit variable */
8005 if (AOP_TYPE(right) == AOP_CRY) {
8006 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8007 aopPut(AOP(result),"c",0);
8013 aopPut(AOP(result),"a",0);
8017 /* if they are the same size : or less */
8018 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8020 /* if they are in the same place */
8021 if (sameRegs(AOP(right),AOP(result)))
8024 /* if they in different places then copy */
8025 size = AOP_SIZE(result);
8027 _startLazyDPSEvaluation();
8030 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8034 _endLazyDPSEvaluation();
8039 /* if the result is of type pointer */
8040 if (IS_PTR(ctype)) {
8043 link *type = operandType(right);
8045 /* pointer to generic pointer */
8046 if (IS_GENPTR(ctype)) {
8051 p_type = DCL_TYPE(type);
8055 #if OLD_CAST_BEHAVIOR
8056 /* KV: we are converting a non-pointer type to
8057 * a generic pointer. This (ifdef'd out) code
8058 * says that the resulting generic pointer
8059 * should have the same class as the storage
8060 * location of the non-pointer variable.
8062 * For example, converting an int (which happens
8063 * to be stored in DATA space) to a pointer results
8064 * in a DATA generic pointer; if the original int
8065 * in XDATA space, so will be the resulting pointer.
8067 * I don't like that behavior, and thus this change:
8068 * all such conversions will be forced to XDATA and
8069 * throw a warning. If you want some non-XDATA
8070 * type, or you want to suppress the warning, you
8071 * must go through an intermediate cast, like so:
8073 * char _generic *gp = (char _xdata *)(intVar);
8075 link *etype = getSpec(type);
8077 /* we have to go by the storage class */
8078 if (SPEC_OCLS(etype) != generic)
8080 p_type = PTR_TYPE(SPEC_OCLS(etype));
8085 /* Converting unknown class (i.e. register variable)
8086 * to generic pointer. This is not good, but
8087 * we'll make a guess (and throw a warning).
8090 werror(W_INT_TO_GEN_PTR_CAST);
8094 /* the first two bytes are known */
8095 size = GPTRSIZE - 1;
8097 _startLazyDPSEvaluation();
8100 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8104 _endLazyDPSEvaluation();
8106 /* the last byte depending on type */
8123 /* this should never happen */
8124 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8125 "got unknown pointer type");
8128 aopPut(AOP(result),l, GPTRSIZE - 1);
8132 /* just copy the pointers */
8133 size = AOP_SIZE(result);
8135 _startLazyDPSEvaluation();
8138 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8142 _endLazyDPSEvaluation();
8146 /* so we now know that the size of destination is greater
8147 than the size of the source */
8148 /* we move to result for the size of source */
8149 size = AOP_SIZE(right);
8151 _startLazyDPSEvaluation();
8154 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8158 _endLazyDPSEvaluation();
8160 /* now depending on the sign of the source && destination */
8161 size = AOP_SIZE(result) - AOP_SIZE(right);
8162 /* if unsigned or not an integral type */
8163 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
8165 aopPut(AOP(result),zero,offset++);
8167 /* we need to extend the sign :{ */
8168 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8171 emitcode("rlc","a");
8172 emitcode("subb","a,acc");
8174 aopPut(AOP(result),"a",offset++);
8177 /* we are done hurray !!!! */
8180 freeAsmop(right,NULL,ic,TRUE);
8181 freeAsmop(result,NULL,ic,TRUE);
8185 /*-----------------------------------------------------------------*/
8186 /* genDjnz - generate decrement & jump if not zero instrucion */
8187 /*-----------------------------------------------------------------*/
8188 static int genDjnz (iCode *ic, iCode *ifx)
8194 /* if the if condition has a false label
8195 then we cannot save */
8199 /* if the minus is not of the form
8201 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8202 !IS_OP_LITERAL(IC_RIGHT(ic)))
8205 if (operandLitValue(IC_RIGHT(ic)) != 1)
8208 /* if the size of this greater than one then no
8210 if (getSize(operandType(IC_RESULT(ic))) > 1)
8213 /* otherwise we can save BIG */
8214 lbl = newiTempLabel(NULL);
8215 lbl1= newiTempLabel(NULL);
8217 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8219 if (IS_AOP_PREG(IC_RESULT(ic))) {
8220 emitcode("dec","%s",
8221 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8222 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8223 emitcode("jnz","%05d$",lbl->key+100);
8225 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8228 emitcode ("sjmp","%05d$",lbl1->key+100);
8229 emitcode ("","%05d$:",lbl->key+100);
8230 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8231 emitcode ("","%05d$:",lbl1->key+100);
8233 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8238 /*-----------------------------------------------------------------*/
8239 /* genReceive - generate code for a receive iCode */
8240 /*-----------------------------------------------------------------*/
8241 static void genReceive (iCode *ic)
8244 D(emitcode(";", "genReceive "););
8246 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8247 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8248 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8249 int size = getSize(operandType(IC_RESULT(ic)));
8250 int offset = fReturnSize_390 - size;
8252 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8253 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8256 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8257 size = AOP_SIZE(IC_RESULT(ic));
8260 emitcode ("pop","acc");
8261 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8266 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8268 assignResultValue(IC_RESULT(ic));
8271 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8274 /*-----------------------------------------------------------------*/
8275 /* gen390Code - generate code for 8051 based controllers */
8276 /*-----------------------------------------------------------------*/
8277 void gen390Code (iCode *lic)
8282 lineHead = lineCurr = NULL;
8284 /* print the allocation information */
8286 printAllocInfo( currFunc, codeOutFile);
8287 /* if debug information required */
8288 /* if (options.debug && currFunc) { */
8290 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8292 if (IS_STATIC(currFunc->etype))
8293 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8295 emitcode("","G$%s$0$0 ==.",currFunc->name);
8298 /* stack pointer name */
8299 if (options.useXstack)
8305 for (ic = lic ; ic ; ic = ic->next ) {
8307 if ( cln != ic->lineno ) {
8308 if ( options.debug ) {
8310 emitcode("","C$%s$%d$%d$%d ==.",
8311 ic->filename,ic->lineno,
8312 ic->level,ic->block);
8315 emitcode(";","%s %d",ic->filename,ic->lineno);
8318 /* if the result is marked as
8319 spilt and rematerializable or code for
8320 this has already been generated then
8322 if (resultRemat(ic) || ic->generated )
8325 /* depending on the operation */
8344 /* IPOP happens only when trying to restore a
8345 spilt live range, if there is an ifx statement
8346 following this pop then the if statement might
8347 be using some of the registers being popped which
8348 would destory the contents of the register so
8349 we need to check for this condition and handle it */
8351 ic->next->op == IFX &&
8352 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8353 genIfx (ic->next,ic);
8371 genEndFunction (ic);
8391 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8408 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8412 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8419 /* note these two are xlated by algebraic equivalence
8420 during parsing SDCC.y */
8421 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8422 "got '>=' or '<=' shouldn't have come here");
8426 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8438 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8442 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8446 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8473 case GET_VALUE_AT_ADDRESS:
8478 if (POINTER_SET(ic))
8505 addSet(&_G.sendSet,ic);
8510 /* piCode(ic,stdout); */
8516 /* now we are ready to call the
8517 peep hole optimizer */
8518 if (!options.nopeep)
8519 peepHole (&lineHead);
8521 /* now do the actual printing */
8522 printLine (lineHead,codeOutFile);