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");
1185 /*-----------------------------------------------------------------*/
1186 /* pointToEnd :- points to the last byte of the operand */
1187 /*-----------------------------------------------------------------*/
1188 static void pointToEnd (asmop *aop)
1194 aop->coff = count = (aop->size - 1);
1195 switch (aop->type) {
1199 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1203 emitcode("inc","dptr");
1210 /*-----------------------------------------------------------------*/
1211 /* reAdjustPreg - points a register back to where it should */
1212 /*-----------------------------------------------------------------*/
1213 static void reAdjustPreg (asmop *aop)
1218 if ((size = aop->size) <= 1)
1221 switch (aop->type) {
1225 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1229 if (aop->type == AOP_DPTR2)
1236 emitcode("lcall","__decdptr");
1239 if (aop->type == AOP_DPTR2)
1249 #define AOP(op) op->aop
1250 #define AOP_TYPE(op) AOP(op)->type
1251 #define AOP_SIZE(op) AOP(op)->size
1252 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1253 AOP_TYPE(x) == AOP_R0))
1255 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1256 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1259 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1260 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1261 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1263 /* Workaround for DS80C390 bug: div ab may return bogus results
1264 * if A is accessed in instruction immediately before the div.
1266 * Will be fixed in B4 rev of processor, Dallas claims.
1269 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1270 if (!AOP_NEEDSACC(RIGHT)) \
1272 /* We can load A first, then B, since \
1273 * B (the RIGHT operand) won't clobber A, \
1274 * thus avoiding touching A right before the div. \
1276 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1277 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1279 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1283 /* Just stuff in a nop after loading A. */ \
1284 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1285 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1287 emitcode("nop", "; workaround for DS80C390 div bug."); \
1290 /*-----------------------------------------------------------------*/
1291 /* genNotFloat - generates not for float operations */
1292 /*-----------------------------------------------------------------*/
1293 static void genNotFloat (operand *op, operand *res)
1299 D(emitcode(";", "genNotFloat "););
1301 /* we will put 127 in the first byte of
1303 aopPut(AOP(res),"#127",0);
1304 size = AOP_SIZE(op) - 1;
1307 _startLazyDPSEvaluation();
1308 l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
1312 emitcode("orl","a,%s",
1314 offset++,FALSE,FALSE,FALSE));
1316 _endLazyDPSEvaluation();
1317 tlbl = newiTempLabel(NULL);
1319 tlbl = newiTempLabel(NULL);
1320 aopPut(res->aop,one,1);
1321 emitcode("jz","%05d$",(tlbl->key+100));
1322 aopPut(res->aop,zero,1);
1323 emitcode("","%05d$:",(tlbl->key+100));
1325 size = res->aop->size - 2;
1327 /* put zeros in the rest */
1329 aopPut(res->aop,zero,offset++);
1332 /*-----------------------------------------------------------------*/
1333 /* opIsGptr: returns non-zero if the passed operand is */
1334 /* a generic pointer type. */
1335 /*-----------------------------------------------------------------*/
1336 static int opIsGptr(operand *op)
1338 link *type = operandType(op);
1340 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1347 /*-----------------------------------------------------------------*/
1348 /* getDataSize - get the operand data size */
1349 /*-----------------------------------------------------------------*/
1350 static int getDataSize(operand *op)
1353 size = AOP_SIZE(op);
1354 if (size == GPTRSIZE)
1356 link *type = operandType(op);
1357 if (IS_GENPTR(type))
1359 /* generic pointer; arithmetic operations
1360 * should ignore the high byte (pointer type).
1368 /*-----------------------------------------------------------------*/
1369 /* outAcc - output Acc */
1370 /*-----------------------------------------------------------------*/
1371 static void outAcc(operand *result)
1374 size = getDataSize(result);
1376 aopPut(AOP(result),"a",0);
1379 /* unsigned or positive */
1381 aopPut(AOP(result),zero,offset++);
1386 /*-----------------------------------------------------------------*/
1387 /* outBitC - output a bit C */
1388 /*-----------------------------------------------------------------*/
1389 static void outBitC(operand *result)
1391 /* if the result is bit */
1392 if (AOP_TYPE(result) == AOP_CRY)
1393 aopPut(AOP(result),"c",0);
1395 emitcode("clr","a");
1396 emitcode("rlc","a");
1401 /*-----------------------------------------------------------------*/
1402 /* toBoolean - emit code for orl a,operator(sizeop) */
1403 /*-----------------------------------------------------------------*/
1404 static void toBoolean(operand *oper)
1406 int size = AOP_SIZE(oper) - 1;
1409 /* The generic part of a generic pointer should
1410 * not participate in it's truth value.
1412 * i.e. 0x10000000 is zero.
1416 D(emitcode(";", "toBoolean: generic ptr special case."););
1420 _startLazyDPSEvaluation();
1421 if (AOP_NEEDSACC(oper))
1423 emitcode("push", "b");
1424 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1428 MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1432 if (AOP_NEEDSACC(oper))
1434 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1438 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1441 _endLazyDPSEvaluation();
1443 if (AOP_NEEDSACC(oper))
1445 emitcode("mov", "a,b");
1446 emitcode("pop", "b");
1451 /*-----------------------------------------------------------------*/
1452 /* genNot - generate code for ! operation */
1453 /*-----------------------------------------------------------------*/
1454 static void genNot (iCode *ic)
1457 link *optype = operandType(IC_LEFT(ic));
1459 D(emitcode(";", "genNot "););
1461 /* assign asmOps to operand & result */
1462 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1463 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1465 /* if in bit space then a special case */
1466 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1467 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1468 emitcode("cpl","c");
1469 outBitC(IC_RESULT(ic));
1473 /* if type float then do float */
1474 if (IS_FLOAT(optype)) {
1475 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1479 toBoolean(IC_LEFT(ic));
1481 tlbl = newiTempLabel(NULL);
1482 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1483 emitcode("","%05d$:",tlbl->key+100);
1484 outBitC(IC_RESULT(ic));
1487 /* release the aops */
1488 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1489 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1493 /*-----------------------------------------------------------------*/
1494 /* genCpl - generate code for complement */
1495 /*-----------------------------------------------------------------*/
1496 static void genCpl (iCode *ic)
1501 D(emitcode(";", "genCpl "););
1504 /* assign asmOps to operand & result */
1505 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1506 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1508 /* if both are in bit space then
1510 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1511 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1513 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1514 emitcode("cpl","c");
1515 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1519 size = AOP_SIZE(IC_RESULT(ic));
1520 _startLazyDPSEvaluation();
1522 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1524 emitcode("cpl","a");
1525 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1527 _endLazyDPSEvaluation();
1531 /* release the aops */
1532 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1533 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1536 /*-----------------------------------------------------------------*/
1537 /* genUminusFloat - unary minus for floating points */
1538 /*-----------------------------------------------------------------*/
1539 static void genUminusFloat(operand *op,operand *result)
1541 int size ,offset =0 ;
1543 /* for this we just need to flip the
1544 first it then copy the rest in place */
1545 D(emitcode(";", "genUminusFloat"););
1547 _startLazyDPSEvaluation();
1548 size = AOP_SIZE(op) - 1;
1549 l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1552 emitcode("cpl","acc.7");
1553 aopPut(AOP(result),"a",3);
1557 aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1561 _endLazyDPSEvaluation();
1564 /*-----------------------------------------------------------------*/
1565 /* genUminus - unary minus code generation */
1566 /*-----------------------------------------------------------------*/
1567 static void genUminus (iCode *ic)
1570 link *optype, *rtype;
1572 D(emitcode(";", "genUminus "););
1576 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1577 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1579 /* if both in bit space then special
1581 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1582 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1584 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1585 emitcode("cpl","c");
1586 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1590 optype = operandType(IC_LEFT(ic));
1591 rtype = operandType(IC_RESULT(ic));
1593 /* if float then do float stuff */
1594 if (IS_FLOAT(optype)) {
1595 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1599 /* otherwise subtract from zero */
1600 size = AOP_SIZE(IC_LEFT(ic));
1603 _startLazyDPSEvaluation();
1605 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1606 if (!strcmp(l,"a")) {
1609 emitcode("cpl","a");
1610 emitcode("addc", "a,#0");
1614 emitcode("clr","a");
1615 emitcode("subb","a,%s",l);
1617 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1619 _endLazyDPSEvaluation();
1621 /* if any remaining bytes in the result */
1622 /* we just need to propagate the sign */
1623 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1624 emitcode("rlc","a");
1625 emitcode("subb","a,acc");
1627 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1631 /* release the aops */
1632 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1633 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1636 /*-----------------------------------------------------------------*/
1637 /* saveRegisters - will look for a call and save the registers */
1638 /*-----------------------------------------------------------------*/
1639 static void saveRegisters(iCode *lic)
1647 for (ic = lic ; ic ; ic = ic->next)
1648 if (ic->op == CALL || ic->op == PCALL)
1652 fprintf(stderr,"found parameter push with no function call\n");
1656 /* if the registers have been saved already then
1658 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1661 /* find the registers in use at this time
1662 and push them away to safety */
1663 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1667 if (options.useXstack) {
1668 if (bitVectBitValue(rsave,R0_IDX))
1669 emitcode("mov","b,r0");
1670 emitcode("mov","r0,%s",spname);
1671 for (i = 0 ; i < ds390_nRegs ; i++) {
1672 if (bitVectBitValue(rsave,i)) {
1674 emitcode("mov","a,b");
1676 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1677 emitcode("movx","@r0,a");
1678 emitcode("inc","r0");
1681 emitcode("mov","%s,r0",spname);
1682 if (bitVectBitValue(rsave,R0_IDX))
1683 emitcode("mov","r0,b");
1685 for (i = 0 ; i < ds390_nRegs ; i++) {
1686 if (bitVectBitValue(rsave,i))
1687 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1690 detype = getSpec(operandType(IC_LEFT(ic)));
1692 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1693 IS_ISR(currFunc->etype) &&
1696 saverbank(SPEC_BANK(detype),ic,TRUE);
1699 /*-----------------------------------------------------------------*/
1700 /* unsaveRegisters - pop the pushed registers */
1701 /*-----------------------------------------------------------------*/
1702 static void unsaveRegisters (iCode *ic)
1706 /* find the registers in use at this time
1707 and push them away to safety */
1708 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1711 if (options.useXstack) {
1712 emitcode("mov","r0,%s",spname);
1713 for (i = ds390_nRegs ; i >= 0 ; i--) {
1714 if (bitVectBitValue(rsave,i)) {
1715 emitcode("dec","r0");
1716 emitcode("movx","a,@r0");
1718 emitcode("mov","b,a");
1720 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1724 emitcode("mov","%s,r0",spname);
1725 if (bitVectBitValue(rsave,R0_IDX))
1726 emitcode("mov","r0,b");
1728 for (i = ds390_nRegs ; i >= 0 ; i--) {
1729 if (bitVectBitValue(rsave,i))
1730 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1736 /*-----------------------------------------------------------------*/
1738 /*-----------------------------------------------------------------*/
1739 static void pushSide(operand * oper, int size)
1742 _startLazyDPSEvaluation();
1744 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1745 if (AOP_TYPE(oper) != AOP_REG &&
1746 AOP_TYPE(oper) != AOP_DIR &&
1748 emitcode("mov","a,%s",l);
1749 emitcode("push","acc");
1751 emitcode("push","%s",l);
1753 _endLazyDPSEvaluation();
1756 /*-----------------------------------------------------------------*/
1757 /* assignResultValue - */
1758 /*-----------------------------------------------------------------*/
1759 static void assignResultValue(operand * oper)
1762 int size = AOP_SIZE(oper);
1764 _startLazyDPSEvaluation();
1766 aopPut(AOP(oper),fReturn[offset],offset);
1769 _endLazyDPSEvaluation();
1773 /*-----------------------------------------------------------------*/
1774 /* genXpush - pushes onto the external stack */
1775 /*-----------------------------------------------------------------*/
1776 static void genXpush (iCode *ic)
1778 asmop *aop = newAsmop(0);
1780 int size,offset = 0;
1782 D(emitcode(";", "genXpush "););
1784 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1785 r = getFreePtr(ic,&aop,FALSE);
1788 emitcode("mov","%s,_spx",r->name);
1790 size = AOP_SIZE(IC_LEFT(ic));
1791 _startLazyDPSEvaluation();
1794 char *l = aopGet(AOP(IC_LEFT(ic)),
1795 offset++,FALSE,FALSE,TRUE);
1797 emitcode("movx","@%s,a",r->name);
1798 emitcode("inc","%s",r->name);
1801 _endLazyDPSEvaluation();
1804 emitcode("mov","_spx,%s",r->name);
1806 freeAsmop(NULL,aop,ic,TRUE);
1807 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1810 /*-----------------------------------------------------------------*/
1811 /* genIpush - genrate code for pushing this gets a little complex */
1812 /*-----------------------------------------------------------------*/
1813 static void genIpush (iCode *ic)
1815 int size, offset = 0 ;
1818 D(emitcode(";", "genIpush "););
1821 /* if this is not a parm push : ie. it is spill push
1822 and spill push is always done on the local stack */
1823 if (!ic->parmPush) {
1825 /* and the item is spilt then do nothing */
1826 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1829 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1830 size = AOP_SIZE(IC_LEFT(ic));
1831 /* push it on the stack */
1832 _startLazyDPSEvaluation();
1834 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1839 emitcode("push","%s",l);
1841 _endLazyDPSEvaluation();
1845 /* this is a paramter push: in this case we call
1846 the routine to find the call and save those
1847 registers that need to be saved */
1850 /* if use external stack then call the external
1851 stack pushing routine */
1852 if (options.useXstack) {
1857 /* then do the push */
1858 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1861 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1862 size = AOP_SIZE(IC_LEFT(ic));
1864 _startLazyDPSEvaluation();
1866 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1867 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1868 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1870 emitcode("mov","a,%s",l);
1871 emitcode("push","acc");
1873 emitcode("push","%s",l);
1875 _endLazyDPSEvaluation();
1877 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1880 /*-----------------------------------------------------------------*/
1881 /* genIpop - recover the registers: can happen only for spilling */
1882 /*-----------------------------------------------------------------*/
1883 static void genIpop (iCode *ic)
1887 D(emitcode(";", "genIpop "););
1890 /* if the temp was not pushed then */
1891 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1894 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1895 size = AOP_SIZE(IC_LEFT(ic));
1897 _startLazyDPSEvaluation();
1900 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1903 _endLazyDPSEvaluation();
1905 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1908 /*-----------------------------------------------------------------*/
1909 /* unsaverbank - restores the resgister bank from stack */
1910 /*-----------------------------------------------------------------*/
1911 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1918 if (options.useXstack) {
1920 r = getFreePtr(ic,&aop,FALSE);
1923 emitcode("mov","%s,_spx",r->name);
1924 emitcode("movx","a,@%s",r->name);
1925 emitcode("mov","psw,a");
1926 emitcode("dec","%s",r->name);
1929 emitcode ("pop","psw");
1932 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1933 if (options.useXstack) {
1934 emitcode("movx","a,@%s",r->name);
1935 emitcode("mov","(%s+%d),a",
1936 regs390[i].base,8*bank+regs390[i].offset);
1937 emitcode("dec","%s",r->name);
1940 emitcode("pop","(%s+%d)",
1941 regs390[i].base,8*bank+regs390[i].offset);
1944 if (options.useXstack) {
1946 emitcode("mov","_spx,%s",r->name);
1947 freeAsmop(NULL,aop,ic,TRUE);
1952 /*-----------------------------------------------------------------*/
1953 /* saverbank - saves an entire register bank on the stack */
1954 /*-----------------------------------------------------------------*/
1955 static void saverbank (int bank, iCode *ic, bool pushPsw)
1961 if (options.useXstack) {
1964 r = getFreePtr(ic,&aop,FALSE);
1965 emitcode("mov","%s,_spx",r->name);
1969 for (i = 0 ; i < ds390_nRegs ;i++) {
1970 if (options.useXstack) {
1971 emitcode("inc","%s",r->name);
1972 emitcode("mov","a,(%s+%d)",
1973 regs390[i].base,8*bank+regs390[i].offset);
1974 emitcode("movx","@%s,a",r->name);
1976 emitcode("push","(%s+%d)",
1977 regs390[i].base,8*bank+regs390[i].offset);
1981 if (options.useXstack) {
1982 emitcode("mov","a,psw");
1983 emitcode("movx","@%s,a",r->name);
1984 emitcode("inc","%s",r->name);
1985 emitcode("mov","_spx,%s",r->name);
1986 freeAsmop (NULL,aop,ic,TRUE);
1989 emitcode("push","psw");
1991 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1997 /*-----------------------------------------------------------------*/
1998 /* genCall - generates a call statement */
1999 /*-----------------------------------------------------------------*/
2000 static void genCall (iCode *ic)
2004 D(emitcode(";", "genCall "););
2006 /* if caller saves & we have not saved then */
2010 /* if we are calling a function that is not using
2011 the same register bank then we need to save the
2012 destination registers on the stack */
2013 detype = getSpec(operandType(IC_LEFT(ic)));
2015 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2016 IS_ISR(currFunc->etype) &&
2019 saverbank(SPEC_BANK(detype),ic,TRUE);
2021 /* if send set is not empty the assign */
2025 for (sic = setFirstItem(_G.sendSet) ; sic ;
2026 sic = setNextItem(_G.sendSet))
2028 int size, offset = 0;
2030 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
2031 size = AOP_SIZE(IC_LEFT(sic));
2033 _startLazyDPSEvaluation();
2035 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2036 FALSE, FALSE, TRUE);
2037 if (strcmp(l,fReturn[offset]))
2038 emitcode("mov","%s,%s",
2043 _endLazyDPSEvaluation();
2044 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2049 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2050 OP_SYMBOL(IC_LEFT(ic))->rname :
2051 OP_SYMBOL(IC_LEFT(ic))->name));
2053 /* if we need assign a result value */
2054 if ((IS_ITEMP(IC_RESULT(ic)) &&
2055 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2056 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2057 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2060 /* Not really related to LAZY_DPS_OPT, but don't want
2061 * another testing flag right now...
2064 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2067 assignResultValue(IC_RESULT(ic));
2069 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2072 if (!isOperandInFarSpace(IC_RESULT(ic)))
2075 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2078 assignResultValue(IC_RESULT(ic));
2080 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2084 /* Result is in far space, and requires DPTR to access
2085 * it. Push the result onto the stack and restore from
2088 int size = getSize(operandType(IC_RESULT(ic)));
2089 int offset = size - 1;
2092 emitcode(";", "Kevin function call abuse #1");
2094 /* first push the right side on to the stack */
2095 /* NB: this relies on the fact that "a" is the last
2096 * register in fReturn. If it were not, the MOVA
2097 * would potentially clobber a returned byte in A.
2100 l = fReturn[offset--];
2102 emitcode ("push","acc");
2105 /* now assign DPTR to result */
2106 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2107 size = AOP_SIZE(IC_RESULT(ic));
2108 aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
2110 emitcode ("pop","acc");
2111 aopPut(AOP(IC_RESULT(ic)),"a",++offset);
2113 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2118 /* adjust the stack for parameters if
2120 if (IC_LEFT(ic)->parmBytes) {
2122 if (IC_LEFT(ic)->parmBytes > 3) {
2123 emitcode("mov","a,%s",spname);
2124 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2125 emitcode("mov","%s,a",spname);
2127 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2128 emitcode("dec","%s",spname);
2132 /* if register bank was saved then pop them */
2134 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2136 /* if we hade saved some registers then unsave them */
2137 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2138 unsaveRegisters (ic);
2143 /*-----------------------------------------------------------------*/
2144 /* genPcall - generates a call by pointer statement */
2145 /*-----------------------------------------------------------------*/
2146 static void genPcall (iCode *ic)
2149 symbol *rlbl = newiTempLabel(NULL);
2151 D(emitcode(";", "genPcall "););
2154 /* if caller saves & we have not saved then */
2158 /* if we are calling a function that is not using
2159 the same register bank then we need to save the
2160 destination registers on the stack */
2161 detype = getSpec(operandType(IC_LEFT(ic)));
2163 IS_ISR(currFunc->etype) &&
2164 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2165 saverbank(SPEC_BANK(detype),ic,TRUE);
2168 /* push the return address on to the stack */
2169 emitcode("mov","a,#%05d$",(rlbl->key+100));
2170 emitcode("push","acc");
2171 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2172 emitcode("push","acc");
2174 if (options.model == MODEL_FLAT24)
2176 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2177 emitcode("push","acc");
2180 /* now push the calling address */
2181 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2183 pushSide(IC_LEFT(ic), FPTRSIZE);
2185 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2187 /* if send set is not empty the assign */
2191 for (sic = setFirstItem(_G.sendSet) ; sic ;
2192 sic = setNextItem(_G.sendSet))
2194 int size, offset = 0;
2196 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2197 size = AOP_SIZE(IC_LEFT(sic));
2198 _startLazyDPSEvaluation();
2201 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2203 if (strcmp(l,fReturn[offset]))
2205 emitcode("mov","%s,%s",
2211 _endLazyDPSEvaluation();
2212 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2218 emitcode("","%05d$:",(rlbl->key+100));
2221 /* if we need assign a result value */
2222 if ((IS_ITEMP(IC_RESULT(ic)) &&
2223 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2224 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2225 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2228 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2231 assignResultValue(IC_RESULT(ic));
2233 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2236 /* adjust the stack for parameters if
2238 if (IC_LEFT(ic)->parmBytes) {
2240 if (IC_LEFT(ic)->parmBytes > 3) {
2241 emitcode("mov","a,%s",spname);
2242 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2243 emitcode("mov","%s,a",spname);
2245 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2246 emitcode("dec","%s",spname);
2250 /* if register bank was saved then unsave them */
2252 (SPEC_BANK(currFunc->etype) !=
2254 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2256 /* if we hade saved some registers then
2259 unsaveRegisters (ic);
2263 /*-----------------------------------------------------------------*/
2264 /* resultRemat - result is rematerializable */
2265 /*-----------------------------------------------------------------*/
2266 static int resultRemat (iCode *ic)
2268 if (SKIP_IC(ic) || ic->op == IFX)
2271 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2272 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2273 if (sym->remat && !POINTER_SET(ic))
2281 #define STRCASECMP stricmp
2283 #define STRCASECMP strcasecmp
2286 /*-----------------------------------------------------------------*/
2287 /* inExcludeList - return 1 if the string is in exclude Reg list */
2288 /*-----------------------------------------------------------------*/
2289 static bool inExcludeList(char *s)
2293 if (options.excludeRegs[i] &&
2294 STRCASECMP(options.excludeRegs[i],"none") == 0)
2297 for ( i = 0 ; options.excludeRegs[i]; i++) {
2298 if (options.excludeRegs[i] &&
2299 STRCASECMP(s,options.excludeRegs[i]) == 0)
2305 /*-----------------------------------------------------------------*/
2306 /* genFunction - generated code for function entry */
2307 /*-----------------------------------------------------------------*/
2308 static void genFunction (iCode *ic)
2313 D(emitcode(";", "genFunction "););
2316 /* create the function header */
2317 emitcode(";","-----------------------------------------");
2318 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2319 emitcode(";","-----------------------------------------");
2321 emitcode("","%s:",sym->rname);
2322 fetype = getSpec(operandType(IC_LEFT(ic)));
2324 /* if critical function then turn interrupts off */
2325 if (SPEC_CRTCL(fetype))
2326 emitcode("clr","ea");
2328 /* here we need to generate the equates for the
2329 register bank if required */
2330 if (SPEC_BANK(fetype) != rbank) {
2333 rbank = SPEC_BANK(fetype);
2334 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2335 if (strcmp(regs390[i].base,"0") == 0)
2336 emitcode("","%s = 0x%02x",
2338 8*rbank+regs390[i].offset);
2340 emitcode ("","%s = %s + 0x%02x",
2343 8*rbank+regs390[i].offset);
2347 /* if this is an interrupt service routine then
2348 save acc, b, dpl, dph */
2349 if (IS_ISR(sym->etype)) {
2351 if (!inExcludeList("acc"))
2352 emitcode ("push","acc");
2353 if (!inExcludeList("b"))
2354 emitcode ("push","b");
2355 if (!inExcludeList("dpl"))
2356 emitcode ("push","dpl");
2357 if (!inExcludeList("dph"))
2358 emitcode ("push","dph");
2359 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2361 emitcode ("push", "dpx");
2362 /* Make sure we're using standard DPTR */
2363 emitcode ("push", "dps");
2364 emitcode ("mov", "dps, #0x00");
2365 if (options.stack10bit)
2367 /* This ISR could conceivably use DPTR2. Better save it. */
2368 emitcode ("push", "dpl1");
2369 emitcode ("push", "dph1");
2370 emitcode ("push", "dpx1");
2371 emitcode ("push", "ap");
2374 /* if this isr has no bank i.e. is going to
2375 run with bank 0 , then we need to save more
2377 if (!SPEC_BANK(sym->etype)) {
2379 /* if this function does not call any other
2380 function then we can be economical and
2381 save only those registers that are used */
2382 if (! sym->hasFcall) {
2385 /* if any registers used */
2386 if (sym->regsUsed) {
2387 /* save the registers used */
2388 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2389 if (bitVectBitValue(sym->regsUsed,i) ||
2390 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2391 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2396 /* this function has a function call cannot
2397 determines register usage so we will have the
2399 saverbank(0,ic,FALSE);
2403 /* if callee-save to be used for this function
2404 then save the registers being used in this function */
2405 if (sym->calleeSave) {
2408 /* if any registers used */
2409 if (sym->regsUsed) {
2410 /* save the registers used */
2411 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2412 if (bitVectBitValue(sym->regsUsed,i) ||
2413 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2414 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2422 /* set the register bank to the desired value */
2423 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2424 emitcode("push","psw");
2425 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2428 if (IS_RENT(sym->etype) || options.stackAuto) {
2430 if (options.useXstack) {
2431 emitcode("mov","r0,%s",spname);
2432 emitcode("mov","a,_bp");
2433 emitcode("movx","@r0,a");
2434 emitcode("inc","%s",spname);
2438 /* set up the stack */
2439 emitcode ("push","_bp"); /* save the callers stack */
2441 emitcode ("mov","_bp,%s",spname);
2444 /* adjust the stack for the function */
2449 werror(W_STACK_OVERFLOW,sym->name);
2451 if (i > 3 && sym->recvSize < 4) {
2453 emitcode ("mov","a,sp");
2454 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2455 emitcode ("mov","sp,a");
2460 emitcode("inc","sp");
2465 emitcode ("mov","a,_spx");
2466 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2467 emitcode ("mov","_spx,a");
2472 /*-----------------------------------------------------------------*/
2473 /* genEndFunction - generates epilogue for functions */
2474 /*-----------------------------------------------------------------*/
2475 static void genEndFunction (iCode *ic)
2477 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2479 D(emitcode(";", "genEndFunction "););
2481 if (IS_RENT(sym->etype) || options.stackAuto)
2483 emitcode ("mov","%s,_bp",spname);
2486 /* if use external stack but some variables were
2487 added to the local stack then decrement the
2489 if (options.useXstack && sym->stack) {
2490 emitcode("mov","a,sp");
2491 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2492 emitcode("mov","sp,a");
2496 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2497 if (options.useXstack) {
2498 emitcode("mov","r0,%s",spname);
2499 emitcode("movx","a,@r0");
2500 emitcode("mov","_bp,a");
2501 emitcode("dec","%s",spname);
2505 emitcode ("pop","_bp");
2509 /* restore the register bank */
2510 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2511 emitcode ("pop","psw");
2513 if (IS_ISR(sym->etype)) {
2515 /* now we need to restore the registers */
2516 /* if this isr has no bank i.e. is going to
2517 run with bank 0 , then we need to save more
2519 if (!SPEC_BANK(sym->etype)) {
2521 /* if this function does not call any other
2522 function then we can be economical and
2523 save only those registers that are used */
2524 if (! sym->hasFcall) {
2527 /* if any registers used */
2528 if (sym->regsUsed) {
2529 /* save the registers used */
2530 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2531 if (bitVectBitValue(sym->regsUsed,i) ||
2532 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2533 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2538 /* this function has a function call cannot
2539 determines register usage so we will have the
2541 unsaverbank(0,ic,FALSE);
2545 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2547 if (options.stack10bit)
2549 emitcode ("pop", "ap");
2550 emitcode ("pop", "dpx1");
2551 emitcode ("pop", "dph1");
2552 emitcode ("pop", "dpl1");
2554 emitcode ("pop", "dps");
2555 emitcode ("pop", "dpx");
2557 if (!inExcludeList("dph"))
2558 emitcode ("pop","dph");
2559 if (!inExcludeList("dpl"))
2560 emitcode ("pop","dpl");
2561 if (!inExcludeList("b"))
2562 emitcode ("pop","b");
2563 if (!inExcludeList("acc"))
2564 emitcode ("pop","acc");
2566 if (SPEC_CRTCL(sym->etype))
2567 emitcode("setb","ea");
2569 /* if debug then send end of function */
2570 /* if (options.debug && currFunc) { */
2573 emitcode("","C$%s$%d$%d$%d ==.",
2574 ic->filename,currFunc->lastLine,
2575 ic->level,ic->block);
2576 if (IS_STATIC(currFunc->etype))
2577 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2579 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2583 emitcode ("reti","");
2586 if (SPEC_CRTCL(sym->etype))
2587 emitcode("setb","ea");
2589 if (sym->calleeSave) {
2592 /* if any registers used */
2593 if (sym->regsUsed) {
2594 /* save the registers used */
2595 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2596 if (bitVectBitValue(sym->regsUsed,i) ||
2597 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2598 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2604 /* if debug then send end of function */
2607 emitcode("","C$%s$%d$%d$%d ==.",
2608 ic->filename,currFunc->lastLine,
2609 ic->level,ic->block);
2610 if (IS_STATIC(currFunc->etype))
2611 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2613 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2617 emitcode ("ret","");
2622 /*-----------------------------------------------------------------*/
2623 /* genRet - generate code for return statement */
2624 /*-----------------------------------------------------------------*/
2625 static void genRet (iCode *ic)
2627 int size,offset = 0 , pushed = 0;
2629 D(emitcode(";", "genRet "););
2631 /* if we have no return value then
2632 just generate the "ret" */
2636 /* we have something to return then
2637 move the return value into place */
2638 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2639 size = AOP_SIZE(IC_LEFT(ic));
2641 _startLazyDPSEvaluation();
2644 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2645 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2647 emitcode("push","%s",l);
2650 l = aopGet(AOP(IC_LEFT(ic)),offset,
2652 if (strcmp(fReturn[offset],l))
2653 emitcode("mov","%s,%s",fReturn[offset++],l);
2656 _endLazyDPSEvaluation();
2661 if (strcmp(fReturn[pushed],"a"))
2662 emitcode("pop",fReturn[pushed]);
2664 emitcode("pop","acc");
2667 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2670 /* generate a jump to the return label
2671 if the next is not the return statement */
2672 if (!(ic->next && ic->next->op == LABEL &&
2673 IC_LABEL(ic->next) == returnLabel))
2675 emitcode("ljmp","%05d$",(returnLabel->key+100));
2679 /*-----------------------------------------------------------------*/
2680 /* genLabel - generates a label */
2681 /*-----------------------------------------------------------------*/
2682 static void genLabel (iCode *ic)
2684 /* special case never generate */
2685 if (IC_LABEL(ic) == entryLabel)
2688 D(emitcode(";", "genLabel "););
2690 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2693 /*-----------------------------------------------------------------*/
2694 /* genGoto - generates a ljmp */
2695 /*-----------------------------------------------------------------*/
2696 static void genGoto (iCode *ic)
2698 D(emitcode(";", "genGoto "););
2699 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2702 /*-----------------------------------------------------------------*/
2703 /* findLabelBackwards: walks back through the iCode chain looking */
2704 /* for the given label. Returns number of iCode instructions */
2705 /* between that label and given ic. */
2706 /* Returns zero if label not found. */
2707 /*-----------------------------------------------------------------*/
2708 static int findLabelBackwards(iCode *ic, int key)
2717 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2719 /* printf("findLabelBackwards = %d\n", count); */
2727 /*-----------------------------------------------------------------*/
2728 /* genPlusIncr :- does addition with increment if possible */
2729 /*-----------------------------------------------------------------*/
2730 static bool genPlusIncr (iCode *ic)
2732 unsigned int icount ;
2733 unsigned int size = getDataSize(IC_RESULT(ic));
2735 /* will try to generate an increment */
2736 /* if the right side is not a literal
2738 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2741 /* if the literal value of the right hand side
2742 is greater than 4 then it is not worth it */
2743 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2746 /* if increment 16 bits in register */
2748 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2749 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2750 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2757 /* If the next instruction is a goto and the goto target
2758 * is <= 5 instructions previous to this, we can generate
2759 * jumps straight to that target.
2761 if (ic->next && ic->next->op == GOTO
2762 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2763 && labelRange <= 5 )
2765 emitcode(";", "tail increment optimized (range %d)", labelRange);
2766 tlbl = IC_LABEL(ic->next);
2771 tlbl = newiTempLabel(NULL);
2774 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2775 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2776 IS_AOP_PREG(IC_RESULT(ic)))
2777 emitcode("cjne","%s,#0x00,%05d$"
2778 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2781 emitcode("clr","a");
2782 emitcode("cjne","a,%s,%05d$"
2783 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2787 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2790 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2791 IS_AOP_PREG(IC_RESULT(ic)))
2792 emitcode("cjne","%s,#0x00,%05d$"
2793 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2796 emitcode("cjne","a,%s,%05d$"
2797 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2800 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2804 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2805 IS_AOP_PREG(IC_RESULT(ic)))
2806 emitcode("cjne","%s,#0x00,%05d$"
2807 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2810 emitcode("cjne","a,%s,%05d$"
2811 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2814 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2819 emitcode("","%05d$:",tlbl->key+100);
2824 /* if the sizes are greater than 1 then we cannot */
2825 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2826 AOP_SIZE(IC_LEFT(ic)) > 1 )
2829 /* we can if the aops of the left & result match or
2830 if they are in registers and the registers are the
2833 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2834 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2835 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2838 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2839 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2840 aopPut(AOP(IC_RESULT(ic)),"a",0);
2843 _startLazyDPSEvaluation();
2846 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2848 _endLazyDPSEvaluation();
2857 /*-----------------------------------------------------------------*/
2858 /* outBitAcc - output a bit in acc */
2859 /*-----------------------------------------------------------------*/
2860 static void outBitAcc(operand *result)
2862 symbol *tlbl = newiTempLabel(NULL);
2863 /* if the result is a bit */
2864 if (AOP_TYPE(result) == AOP_CRY){
2865 aopPut(AOP(result),"a",0);
2868 emitcode("jz","%05d$",tlbl->key+100);
2869 emitcode("mov","a,%s",one);
2870 emitcode("","%05d$:",tlbl->key+100);
2875 /*-----------------------------------------------------------------*/
2876 /* genPlusBits - generates code for addition of two bits */
2877 /*-----------------------------------------------------------------*/
2878 static void genPlusBits (iCode *ic)
2880 D(emitcode(";", "genPlusBits "););
2881 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2882 symbol *lbl = newiTempLabel(NULL);
2883 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2884 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2885 emitcode("cpl","c");
2886 emitcode("","%05d$:",(lbl->key+100));
2887 outBitC(IC_RESULT(ic));
2890 emitcode("clr","a");
2891 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2892 emitcode("rlc","a");
2893 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2894 emitcode("addc","a,#0x00");
2895 outAcc(IC_RESULT(ic));
2899 static void adjustArithmeticResult(iCode *ic)
2901 if (opIsGptr(IC_RESULT(ic)) &&
2902 opIsGptr(IC_LEFT(ic)) &&
2903 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2905 aopPut(AOP(IC_RESULT(ic)),
2906 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2910 if (opIsGptr(IC_RESULT(ic)) &&
2911 opIsGptr(IC_RIGHT(ic)) &&
2912 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2914 aopPut(AOP(IC_RESULT(ic)),
2915 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2919 if (opIsGptr(IC_RESULT(ic)) &&
2920 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2921 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2922 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2923 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2925 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2926 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2930 #define AOP_OP_3(ic) \
2931 aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
2932 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
2933 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
2934 if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
2935 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2937 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2939 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2942 #define AOP_SET_LOCALS(ic) \
2943 left = IC_LEFT(ic); \
2944 right = IC_RIGHT(ic); \
2945 result = IC_RESULT(ic);
2947 /*-----------------------------------------------------------------*/
2948 /* genPlus - generates code for addition */
2949 /*-----------------------------------------------------------------*/
2950 static void genPlus (iCode *ic)
2952 int size, offset = 0;
2953 bool pushResult = FALSE;
2956 D(emitcode(";", "genPlus "););
2958 /* special cases :- */
2960 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
2961 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2962 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
2963 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
2969 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR);
2971 /* if literal, literal on the right or
2972 if left requires ACC or right is already
2974 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2975 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2976 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2977 operand *t = IC_RIGHT(ic);
2978 IC_RIGHT(ic) = IC_LEFT(ic);
2982 /* if both left & right are in bit
2984 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2985 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2990 /* if left in bit space & right literal */
2991 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2992 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2993 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2994 /* if result in bit space */
2995 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2996 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2997 emitcode("cpl","c");
2998 outBitC(IC_RESULT(ic));
3000 size = getDataSize(IC_RESULT(ic));
3001 _startLazyDPSEvaluation();
3003 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3004 emitcode("addc","a,#00");
3005 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3007 _endLazyDPSEvaluation();
3012 /* if I can do an increment instead
3013 of add then GOOD for ME */
3014 if (genPlusIncr (ic) == TRUE)
3018 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3020 _startLazyDPSEvaluation();
3023 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3025 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3027 emitcode("add","a,%s",
3028 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3030 emitcode("addc","a,%s",
3031 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3033 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3035 emitcode("add","a,%s",
3036 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3038 emitcode("addc","a,%s",
3039 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3043 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3047 emitcode("push", "acc");
3051 _endLazyDPSEvaluation();
3055 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3057 size = getDataSize(IC_LEFT(ic));
3058 rSize = getDataSize(IC_RESULT(ic));
3060 /* If the pushed data is bigger than the result,
3061 * simply discard unused bytes. Icky, but works.
3063 * Should we throw a warning here? We're losing data...
3065 while (size > rSize)
3067 D(emitcode(";", "discarding unused result byte."););
3068 emitcode("pop", "acc");
3074 emitcode("clr", "a");
3075 /* Conversly, we haven't pushed enough here.
3076 * just zero-pad, and all is well.
3078 while (size < rSize)
3080 emitcode("push", "acc");
3088 emitcode("pop", "acc");
3089 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3093 adjustArithmeticResult(ic);
3096 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3097 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3098 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3101 /*-----------------------------------------------------------------*/
3102 /* genMinusDec :- does subtraction with deccrement if possible */
3103 /*-----------------------------------------------------------------*/
3104 static bool genMinusDec (iCode *ic)
3106 unsigned int icount ;
3107 unsigned int size = getDataSize(IC_RESULT(ic));
3109 /* will try to generate an increment */
3110 /* if the right side is not a literal
3112 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3115 /* if the literal value of the right hand side
3116 is greater than 4 then it is not worth it */
3117 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3120 /* if decrement 16 bits in register */
3121 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3122 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3123 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3130 /* If the next instruction is a goto and the goto target
3131 * is <= 5 instructions previous to this, we can generate
3132 * jumps straight to that target.
3134 if (ic->next && ic->next->op == GOTO
3135 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3136 && labelRange <= 5 )
3138 emitcode(";", "tail decrement optimized (range %d)", labelRange);
3139 tlbl = IC_LABEL(ic->next);
3144 tlbl = newiTempLabel(NULL);
3148 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3149 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3150 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3151 IS_AOP_PREG(IC_RESULT(ic)))
3152 emitcode("cjne","%s,#0xff,%05d$"
3153 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3156 emitcode("mov","a,#0xff");
3157 emitcode("cjne","a,%s,%05d$"
3158 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3161 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3164 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3165 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3166 IS_AOP_PREG(IC_RESULT(ic)))
3167 emitcode("cjne","%s,#0xff,%05d$"
3168 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3171 emitcode("cjne","a,%s,%05d$"
3172 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3175 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3179 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3180 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3181 IS_AOP_PREG(IC_RESULT(ic)))
3182 emitcode("cjne","%s,#0xff,%05d$"
3183 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3186 emitcode("cjne","a,%s,%05d$"
3187 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3190 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3194 emitcode("","%05d$:",tlbl->key+100);
3199 /* if the sizes are greater than 1 then we cannot */
3200 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3201 AOP_SIZE(IC_LEFT(ic)) > 1 )
3204 /* we can if the aops of the left & result match or
3205 if they are in registers and the registers are the
3208 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3209 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3210 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3212 _startLazyDPSEvaluation();
3215 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3217 _endLazyDPSEvaluation();
3225 /*-----------------------------------------------------------------*/
3226 /* addSign - complete with sign */
3227 /*-----------------------------------------------------------------*/
3228 static void addSign(operand *result, int offset, int sign)
3230 int size = (getDataSize(result) - offset);
3233 emitcode("rlc","a");
3234 emitcode("subb","a,acc");
3236 aopPut(AOP(result),"a",offset++);
3239 aopPut(AOP(result),zero,offset++);
3243 /*-----------------------------------------------------------------*/
3244 /* genMinusBits - generates code for subtraction of two bits */
3245 /*-----------------------------------------------------------------*/
3246 static void genMinusBits (iCode *ic)
3248 symbol *lbl = newiTempLabel(NULL);
3250 D(emitcode(";", "genMinusBits "););
3252 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3253 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3254 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3255 emitcode("cpl","c");
3256 emitcode("","%05d$:",(lbl->key+100));
3257 outBitC(IC_RESULT(ic));
3260 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3261 emitcode("subb","a,acc");
3262 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3263 emitcode("inc","a");
3264 emitcode("","%05d$:",(lbl->key+100));
3265 aopPut(AOP(IC_RESULT(ic)),"a",0);
3266 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3270 /*-----------------------------------------------------------------*/
3271 /* genMinus - generates code for subtraction */
3272 /*-----------------------------------------------------------------*/
3273 static void genMinus (iCode *ic)
3275 int size, offset = 0;
3277 unsigned long lit = 0L;
3278 bool pushResult = FALSE;
3280 D(emitcode(";", "genMinus "););
3282 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3283 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3284 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3285 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3291 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3293 /* special cases :- */
3294 /* if both left & right are in bit space */
3295 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3296 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3301 /* if I can do an decrement instead
3302 of subtract then GOOD for ME */
3303 if (genMinusDec (ic) == TRUE)
3308 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3310 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3314 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3319 /* if literal, add a,#-lit, else normal subb */
3320 _startLazyDPSEvaluation();
3322 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3323 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3324 emitcode("subb","a,%s",
3325 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3327 /* first add without previous c */
3329 emitcode("add","a,#0x%02x",
3330 (unsigned int)(lit & 0x0FFL));
3332 emitcode("addc","a,#0x%02x",
3333 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3338 emitcode("push", "acc");
3342 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3346 _endLazyDPSEvaluation();
3350 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3352 size = getDataSize(IC_LEFT(ic));
3353 rSize = getDataSize(IC_RESULT(ic));
3355 /* If the pushed data is bigger than the result,
3356 * simply discard unused bytes. Icky, but works.
3358 * Should we throw a warning here? We're losing data...
3360 while (size > getDataSize(IC_RESULT(ic)))
3362 emitcode(";", "discarding unused result byte.");
3363 emitcode("pop", "acc");
3369 emitcode("clr", "a");
3370 /* Conversly, we haven't pushed enough here.
3371 * just zero-pad, and all is well.
3373 while (size < rSize)
3375 emitcode("push", "acc");
3383 emitcode("pop", "acc");
3384 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3388 adjustArithmeticResult(ic);
3391 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3392 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3393 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3397 /*-----------------------------------------------------------------*/
3398 /* genMultbits :- multiplication of bits */
3399 /*-----------------------------------------------------------------*/
3400 static void genMultbits (operand *left,
3404 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3405 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3410 /*-----------------------------------------------------------------*/
3411 /* genMultOneByte : 8 bit multiplication & division */
3412 /*-----------------------------------------------------------------*/
3413 static void genMultOneByte (operand *left,
3417 link *opetype = operandType(result);
3422 /* (if two literals, the value is computed before) */
3423 /* if one literal, literal on the right */
3424 if (AOP_TYPE(left) == AOP_LIT){
3430 size = AOP_SIZE(result);
3431 /* signed or unsigned */
3432 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3433 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3435 emitcode("mul","ab");
3436 /* if result size = 1, mul signed = mul unsigned */
3437 aopPut(AOP(result),"a",0);
3439 if (SPEC_USIGN(opetype)){
3440 aopPut(AOP(result),"b",1);
3442 /* for filling the MSBs */
3443 emitcode("clr","a");
3446 emitcode("mov","a,b");
3448 /* adjust the MSB if left or right neg */
3450 /* if one literal */
3451 if (AOP_TYPE(right) == AOP_LIT){
3452 /* AND literal negative */
3453 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3454 /* adjust MSB (c==0 after mul) */
3455 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3459 lbl = newiTempLabel(NULL);
3460 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3461 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3462 emitcode("","%05d$:",(lbl->key+100));
3463 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3464 lbl = newiTempLabel(NULL);
3465 emitcode("jc","%05d$",(lbl->key+100));
3466 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3467 emitcode("","%05d$:",(lbl->key+100));
3470 lbl = newiTempLabel(NULL);
3471 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3472 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3473 emitcode("","%05d$:",(lbl->key+100));
3474 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3475 lbl = newiTempLabel(NULL);
3476 emitcode("jc","%05d$",(lbl->key+100));
3477 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3478 emitcode("","%05d$:",(lbl->key+100));
3480 aopPut(AOP(result),"a",1);
3483 emitcode("rlc","a");
3484 emitcode("subb","a,acc");
3491 aopPut(AOP(result),"a",offset++);
3495 /*-----------------------------------------------------------------*/
3496 /* genMult - generates code for multiplication */
3497 /*-----------------------------------------------------------------*/
3498 static void genMult (iCode *ic)
3500 operand *left = IC_LEFT(ic);
3501 operand *right = IC_RIGHT(ic);
3502 operand *result= IC_RESULT(ic);
3504 D(emitcode(";", "genMult "););
3506 /* assign the amsops */
3509 aopOp (left,ic,FALSE, FALSE);
3510 aopOp (right,ic,FALSE, TRUE);
3511 aopOp (result,ic,TRUE, FALSE);
3514 /* special cases first */
3516 if (AOP_TYPE(left) == AOP_CRY &&
3517 AOP_TYPE(right)== AOP_CRY) {
3518 genMultbits(left,right,result);
3522 /* if both are of size == 1 */
3523 if (AOP_SIZE(left) == 1 &&
3524 AOP_SIZE(right) == 1 ) {
3525 genMultOneByte(left,right,result);
3529 /* should have been converted to function call */
3533 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3534 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3535 freeAsmop(result,NULL,ic,TRUE);
3538 /*-----------------------------------------------------------------*/
3539 /* genDivbits :- division of bits */
3540 /*-----------------------------------------------------------------*/
3541 static void genDivbits (operand *left,
3548 /* the result must be bit */
3549 LOAD_AB_FOR_DIV(left, right, l);
3550 emitcode("div","ab");
3551 emitcode("rrc","a");
3552 aopPut(AOP(result),"c",0);
3555 /*-----------------------------------------------------------------*/
3556 /* genDivOneByte : 8 bit division */
3557 /*-----------------------------------------------------------------*/
3558 static void genDivOneByte (operand *left,
3562 link *opetype = operandType(result);
3567 size = AOP_SIZE(result) - 1;
3569 /* signed or unsigned */
3570 if (SPEC_USIGN(opetype)) {
3571 /* unsigned is easy */
3572 LOAD_AB_FOR_DIV(left, right, l);
3573 emitcode("div","ab");
3574 aopPut(AOP(result),"a",0);
3576 aopPut(AOP(result),zero,offset++);
3580 /* signed is a little bit more difficult */
3582 /* save the signs of the operands */
3583 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3585 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3586 emitcode("push","acc"); /* save it on the stack */
3588 /* now sign adjust for both left & right */
3589 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3591 lbl = newiTempLabel(NULL);
3592 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3593 emitcode("cpl","a");
3594 emitcode("inc","a");
3595 emitcode("","%05d$:",(lbl->key+100));
3596 emitcode("mov","b,a");
3598 /* sign adjust left side */
3599 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3602 lbl = newiTempLabel(NULL);
3603 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3604 emitcode("cpl","a");
3605 emitcode("inc","a");
3606 emitcode("","%05d$:",(lbl->key+100));
3608 /* now the division */
3609 emitcode("nop", "; workaround for DS80C390 div bug.");
3610 emitcode("div","ab");
3611 /* we are interested in the lower order
3613 emitcode("mov","b,a");
3614 lbl = newiTempLabel(NULL);
3615 emitcode("pop","acc");
3616 /* if there was an over flow we don't
3617 adjust the sign of the result */
3618 emitcode("jb","ov,%05d$",(lbl->key+100));
3619 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3621 emitcode("clr","a");
3622 emitcode("subb","a,b");
3623 emitcode("mov","b,a");
3624 emitcode("","%05d$:",(lbl->key+100));
3626 /* now we are done */
3627 aopPut(AOP(result),"b",0);
3629 emitcode("mov","c,b.7");
3630 emitcode("subb","a,acc");
3633 aopPut(AOP(result),"a",offset++);
3637 /*-----------------------------------------------------------------*/
3638 /* genDiv - generates code for division */
3639 /*-----------------------------------------------------------------*/
3640 static void genDiv (iCode *ic)
3642 operand *left = IC_LEFT(ic);
3643 operand *right = IC_RIGHT(ic);
3644 operand *result= IC_RESULT(ic);
3646 D(emitcode(";", "genDiv "););
3648 /* assign the amsops */
3651 aopOp (left,ic,FALSE, FALSE);
3652 aopOp (right,ic,FALSE, TRUE);
3653 aopOp (result,ic,TRUE, FALSE);
3656 /* special cases first */
3658 if (AOP_TYPE(left) == AOP_CRY &&
3659 AOP_TYPE(right)== AOP_CRY) {
3660 genDivbits(left,right,result);
3664 /* if both are of size == 1 */
3665 if (AOP_SIZE(left) == 1 &&
3666 AOP_SIZE(right) == 1 ) {
3667 genDivOneByte(left,right,result);
3671 /* should have been converted to function call */
3674 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3675 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3676 freeAsmop(result,NULL,ic,TRUE);
3679 /*-----------------------------------------------------------------*/
3680 /* genModbits :- modulus of bits */
3681 /*-----------------------------------------------------------------*/
3682 static void genModbits (operand *left,
3689 /* the result must be bit */
3690 LOAD_AB_FOR_DIV(left, right, l);
3691 emitcode("div","ab");
3692 emitcode("mov","a,b");
3693 emitcode("rrc","a");
3694 aopPut(AOP(result),"c",0);
3697 /*-----------------------------------------------------------------*/
3698 /* genModOneByte : 8 bit modulus */
3699 /*-----------------------------------------------------------------*/
3700 static void genModOneByte (operand *left,
3704 link *opetype = operandType(result);
3708 /* signed or unsigned */
3709 if (SPEC_USIGN(opetype)) {
3710 /* unsigned is easy */
3711 LOAD_AB_FOR_DIV(left, right, l);
3712 emitcode("div","ab");
3713 aopPut(AOP(result),"b",0);
3717 /* signed is a little bit more difficult */
3719 /* save the signs of the operands */
3720 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3723 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3724 emitcode("push","acc"); /* save it on the stack */
3726 /* now sign adjust for both left & right */
3727 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3730 lbl = newiTempLabel(NULL);
3731 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3732 emitcode("cpl","a");
3733 emitcode("inc","a");
3734 emitcode("","%05d$:",(lbl->key+100));
3735 emitcode("mov","b,a");
3737 /* sign adjust left side */
3738 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3741 lbl = newiTempLabel(NULL);
3742 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3743 emitcode("cpl","a");
3744 emitcode("inc","a");
3745 emitcode("","%05d$:",(lbl->key+100));
3747 /* now the multiplication */
3748 emitcode("nop", "; workaround for DS80C390 div bug.");
3749 emitcode("div","ab");
3750 /* we are interested in the lower order
3752 lbl = newiTempLabel(NULL);
3753 emitcode("pop","acc");
3754 /* if there was an over flow we don't
3755 adjust the sign of the result */
3756 emitcode("jb","ov,%05d$",(lbl->key+100));
3757 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3759 emitcode("clr","a");
3760 emitcode("subb","a,b");
3761 emitcode("mov","b,a");
3762 emitcode("","%05d$:",(lbl->key+100));
3764 /* now we are done */
3765 aopPut(AOP(result),"b",0);
3769 /*-----------------------------------------------------------------*/
3770 /* genMod - generates code for division */
3771 /*-----------------------------------------------------------------*/
3772 static void genMod (iCode *ic)
3774 operand *left = IC_LEFT(ic);
3775 operand *right = IC_RIGHT(ic);
3776 operand *result= IC_RESULT(ic);
3778 D(emitcode(";", "genMod "););
3780 /* assign the amsops */
3783 aopOp (left,ic,FALSE, FALSE);
3784 aopOp (right,ic,FALSE, TRUE);
3785 aopOp (result,ic,TRUE, FALSE);
3788 /* special cases first */
3790 if (AOP_TYPE(left) == AOP_CRY &&
3791 AOP_TYPE(right)== AOP_CRY) {
3792 genModbits(left,right,result);
3796 /* if both are of size == 1 */
3797 if (AOP_SIZE(left) == 1 &&
3798 AOP_SIZE(right) == 1 ) {
3799 genModOneByte(left,right,result);
3803 /* should have been converted to function call */
3807 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3808 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3809 freeAsmop(result,NULL,ic,TRUE);
3812 /*-----------------------------------------------------------------*/
3813 /* genIfxJump :- will create a jump depending on the ifx */
3814 /*-----------------------------------------------------------------*/
3815 static void genIfxJump (iCode *ic, char *jval)
3818 symbol *tlbl = newiTempLabel(NULL);
3821 D(emitcode(";", "genIfxJump "););
3823 /* if true label then we jump if condition
3825 if ( IC_TRUE(ic) ) {
3827 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3828 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3831 /* false label is present */
3832 jlbl = IC_FALSE(ic) ;
3833 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3834 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3836 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3837 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3839 emitcode(inst,"%05d$",tlbl->key+100);
3840 emitcode("ljmp","%05d$",jlbl->key+100);
3841 emitcode("","%05d$:",tlbl->key+100);
3843 /* mark the icode as generated */
3847 /*-----------------------------------------------------------------*/
3848 /* genCmp :- greater or less than comparison */
3849 /*-----------------------------------------------------------------*/
3850 static void genCmp (operand *left,operand *right,
3851 operand *result, iCode *ifx, int sign)
3853 int size, offset = 0 ;
3854 unsigned long lit = 0L;
3855 bool swappedOps = FALSE;
3857 D(emitcode(";", "genCmp"););
3860 /* If left if lit and right isn't, swap 'em. */
3861 if (AOP_TYPE(left) == AOP_LIT &&
3862 AOP_TYPE(right) != AOP_LIT)
3864 operand *tmp = left;
3867 D(emitcode(";", "kevin literal hack"););
3868 swappedOps = !swappedOps;
3871 if (AOP_NEEDSACC(right))
3873 if (AOP_NEEDSACC(left))
3875 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3876 "both CMP operands need ACC!");
3881 operand *tmp = left;
3884 D(emitcode(";", "kevin ACC hack"););
3885 swappedOps = !swappedOps;
3890 /* if left & right are bit variables */
3891 if (AOP_TYPE(left) == AOP_CRY &&
3892 AOP_TYPE(right) == AOP_CRY ) {
3893 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3894 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3896 /* subtract right from left if at the
3897 end the carry flag is set then we know that
3898 left is greater than right */
3899 size = max(AOP_SIZE(left),AOP_SIZE(right));
3901 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3902 if((size == 1) && !sign &&
3903 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3904 symbol *lbl = newiTempLabel(NULL);
3905 emitcode("cjne","%s,%s,%05d$",
3906 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3907 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3909 emitcode("","%05d$:",lbl->key+100);
3911 if(AOP_TYPE(right) == AOP_LIT){
3912 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3913 /* optimize if(x < 0) or if(x >= 0) */
3919 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3920 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3921 genIfxJump (ifx,"acc.7");
3925 emitcode("rlc","a");
3933 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3934 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3935 emitcode(";", "genCmp #2");
3936 if (sign && (size == 0))
3938 emitcode(";", "genCmp #3");
3939 emitcode("xrl","a,#0x80");
3940 if (AOP_TYPE(right) == AOP_LIT)
3942 unsigned long lit = (unsigned long)
3943 floatFromVal(AOP(right)->aopu.aop_lit);
3944 emitcode(";", "genCmp #3.1");
3945 emitcode("subb","a,#0x%02x",
3946 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3950 emitcode(";", "genCmp #3.2");
3951 if (AOP_NEEDSACC(right))
3953 emitcode("push", "acc");
3955 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3956 FALSE,FALSE,FALSE));
3957 emitcode("xrl","b,#0x80");
3958 if (AOP_NEEDSACC(right))
3960 emitcode("pop", "acc");
3962 emitcode("subb","a,b");
3969 emitcode(";", "genCmp #4");
3970 if (AOP_NEEDSACC(right))
3973 emitcode(";", "genCmp #4.1");
3974 emitcode("xch", "a, b");
3975 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3976 emitcode("xch", "a, b");
3981 emitcode(";", "genCmp #4.2");
3982 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
3985 emitcode("subb","a,%s",s);
3994 D(emitcode(";","kevHack: flip carry."););
3995 emitcode("cpl", "c");
3998 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4001 /* if the result is used in the next
4002 ifx conditional branch then generate
4003 code a little differently */
4005 genIfxJump (ifx,"c");
4008 /* leave the result in acc */
4012 /*-----------------------------------------------------------------*/
4013 /* genCmpGt :- greater than comparison */
4014 /*-----------------------------------------------------------------*/
4015 static void genCmpGt (iCode *ic, iCode *ifx)
4017 operand *left, *right, *result;
4018 link *letype , *retype;
4021 D(emitcode(";", "genCmpGt "););
4024 right= IC_RIGHT(ic);
4025 result = IC_RESULT(ic);
4027 letype = getSpec(operandType(left));
4028 retype =getSpec(operandType(right));
4029 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4030 /* assign the amsops */
4033 aopOp (left,ic,FALSE, TRUE);
4034 aopOp (right,ic,FALSE, FALSE);
4035 aopOp (result,ic,TRUE, FALSE);
4038 genCmp(right, left, result, ifx, sign);
4040 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4041 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4042 freeAsmop(result,NULL,ic,TRUE);
4045 /*-----------------------------------------------------------------*/
4046 /* genCmpLt - less than comparisons */
4047 /*-----------------------------------------------------------------*/
4048 static void genCmpLt (iCode *ic, iCode *ifx)
4050 operand *left, *right, *result;
4051 link *letype , *retype;
4054 D(emitcode(";", "genCmpLt "););
4057 right= IC_RIGHT(ic);
4058 result = IC_RESULT(ic);
4060 letype = getSpec(operandType(left));
4061 retype =getSpec(operandType(right));
4062 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4064 /* assign the amsops */
4067 aopOp (left,ic,FALSE, FALSE);
4068 aopOp (right,ic,FALSE, TRUE);
4069 aopOp (result,ic,TRUE, FALSE);
4072 genCmp(left, right, result, ifx, sign);
4074 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4075 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4076 freeAsmop(result,NULL,ic,TRUE);
4079 /*-----------------------------------------------------------------*/
4080 /* gencjneshort - compare and jump if not equal */
4081 /*-----------------------------------------------------------------*/
4082 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4084 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4086 unsigned long lit = 0L;
4088 D(emitcode(";", "gencjneshort"););
4090 /* if the left side is a literal or
4091 if the right is in a pointer register and left
4093 if ((AOP_TYPE(left) == AOP_LIT) ||
4094 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4100 if(AOP_TYPE(right) == AOP_LIT)
4101 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4103 if (opIsGptr(left) || opIsGptr(right))
4105 /* We are comparing a generic pointer to something.
4106 * Exclude the generic type byte from the comparison.
4109 D(emitcode(";", "cjneshort: generic ptr special case.");)
4113 /* if the right side is a literal then anything goes */
4114 if (AOP_TYPE(right) == AOP_LIT &&
4115 AOP_TYPE(left) != AOP_DIR ) {
4117 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4119 emitcode("cjne","a,%s,%05d$",
4120 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4126 /* if the right side is in a register or in direct space or
4127 if the left is a pointer register & right is not */
4128 else if (AOP_TYPE(right) == AOP_REG ||
4129 AOP_TYPE(right) == AOP_DIR ||
4130 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4131 (IS_AOP_PREG(left) && !IS_AOP_PREG(right)))
4135 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4136 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4137 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4138 emitcode("jnz","%05d$",lbl->key+100);
4140 emitcode("cjne","a,%s,%05d$",
4141 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4146 /* right is a pointer reg need both a & b */
4148 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4150 emitcode("mov","b,%s",l);
4151 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4152 emitcode("cjne","a,b,%05d$",lbl->key+100);
4158 /*-----------------------------------------------------------------*/
4159 /* gencjne - compare and jump if not equal */
4160 /*-----------------------------------------------------------------*/
4161 static void gencjne(operand *left, operand *right, symbol *lbl)
4163 symbol *tlbl = newiTempLabel(NULL);
4165 D(emitcode(";", "gencjne"););
4167 gencjneshort(left, right, lbl);
4169 emitcode("mov","a,%s",one);
4170 emitcode("sjmp","%05d$",tlbl->key+100);
4171 emitcode("","%05d$:",lbl->key+100);
4172 emitcode("clr","a");
4173 emitcode("","%05d$:",tlbl->key+100);
4176 /*-----------------------------------------------------------------*/
4177 /* genCmpEq - generates code for equal to */
4178 /*-----------------------------------------------------------------*/
4179 static void genCmpEq (iCode *ic, iCode *ifx)
4181 operand *left, *right, *result;
4183 D(emitcode(";", "genCmpEq "););
4188 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4189 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4190 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4193 /* if literal, literal on the right or
4194 if the right is in a pointer register and left
4196 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4197 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4198 operand *t = IC_RIGHT(ic);
4199 IC_RIGHT(ic) = IC_LEFT(ic);
4203 if(ifx && !AOP_SIZE(result)){
4205 /* if they are both bit variables */
4206 if (AOP_TYPE(left) == AOP_CRY &&
4207 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4208 if(AOP_TYPE(right) == AOP_LIT){
4209 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4211 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4212 emitcode("cpl","c");
4213 } else if(lit == 1L) {
4214 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4216 emitcode("clr","c");
4218 /* AOP_TYPE(right) == AOP_CRY */
4220 symbol *lbl = newiTempLabel(NULL);
4221 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4222 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4223 emitcode("cpl","c");
4224 emitcode("","%05d$:",(lbl->key+100));
4226 /* if true label then we jump if condition
4228 tlbl = newiTempLabel(NULL);
4229 if ( IC_TRUE(ifx) ) {
4230 emitcode("jnc","%05d$",tlbl->key+100);
4231 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4233 emitcode("jc","%05d$",tlbl->key+100);
4234 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4236 emitcode("","%05d$:",tlbl->key+100);
4238 tlbl = newiTempLabel(NULL);
4239 gencjneshort(left, right, tlbl);
4240 if ( IC_TRUE(ifx) ) {
4241 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4242 emitcode("","%05d$:",tlbl->key+100);
4244 symbol *lbl = newiTempLabel(NULL);
4245 emitcode("sjmp","%05d$",lbl->key+100);
4246 emitcode("","%05d$:",tlbl->key+100);
4247 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4248 emitcode("","%05d$:",lbl->key+100);
4251 /* mark the icode as generated */
4256 /* if they are both bit variables */
4257 if (AOP_TYPE(left) == AOP_CRY &&
4258 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4259 if(AOP_TYPE(right) == AOP_LIT){
4260 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4262 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4263 emitcode("cpl","c");
4264 } else if(lit == 1L) {
4265 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4267 emitcode("clr","c");
4269 /* AOP_TYPE(right) == AOP_CRY */
4271 symbol *lbl = newiTempLabel(NULL);
4272 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4273 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4274 emitcode("cpl","c");
4275 emitcode("","%05d$:",(lbl->key+100));
4278 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4283 genIfxJump (ifx,"c");
4286 /* if the result is used in an arithmetic operation
4287 then put the result in place */
4290 gencjne(left,right,newiTempLabel(NULL));
4291 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4292 aopPut(AOP(result),"a",0);
4296 genIfxJump (ifx,"a");
4299 /* if the result is used in an arithmetic operation
4300 then put the result in place */
4301 if (AOP_TYPE(result) != AOP_CRY)
4303 /* leave the result in acc */
4307 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4308 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4309 freeAsmop(result,NULL,ic,TRUE);
4312 /*-----------------------------------------------------------------*/
4313 /* ifxForOp - returns the icode containing the ifx for operand */
4314 /*-----------------------------------------------------------------*/
4315 static iCode *ifxForOp ( operand *op, iCode *ic )
4317 /* if true symbol then needs to be assigned */
4318 if (IS_TRUE_SYMOP(op))
4321 /* if this has register type condition and
4322 the next instruction is ifx with the same operand
4323 and live to of the operand is upto the ifx only then */
4325 ic->next->op == IFX &&
4326 IC_COND(ic->next)->key == op->key &&
4327 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4332 /*-----------------------------------------------------------------*/
4333 /* genAndOp - for && operation */
4334 /*-----------------------------------------------------------------*/
4335 static void genAndOp (iCode *ic)
4337 operand *left,*right, *result;
4340 D(emitcode(";", "genAndOp "););
4342 /* note here that && operations that are in an
4343 if statement are taken away by backPatchLabels
4344 only those used in arthmetic operations remain */
4348 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4349 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4350 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4353 /* if both are bit variables */
4354 if (AOP_TYPE(left) == AOP_CRY &&
4355 AOP_TYPE(right) == AOP_CRY ) {
4356 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4357 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4360 tlbl = newiTempLabel(NULL);
4362 emitcode("jz","%05d$",tlbl->key+100);
4364 emitcode("","%05d$:",tlbl->key+100);
4368 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4369 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4370 freeAsmop(result,NULL,ic,TRUE);
4374 /*-----------------------------------------------------------------*/
4375 /* genOrOp - for || operation */
4376 /*-----------------------------------------------------------------*/
4377 static void genOrOp (iCode *ic)
4379 operand *left,*right, *result;
4382 D(emitcode(";", "genOrOp "););
4384 /* note here that || operations that are in an
4385 if statement are taken away by backPatchLabels
4386 only those used in arthmetic operations remain */
4390 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
4391 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
4392 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
4395 /* if both are bit variables */
4396 if (AOP_TYPE(left) == AOP_CRY &&
4397 AOP_TYPE(right) == AOP_CRY ) {
4398 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4399 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4402 tlbl = newiTempLabel(NULL);
4404 emitcode("jnz","%05d$",tlbl->key+100);
4406 emitcode("","%05d$:",tlbl->key+100);
4410 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4411 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4412 freeAsmop(result,NULL,ic,TRUE);
4415 /*-----------------------------------------------------------------*/
4416 /* isLiteralBit - test if lit == 2^n */
4417 /*-----------------------------------------------------------------*/
4418 static int isLiteralBit(unsigned long lit)
4420 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4421 0x100L,0x200L,0x400L,0x800L,
4422 0x1000L,0x2000L,0x4000L,0x8000L,
4423 0x10000L,0x20000L,0x40000L,0x80000L,
4424 0x100000L,0x200000L,0x400000L,0x800000L,
4425 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4426 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4429 for(idx = 0; idx < 32; idx++)
4435 /*-----------------------------------------------------------------*/
4436 /* continueIfTrue - */
4437 /*-----------------------------------------------------------------*/
4438 static void continueIfTrue (iCode *ic)
4441 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4445 /*-----------------------------------------------------------------*/
4447 /*-----------------------------------------------------------------*/
4448 static void jumpIfTrue (iCode *ic)
4451 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4455 /*-----------------------------------------------------------------*/
4456 /* jmpTrueOrFalse - */
4457 /*-----------------------------------------------------------------*/
4458 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4460 // ugly but optimized by peephole
4462 symbol *nlbl = newiTempLabel(NULL);
4463 emitcode("sjmp","%05d$",nlbl->key+100);
4464 emitcode("","%05d$:",tlbl->key+100);
4465 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4466 emitcode("","%05d$:",nlbl->key+100);
4469 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4470 emitcode("","%05d$:",tlbl->key+100);
4475 /*-----------------------------------------------------------------*/
4476 /* genAnd - code for and */
4477 /*-----------------------------------------------------------------*/
4478 static void genAnd (iCode *ic, iCode *ifx)
4480 operand *left, *right, *result;
4482 unsigned long lit = 0L;
4486 D(emitcode(";", "genAnd "););
4491 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4492 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4493 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4497 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4499 AOP_TYPE(left), AOP_TYPE(right));
4500 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4502 AOP_SIZE(left), AOP_SIZE(right));
4505 /* if left is a literal & right is not then exchange them */
4506 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4507 AOP_NEEDSACC(left)) {
4508 operand *tmp = right ;
4513 /* if result = right then exchange them */
4514 if(sameRegs(AOP(result),AOP(right))){
4515 operand *tmp = right ;
4520 /* if right is bit then exchange them */
4521 if (AOP_TYPE(right) == AOP_CRY &&
4522 AOP_TYPE(left) != AOP_CRY){
4523 operand *tmp = right ;
4527 if(AOP_TYPE(right) == AOP_LIT)
4528 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4530 size = AOP_SIZE(result);
4533 // result = bit & yy;
4534 if (AOP_TYPE(left) == AOP_CRY){
4535 // c = bit & literal;
4536 if(AOP_TYPE(right) == AOP_LIT){
4538 if(size && sameRegs(AOP(result),AOP(left)))
4541 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4544 if(size && (AOP_TYPE(result) == AOP_CRY)){
4545 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4548 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4552 emitcode("clr","c");
4555 if (AOP_TYPE(right) == AOP_CRY){
4557 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4558 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4561 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4563 emitcode("rrc","a");
4564 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4572 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4573 genIfxJump(ifx, "c");
4577 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4578 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4579 if((AOP_TYPE(right) == AOP_LIT) &&
4580 (AOP_TYPE(result) == AOP_CRY) &&
4581 (AOP_TYPE(left) != AOP_CRY)){
4582 int posbit = isLiteralBit(lit);
4586 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4589 emitcode("mov","c,acc.%d",posbit&0x07);
4593 sprintf(buffer,"acc.%d",posbit&0x07);
4594 genIfxJump(ifx, buffer);
4599 symbol *tlbl = newiTempLabel(NULL);
4600 int sizel = AOP_SIZE(left);
4602 emitcode("setb","c");
4604 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4605 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4607 if((posbit = isLiteralBit(bytelit)) != 0)
4608 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4610 if(bytelit != 0x0FFL)
4611 emitcode("anl","a,%s",
4612 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4613 emitcode("jnz","%05d$",tlbl->key+100);
4618 // bit = left & literal
4620 emitcode("clr","c");
4621 emitcode("","%05d$:",tlbl->key+100);
4623 // if(left & literal)
4626 jmpTrueOrFalse(ifx, tlbl);
4634 /* if left is same as result */
4635 if(sameRegs(AOP(result),AOP(left))){
4636 for(;size--; offset++) {
4637 if(AOP_TYPE(right) == AOP_LIT){
4638 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4642 aopPut(AOP(result),zero,offset);
4644 if (IS_AOP_PREG(result)) {
4645 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4646 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4647 aopPut(AOP(result),"a",offset);
4649 emitcode("anl","%s,%s",
4650 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4651 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4653 if (AOP_TYPE(left) == AOP_ACC)
4654 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4656 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4657 if (IS_AOP_PREG(result)) {
4658 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4659 aopPut(AOP(result),"a",offset);
4662 emitcode("anl","%s,a",
4663 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4668 // left & result in different registers
4669 if(AOP_TYPE(result) == AOP_CRY){
4671 // if(size), result in bit
4672 // if(!size && ifx), conditional oper: if(left & right)
4673 symbol *tlbl = newiTempLabel(NULL);
4674 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4676 emitcode("setb","c");
4678 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4679 emitcode("anl","a,%s",
4680 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4681 emitcode("jnz","%05d$",tlbl->key+100);
4686 emitcode("","%05d$:",tlbl->key+100);
4689 jmpTrueOrFalse(ifx, tlbl);
4691 for(;(size--);offset++) {
4693 // result = left & right
4694 if(AOP_TYPE(right) == AOP_LIT){
4695 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4697 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4700 } else if(bytelit == 0){
4701 aopPut(AOP(result),zero,offset);
4705 // faster than result <- left, anl result,right
4706 // and better if result is SFR
4707 if (AOP_TYPE(left) == AOP_ACC)
4708 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4710 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4711 emitcode("anl","a,%s",
4712 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4714 aopPut(AOP(result),"a",offset);
4720 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4721 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4722 freeAsmop(result,NULL,ic,TRUE);
4725 /*-----------------------------------------------------------------*/
4726 /* genOr - code for or */
4727 /*-----------------------------------------------------------------*/
4728 static void genOr (iCode *ic, iCode *ifx)
4730 operand *left, *right, *result;
4732 unsigned long lit = 0L;
4734 D(emitcode(";", "genOr "););
4739 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4740 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4741 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4745 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4747 AOP_TYPE(left), AOP_TYPE(right));
4748 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4750 AOP_SIZE(left), AOP_SIZE(right));
4753 /* if left is a literal & right is not then exchange them */
4754 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4755 AOP_NEEDSACC(left)) {
4756 operand *tmp = right ;
4761 /* if result = right then exchange them */
4762 if(sameRegs(AOP(result),AOP(right))){
4763 operand *tmp = right ;
4768 /* if right is bit then exchange them */
4769 if (AOP_TYPE(right) == AOP_CRY &&
4770 AOP_TYPE(left) != AOP_CRY){
4771 operand *tmp = right ;
4775 if(AOP_TYPE(right) == AOP_LIT)
4776 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4778 size = AOP_SIZE(result);
4782 if (AOP_TYPE(left) == AOP_CRY){
4783 if(AOP_TYPE(right) == AOP_LIT){
4784 // c = bit & literal;
4786 // lit != 0 => result = 1
4787 if(AOP_TYPE(result) == AOP_CRY){
4789 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4791 continueIfTrue(ifx);
4794 emitcode("setb","c");
4796 // lit == 0 => result = left
4797 if(size && sameRegs(AOP(result),AOP(left)))
4799 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4802 if (AOP_TYPE(right) == AOP_CRY){
4804 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4805 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4809 symbol *tlbl = newiTempLabel(NULL);
4810 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4811 emitcode("setb","c");
4812 emitcode("jb","%s,%05d$",
4813 AOP(left)->aopu.aop_dir,tlbl->key+100);
4815 emitcode("jnz","%05d$",tlbl->key+100);
4816 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4817 jmpTrueOrFalse(ifx, tlbl);
4821 emitcode("","%05d$:",tlbl->key+100);
4830 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4831 genIfxJump(ifx, "c");
4835 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4836 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4837 if((AOP_TYPE(right) == AOP_LIT) &&
4838 (AOP_TYPE(result) == AOP_CRY) &&
4839 (AOP_TYPE(left) != AOP_CRY)){
4843 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4845 continueIfTrue(ifx);
4848 // lit = 0, result = boolean(left)
4850 emitcode("setb","c");
4853 symbol *tlbl = newiTempLabel(NULL);
4854 emitcode("jnz","%05d$",tlbl->key+100);
4856 emitcode("","%05d$:",tlbl->key+100);
4858 genIfxJump (ifx,"a");
4866 /* if left is same as result */
4867 if(sameRegs(AOP(result),AOP(left))){
4868 for(;size--; offset++) {
4869 if(AOP_TYPE(right) == AOP_LIT){
4870 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4873 if (IS_AOP_PREG(left)) {
4874 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4875 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4876 aopPut(AOP(result),"a",offset);
4878 emitcode("orl","%s,%s",
4879 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4880 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4882 if (AOP_TYPE(left) == AOP_ACC)
4883 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4885 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4886 if (IS_AOP_PREG(left)) {
4887 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4888 aopPut(AOP(result),"a",offset);
4890 emitcode("orl","%s,a",
4891 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4896 // left & result in different registers
4897 if(AOP_TYPE(result) == AOP_CRY){
4899 // if(size), result in bit
4900 // if(!size && ifx), conditional oper: if(left | right)
4901 symbol *tlbl = newiTempLabel(NULL);
4902 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4904 emitcode("setb","c");
4906 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4907 emitcode("orl","a,%s",
4908 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4909 emitcode("jnz","%05d$",tlbl->key+100);
4914 emitcode("","%05d$:",tlbl->key+100);
4917 jmpTrueOrFalse(ifx, tlbl);
4918 } else for(;(size--);offset++){
4920 // result = left & right
4921 if(AOP_TYPE(right) == AOP_LIT){
4922 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4924 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4929 // faster than result <- left, anl result,right
4930 // and better if result is SFR
4931 if (AOP_TYPE(left) == AOP_ACC)
4932 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4934 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4935 emitcode("orl","a,%s",
4936 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4938 aopPut(AOP(result),"a",offset);
4943 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4944 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4945 freeAsmop(result,NULL,ic,TRUE);
4948 /*-----------------------------------------------------------------*/
4949 /* genXor - code for xclusive or */
4950 /*-----------------------------------------------------------------*/
4951 static void genXor (iCode *ic, iCode *ifx)
4953 operand *left, *right, *result;
4955 unsigned long lit = 0L;
4957 D(emitcode(";", "genXor "););
4962 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
4963 aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
4964 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
4968 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4970 AOP_TYPE(left), AOP_TYPE(right));
4971 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4973 AOP_SIZE(left), AOP_SIZE(right));
4976 /* if left is a literal & right is not ||
4977 if left needs acc & right does not */
4978 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4979 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4980 operand *tmp = right ;
4985 /* if result = right then exchange them */
4986 if(sameRegs(AOP(result),AOP(right))){
4987 operand *tmp = right ;
4992 /* if right is bit then exchange them */
4993 if (AOP_TYPE(right) == AOP_CRY &&
4994 AOP_TYPE(left) != AOP_CRY){
4995 operand *tmp = right ;
4999 if(AOP_TYPE(right) == AOP_LIT)
5000 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5002 size = AOP_SIZE(result);
5006 if (AOP_TYPE(left) == AOP_CRY){
5007 if(AOP_TYPE(right) == AOP_LIT){
5008 // c = bit & literal;
5010 // lit>>1 != 0 => result = 1
5011 if(AOP_TYPE(result) == AOP_CRY){
5013 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5015 continueIfTrue(ifx);
5018 emitcode("setb","c");
5022 // lit == 0, result = left
5023 if(size && sameRegs(AOP(result),AOP(left)))
5025 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5027 // lit == 1, result = not(left)
5028 if(size && sameRegs(AOP(result),AOP(left))){
5029 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5032 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5033 emitcode("cpl","c");
5040 symbol *tlbl = newiTempLabel(NULL);
5041 if (AOP_TYPE(right) == AOP_CRY){
5043 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5046 int sizer = AOP_SIZE(right);
5048 // if val>>1 != 0, result = 1
5049 emitcode("setb","c");
5051 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5053 // test the msb of the lsb
5054 emitcode("anl","a,#0xfe");
5055 emitcode("jnz","%05d$",tlbl->key+100);
5059 emitcode("rrc","a");
5061 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5062 emitcode("cpl","c");
5063 emitcode("","%05d$:",(tlbl->key+100));
5070 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5071 genIfxJump(ifx, "c");
5075 if(sameRegs(AOP(result),AOP(left))){
5076 /* if left is same as result */
5077 for(;size--; offset++) {
5078 if(AOP_TYPE(right) == AOP_LIT){
5079 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5082 if (IS_AOP_PREG(left)) {
5083 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5084 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5085 aopPut(AOP(result),"a",offset);
5087 emitcode("xrl","%s,%s",
5088 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5089 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5091 if (AOP_TYPE(left) == AOP_ACC)
5092 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5094 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5095 if (IS_AOP_PREG(left)) {
5096 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5097 aopPut(AOP(result),"a",offset);
5099 emitcode("xrl","%s,a",
5100 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5105 // left & result in different registers
5106 if(AOP_TYPE(result) == AOP_CRY){
5108 // if(size), result in bit
5109 // if(!size && ifx), conditional oper: if(left ^ right)
5110 symbol *tlbl = newiTempLabel(NULL);
5111 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5113 emitcode("setb","c");
5115 if((AOP_TYPE(right) == AOP_LIT) &&
5116 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5117 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5119 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5120 emitcode("xrl","a,%s",
5121 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5123 emitcode("jnz","%05d$",tlbl->key+100);
5128 emitcode("","%05d$:",tlbl->key+100);
5131 jmpTrueOrFalse(ifx, tlbl);
5132 } else for(;(size--);offset++){
5134 // result = left & right
5135 if(AOP_TYPE(right) == AOP_LIT){
5136 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
5138 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5143 // faster than result <- left, anl result,right
5144 // and better if result is SFR
5145 if (AOP_TYPE(left) == AOP_ACC)
5146 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5148 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5149 emitcode("xrl","a,%s",
5150 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5152 aopPut(AOP(result),"a",offset);
5157 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5158 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5159 freeAsmop(result,NULL,ic,TRUE);
5162 /*-----------------------------------------------------------------*/
5163 /* genInline - write the inline code out */
5164 /*-----------------------------------------------------------------*/
5165 static void genInline (iCode *ic)
5167 char buffer[MAX_INLINEASM];
5171 D(emitcode(";", "genInline "););
5173 _G.inLine += (!options.asmpeep);
5174 strcpy(buffer,IC_INLINE(ic));
5176 /* emit each line as a code */
5195 /* emitcode("",buffer); */
5196 _G.inLine -= (!options.asmpeep);
5199 /*-----------------------------------------------------------------*/
5200 /* genRRC - rotate right with carry */
5201 /*-----------------------------------------------------------------*/
5202 static void genRRC (iCode *ic)
5204 operand *left , *result ;
5205 int size, offset = 0;
5208 D(emitcode(";", "genRRC "););
5210 /* rotate right with carry */
5212 result=IC_RESULT(ic);
5213 aopOp (left,ic,FALSE, FALSE);
5214 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5216 /* move it to the result */
5217 size = AOP_SIZE(result);
5221 _startLazyDPSEvaluation();
5223 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5225 emitcode("rrc","a");
5226 if (AOP_SIZE(result) > 1)
5227 aopPut(AOP(result),"a",offset--);
5229 _endLazyDPSEvaluation();
5231 /* now we need to put the carry into the
5232 highest order byte of the result */
5233 if (AOP_SIZE(result) > 1) {
5234 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5237 emitcode("mov","acc.7,c");
5238 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5239 freeAsmop(left,NULL,ic,TRUE);
5240 freeAsmop(result,NULL,ic,TRUE);
5243 /*-----------------------------------------------------------------*/
5244 /* genRLC - generate code for rotate left with carry */
5245 /*-----------------------------------------------------------------*/
5246 static void genRLC (iCode *ic)
5248 operand *left , *result ;
5249 int size, offset = 0;
5252 D(emitcode(";", "genRLC "););
5254 /* rotate right with carry */
5256 result=IC_RESULT(ic);
5257 aopOp (left,ic,FALSE, FALSE);
5258 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5260 /* move it to the result */
5261 size = AOP_SIZE(result);
5264 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5266 emitcode("add","a,acc");
5267 if (AOP_SIZE(result) > 1)
5269 aopPut(AOP(result),"a",offset++);
5272 _startLazyDPSEvaluation();
5274 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5276 emitcode("rlc","a");
5277 if (AOP_SIZE(result) > 1)
5278 aopPut(AOP(result),"a",offset++);
5280 _endLazyDPSEvaluation();
5282 /* now we need to put the carry into the
5283 highest order byte of the result */
5284 if (AOP_SIZE(result) > 1) {
5285 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5288 emitcode("mov","acc.0,c");
5289 aopPut(AOP(result),"a",0);
5290 freeAsmop(left,NULL,ic,TRUE);
5291 freeAsmop(result,NULL,ic,TRUE);
5294 /*-----------------------------------------------------------------*/
5295 /* genGetHbit - generates code get highest order bit */
5296 /*-----------------------------------------------------------------*/
5297 static void genGetHbit (iCode *ic)
5299 operand *left, *result;
5301 result=IC_RESULT(ic);
5302 aopOp (left,ic,FALSE, FALSE);
5303 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5305 D(emitcode(";", "genGetHbit "););
5307 /* get the highest order byte into a */
5308 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5309 if(AOP_TYPE(result) == AOP_CRY){
5310 emitcode("rlc","a");
5315 emitcode("anl","a,#0x01");
5320 freeAsmop(left,NULL,ic,TRUE);
5321 freeAsmop(result,NULL,ic,TRUE);
5324 /*-----------------------------------------------------------------*/
5325 /* AccRol - rotate left accumulator by known count */
5326 /*-----------------------------------------------------------------*/
5327 static void AccRol (int shCount)
5329 shCount &= 0x0007; // shCount : 0..7
5341 emitcode("swap","a");
5345 emitcode("swap","a");
5348 emitcode("swap","a");
5361 /*-----------------------------------------------------------------*/
5362 /* AccLsh - left shift accumulator by known count */
5363 /*-----------------------------------------------------------------*/
5364 static void AccLsh (int shCount)
5368 emitcode("add","a,acc");
5371 emitcode("add","a,acc");
5372 emitcode("add","a,acc");
5374 /* rotate left accumulator */
5376 /* and kill the lower order bits */
5377 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5382 /*-----------------------------------------------------------------*/
5383 /* AccRsh - right shift accumulator by known count */
5384 /*-----------------------------------------------------------------*/
5385 static void AccRsh (int shCount)
5390 emitcode("rrc","a");
5392 /* rotate right accumulator */
5393 AccRol(8 - shCount);
5394 /* and kill the higher order bits */
5395 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5400 /*-----------------------------------------------------------------*/
5401 /* AccSRsh - signed right shift accumulator by known count */
5402 /*-----------------------------------------------------------------*/
5403 static void AccSRsh (int shCount)
5408 emitcode("mov","c,acc.7");
5409 emitcode("rrc","a");
5410 } else if(shCount == 2){
5411 emitcode("mov","c,acc.7");
5412 emitcode("rrc","a");
5413 emitcode("mov","c,acc.7");
5414 emitcode("rrc","a");
5416 tlbl = newiTempLabel(NULL);
5417 /* rotate right accumulator */
5418 AccRol(8 - shCount);
5419 /* and kill the higher order bits */
5420 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5421 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5422 emitcode("orl","a,#0x%02x",
5423 (unsigned char)~SRMask[shCount]);
5424 emitcode("","%05d$:",tlbl->key+100);
5429 /*-----------------------------------------------------------------*/
5430 /* shiftR1Left2Result - shift right one byte from left to result */
5431 /*-----------------------------------------------------------------*/
5432 static void shiftR1Left2Result (operand *left, int offl,
5433 operand *result, int offr,
5434 int shCount, int sign)
5436 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5437 /* shift right accumulator */
5442 aopPut(AOP(result),"a",offr);
5445 /*-----------------------------------------------------------------*/
5446 /* shiftL1Left2Result - shift left one byte from left to result */
5447 /*-----------------------------------------------------------------*/
5448 static void shiftL1Left2Result (operand *left, int offl,
5449 operand *result, int offr, int shCount)
5452 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5454 /* shift left accumulator */
5456 aopPut(AOP(result),"a",offr);
5459 /*-----------------------------------------------------------------*/
5460 /* movLeft2Result - move byte from left to result */
5461 /*-----------------------------------------------------------------*/
5462 static void movLeft2Result (operand *left, int offl,
5463 operand *result, int offr, int sign)
5466 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5467 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5469 if (*l == '@' && (IS_AOP_PREG(result))) {
5470 emitcode("mov","a,%s",l);
5471 aopPut(AOP(result),"a",offr);
5474 aopPut(AOP(result),l,offr);
5476 /* MSB sign in acc.7 ! */
5477 if(getDataSize(left) == offl+1){
5478 emitcode("mov","a,%s",l);
5479 aopPut(AOP(result),"a",offr);
5486 /*-----------------------------------------------------------------*/
5487 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5488 /*-----------------------------------------------------------------*/
5489 static void AccAXRrl1 (char *x)
5491 emitcode("rrc","a");
5492 emitcode("xch","a,%s", x);
5493 emitcode("rrc","a");
5494 emitcode("xch","a,%s", x);
5497 /*-----------------------------------------------------------------*/
5498 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5499 /*-----------------------------------------------------------------*/
5500 static void AccAXLrl1 (char *x)
5502 emitcode("xch","a,%s",x);
5503 emitcode("rlc","a");
5504 emitcode("xch","a,%s",x);
5505 emitcode("rlc","a");
5508 /*-----------------------------------------------------------------*/
5509 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5510 /*-----------------------------------------------------------------*/
5511 static void AccAXLsh1 (char *x)
5513 emitcode("xch","a,%s",x);
5514 emitcode("add","a,acc");
5515 emitcode("xch","a,%s",x);
5516 emitcode("rlc","a");
5519 /*-----------------------------------------------------------------*/
5520 /* AccAXLsh - left shift a:x by known count (0..7) */
5521 /*-----------------------------------------------------------------*/
5522 static void AccAXLsh (char *x, int shCount)
5536 case 5 : // AAAAABBB:CCCCCDDD
5537 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5538 emitcode("anl","a,#0x%02x",
5539 SLMask[shCount]); // BBB00000:CCCCCDDD
5540 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5541 AccRol(shCount); // DDDCCCCC:BBB00000
5542 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5543 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5544 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5545 emitcode("anl","a,#0x%02x",
5546 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5547 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5548 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5550 case 6 : // AAAAAABB:CCCCCCDD
5551 emitcode("anl","a,#0x%02x",
5552 SRMask[shCount]); // 000000BB:CCCCCCDD
5553 emitcode("mov","c,acc.0"); // c = B
5554 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5555 AccAXRrl1(x); // BCCCCCCD:D000000B
5556 AccAXRrl1(x); // BBCCCCCC:DD000000
5558 case 7 : // a:x <<= 7
5559 emitcode("anl","a,#0x%02x",
5560 SRMask[shCount]); // 0000000B:CCCCCCCD
5561 emitcode("mov","c,acc.0"); // c = B
5562 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5563 AccAXRrl1(x); // BCCCCCCC:D0000000
5570 /*-----------------------------------------------------------------*/
5571 /* AccAXRsh - right shift a:x known count (0..7) */
5572 /*-----------------------------------------------------------------*/
5573 static void AccAXRsh (char *x, int shCount)
5580 AccAXRrl1(x); // 0->a:x
5584 AccAXRrl1(x); // 0->a:x
5586 AccAXRrl1(x); // 0->a:x
5590 case 5 : // AAAAABBB:CCCCCDDD = a:x
5591 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5592 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5593 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5594 emitcode("anl","a,#0x%02x",
5595 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5596 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5597 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5598 emitcode("anl","a,#0x%02x",
5599 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5600 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5601 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5602 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5604 case 6 : // AABBBBBB:CCDDDDDD
5605 emitcode("mov","c,acc.7");
5606 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5607 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5608 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5609 emitcode("anl","a,#0x%02x",
5610 SRMask[shCount]); // 000000AA:BBBBBBCC
5612 case 7 : // ABBBBBBB:CDDDDDDD
5613 emitcode("mov","c,acc.7"); // c = A
5614 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5615 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5616 emitcode("anl","a,#0x%02x",
5617 SRMask[shCount]); // 0000000A:BBBBBBBC
5624 /*-----------------------------------------------------------------*/
5625 /* AccAXRshS - right shift signed a:x known count (0..7) */
5626 /*-----------------------------------------------------------------*/
5627 static void AccAXRshS (char *x, int shCount)
5634 emitcode("mov","c,acc.7");
5635 AccAXRrl1(x); // s->a:x
5638 emitcode("mov","c,acc.7");
5639 AccAXRrl1(x); // s->a:x
5640 emitcode("mov","c,acc.7");
5641 AccAXRrl1(x); // s->a:x
5645 case 5 : // AAAAABBB:CCCCCDDD = a:x
5646 tlbl = newiTempLabel(NULL);
5647 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5648 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5649 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5650 emitcode("anl","a,#0x%02x",
5651 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5652 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5653 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5654 emitcode("anl","a,#0x%02x",
5655 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5656 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5657 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5658 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5659 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5660 emitcode("orl","a,#0x%02x",
5661 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5662 emitcode("","%05d$:",tlbl->key+100);
5663 break; // SSSSAAAA:BBBCCCCC
5664 case 6 : // AABBBBBB:CCDDDDDD
5665 tlbl = newiTempLabel(NULL);
5666 emitcode("mov","c,acc.7");
5667 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5668 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5669 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5670 emitcode("anl","a,#0x%02x",
5671 SRMask[shCount]); // 000000AA:BBBBBBCC
5672 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5673 emitcode("orl","a,#0x%02x",
5674 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5675 emitcode("","%05d$:",tlbl->key+100);
5677 case 7 : // ABBBBBBB:CDDDDDDD
5678 tlbl = newiTempLabel(NULL);
5679 emitcode("mov","c,acc.7"); // c = A
5680 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5681 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5682 emitcode("anl","a,#0x%02x",
5683 SRMask[shCount]); // 0000000A:BBBBBBBC
5684 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5685 emitcode("orl","a,#0x%02x",
5686 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5687 emitcode("","%05d$:",tlbl->key+100);
5694 /*-----------------------------------------------------------------*/
5695 /* shiftL2Left2Result - shift left two bytes from left to result */
5696 /*-----------------------------------------------------------------*/
5697 static void shiftL2Left2Result (operand *left, int offl,
5698 operand *result, int offr, int shCount)
5700 if(sameRegs(AOP(result), AOP(left)) &&
5701 ((offl + MSB16) == offr)){
5702 /* don't crash result[offr] */
5703 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5704 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5706 movLeft2Result(left,offl, result, offr, 0);
5707 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5709 /* ax << shCount (x = lsb(result))*/
5710 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5711 aopPut(AOP(result),"a",offr+MSB16);
5715 /*-----------------------------------------------------------------*/
5716 /* shiftR2Left2Result - shift right two bytes from left to result */
5717 /*-----------------------------------------------------------------*/
5718 static void shiftR2Left2Result (operand *left, int offl,
5719 operand *result, int offr,
5720 int shCount, int sign)
5722 if(sameRegs(AOP(result), AOP(left)) &&
5723 ((offl + MSB16) == offr)){
5724 /* don't crash result[offr] */
5725 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5726 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5728 movLeft2Result(left,offl, result, offr, 0);
5729 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5731 /* a:x >> shCount (x = lsb(result))*/
5733 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5735 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5736 if(getDataSize(result) > 1)
5737 aopPut(AOP(result),"a",offr+MSB16);
5740 /*-----------------------------------------------------------------*/
5741 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5742 /*-----------------------------------------------------------------*/
5743 static void shiftLLeftOrResult (operand *left, int offl,
5744 operand *result, int offr, int shCount)
5746 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5747 /* shift left accumulator */
5749 /* or with result */
5750 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5751 /* back to result */
5752 aopPut(AOP(result),"a",offr);
5755 /*-----------------------------------------------------------------*/
5756 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5757 /*-----------------------------------------------------------------*/
5758 static void shiftRLeftOrResult (operand *left, int offl,
5759 operand *result, int offr, int shCount)
5761 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5762 /* shift right accumulator */
5764 /* or with result */
5765 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5766 /* back to result */
5767 aopPut(AOP(result),"a",offr);
5770 /*-----------------------------------------------------------------*/
5771 /* genlshOne - left shift a one byte quantity by known count */
5772 /*-----------------------------------------------------------------*/
5773 static void genlshOne (operand *result, operand *left, int shCount)
5775 D(emitcode(";", "genlshOne "););
5776 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5779 /*-----------------------------------------------------------------*/
5780 /* genlshTwo - left shift two bytes by known amount != 0 */
5781 /*-----------------------------------------------------------------*/
5782 static void genlshTwo (operand *result,operand *left, int shCount)
5786 D(emitcode(";", "genlshTwo "););
5788 size = getDataSize(result);
5790 /* if shCount >= 8 */
5796 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5798 movLeft2Result(left, LSB, result, MSB16, 0);
5800 aopPut(AOP(result),zero,LSB);
5803 /* 1 <= shCount <= 7 */
5806 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5808 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5812 /*-----------------------------------------------------------------*/
5813 /* shiftLLong - shift left one long from left to result */
5814 /* offl = LSB or MSB16 */
5815 /*-----------------------------------------------------------------*/
5816 static void shiftLLong (operand *left, operand *result, int offr )
5819 int size = AOP_SIZE(result);
5821 if(size >= LSB+offr){
5822 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5824 emitcode("add","a,acc");
5825 if (sameRegs(AOP(left),AOP(result)) &&
5826 size >= MSB16+offr && offr != LSB )
5827 emitcode("xch","a,%s",
5828 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5830 aopPut(AOP(result),"a",LSB+offr);
5833 if(size >= MSB16+offr){
5834 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5835 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5838 emitcode("rlc","a");
5839 if (sameRegs(AOP(left),AOP(result)) &&
5840 size >= MSB24+offr && offr != LSB)
5841 emitcode("xch","a,%s",
5842 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5844 aopPut(AOP(result),"a",MSB16+offr);
5847 if(size >= MSB24+offr){
5848 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5849 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5852 emitcode("rlc","a");
5853 if (sameRegs(AOP(left),AOP(result)) &&
5854 size >= MSB32+offr && offr != LSB )
5855 emitcode("xch","a,%s",
5856 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5858 aopPut(AOP(result),"a",MSB24+offr);
5861 if(size > MSB32+offr){
5862 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5863 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5866 emitcode("rlc","a");
5867 aopPut(AOP(result),"a",MSB32+offr);
5870 aopPut(AOP(result),zero,LSB);
5873 /*-----------------------------------------------------------------*/
5874 /* genlshFour - shift four byte by a known amount != 0 */
5875 /*-----------------------------------------------------------------*/
5876 static void genlshFour (operand *result, operand *left, int shCount)
5880 D(emitcode(";", "genlshFour "););
5882 size = AOP_SIZE(result);
5884 /* if shifting more that 3 bytes */
5885 if (shCount >= 24 ) {
5888 /* lowest order of left goes to the highest
5889 order of the destination */
5890 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5892 movLeft2Result(left, LSB, result, MSB32, 0);
5893 aopPut(AOP(result),zero,LSB);
5894 aopPut(AOP(result),zero,MSB16);
5895 aopPut(AOP(result),zero,MSB32);
5899 /* more than two bytes */
5900 else if ( shCount >= 16 ) {
5901 /* lower order two bytes goes to higher order two bytes */
5903 /* if some more remaining */
5905 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5907 movLeft2Result(left, MSB16, result, MSB32, 0);
5908 movLeft2Result(left, LSB, result, MSB24, 0);
5910 aopPut(AOP(result),zero,MSB16);
5911 aopPut(AOP(result),zero,LSB);
5915 /* if more than 1 byte */
5916 else if ( shCount >= 8 ) {
5917 /* lower order three bytes goes to higher order three bytes */
5921 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5923 movLeft2Result(left, LSB, result, MSB16, 0);
5925 else{ /* size = 4 */
5927 movLeft2Result(left, MSB24, result, MSB32, 0);
5928 movLeft2Result(left, MSB16, result, MSB24, 0);
5929 movLeft2Result(left, LSB, result, MSB16, 0);
5930 aopPut(AOP(result),zero,LSB);
5932 else if(shCount == 1)
5933 shiftLLong(left, result, MSB16);
5935 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5936 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5937 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5938 aopPut(AOP(result),zero,LSB);
5943 /* 1 <= shCount <= 7 */
5944 else if(shCount <= 2){
5945 shiftLLong(left, result, LSB);
5947 shiftLLong(result, result, LSB);
5949 /* 3 <= shCount <= 7, optimize */
5951 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5952 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5953 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5957 /*-----------------------------------------------------------------*/
5958 /* genLeftShiftLiteral - left shifting by known count */
5959 /*-----------------------------------------------------------------*/
5960 static void genLeftShiftLiteral (operand *left,
5965 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5968 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
5970 freeAsmop(right,NULL,ic,TRUE);
5972 aopOp(left,ic,FALSE, FALSE);
5973 aopOp(result,ic,FALSE, TRUE);
5975 size = getSize(operandType(result));
5978 emitcode("; shift left ","result %d, left %d",size,
5982 /* I suppose that the left size >= result size */
5985 movLeft2Result(left, size, result, size, 0);
5989 else if(shCount >= (size * 8))
5991 aopPut(AOP(result),zero,size);
5995 genlshOne (result,left,shCount);
5999 case 3: /* bug: this is for generic pointers, I bet. */
6000 genlshTwo (result,left,shCount);
6004 genlshFour (result,left,shCount);
6008 freeAsmop(left,NULL,ic,TRUE);
6009 freeAsmop(result,NULL,ic,TRUE);
6012 /*-----------------------------------------------------------------*/
6013 /* genLeftShift - generates code for left shifting */
6014 /*-----------------------------------------------------------------*/
6015 static void genLeftShift (iCode *ic)
6017 operand *left,*right, *result;
6020 symbol *tlbl , *tlbl1;
6022 D(emitcode(";", "genLeftShift "););
6024 right = IC_RIGHT(ic);
6026 result = IC_RESULT(ic);
6028 aopOp(right,ic,FALSE, FALSE);
6031 /* if the shift count is known then do it
6032 as efficiently as possible */
6033 if (AOP_TYPE(right) == AOP_LIT) {
6034 genLeftShiftLiteral (left,right,result,ic);
6039 /* shift count is unknown then we have to form
6040 a loop get the loop count in B : Note: we take
6041 only the lower order byte since shifting
6042 more that 32 bits make no sense anyway, ( the
6043 largest size of an object can be only 32 bits ) */
6045 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6046 emitcode("inc","b");
6047 freeAsmop (right,NULL,ic,TRUE);
6048 aopOp(left,ic,FALSE, FALSE);
6049 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6051 /* now move the left to the result if they are not the
6053 if (!sameRegs(AOP(left),AOP(result)) &&
6054 AOP_SIZE(result) > 1) {
6056 size = AOP_SIZE(result);
6058 _startLazyDPSEvaluation();
6060 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6061 if (*l == '@' && (IS_AOP_PREG(result))) {
6063 emitcode("mov","a,%s",l);
6064 aopPut(AOP(result),"a",offset);
6066 aopPut(AOP(result),l,offset);
6069 _endLazyDPSEvaluation();
6072 tlbl = newiTempLabel(NULL);
6073 size = AOP_SIZE(result);
6075 tlbl1 = newiTempLabel(NULL);
6077 /* if it is only one byte then */
6079 symbol *tlbl1 = newiTempLabel(NULL);
6081 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6083 emitcode("sjmp","%05d$",tlbl1->key+100);
6084 emitcode("","%05d$:",tlbl->key+100);
6085 emitcode("add","a,acc");
6086 emitcode("","%05d$:",tlbl1->key+100);
6087 emitcode("djnz","b,%05d$",tlbl->key+100);
6088 aopPut(AOP(result),"a",0);
6092 reAdjustPreg(AOP(result));
6094 emitcode("sjmp","%05d$",tlbl1->key+100);
6095 emitcode("","%05d$:",tlbl->key+100);
6096 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6098 emitcode("add","a,acc");
6099 aopPut(AOP(result),"a",offset++);
6100 _startLazyDPSEvaluation();
6102 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6104 emitcode("rlc","a");
6105 aopPut(AOP(result),"a",offset++);
6107 _endLazyDPSEvaluation();
6108 reAdjustPreg(AOP(result));
6110 emitcode("","%05d$:",tlbl1->key+100);
6111 emitcode("djnz","b,%05d$",tlbl->key+100);
6113 freeAsmop(left,NULL,ic,TRUE);
6114 freeAsmop(result,NULL,ic,TRUE);
6117 /*-----------------------------------------------------------------*/
6118 /* genrshOne - right shift a one byte quantity by known count */
6119 /*-----------------------------------------------------------------*/
6120 static void genrshOne (operand *result, operand *left,
6121 int shCount, int sign)
6123 D(emitcode(";", "genrshOne"););
6124 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6127 /*-----------------------------------------------------------------*/
6128 /* genrshTwo - right shift two bytes by known amount != 0 */
6129 /*-----------------------------------------------------------------*/
6130 static void genrshTwo (operand *result,operand *left,
6131 int shCount, int sign)
6133 D(emitcode(";", "genrshTwo"););
6135 /* if shCount >= 8 */
6139 shiftR1Left2Result(left, MSB16, result, LSB,
6142 movLeft2Result(left, MSB16, result, LSB, sign);
6143 addSign(result, MSB16, sign);
6146 /* 1 <= shCount <= 7 */
6148 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6151 /*-----------------------------------------------------------------*/
6152 /* shiftRLong - shift right one long from left to result */
6153 /* offl = LSB or MSB16 */
6154 /*-----------------------------------------------------------------*/
6155 static void shiftRLong (operand *left, int offl,
6156 operand *result, int sign)
6159 emitcode("clr","c");
6160 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6162 emitcode("mov","c,acc.7");
6163 emitcode("rrc","a");
6164 aopPut(AOP(result),"a",MSB32-offl);
6166 /* add sign of "a" */
6167 addSign(result, MSB32, sign);
6169 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6170 emitcode("rrc","a");
6171 aopPut(AOP(result),"a",MSB24-offl);
6173 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6174 emitcode("rrc","a");
6175 aopPut(AOP(result),"a",MSB16-offl);
6178 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6179 emitcode("rrc","a");
6180 aopPut(AOP(result),"a",LSB);
6184 /*-----------------------------------------------------------------*/
6185 /* genrshFour - shift four byte by a known amount != 0 */
6186 /*-----------------------------------------------------------------*/
6187 static void genrshFour (operand *result, operand *left,
6188 int shCount, int sign)
6190 D(emitcode(";", "genrshFour"););
6192 /* if shifting more that 3 bytes */
6193 if(shCount >= 24 ) {
6196 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6198 movLeft2Result(left, MSB32, result, LSB, sign);
6199 addSign(result, MSB16, sign);
6201 else if(shCount >= 16){
6204 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6206 movLeft2Result(left, MSB24, result, LSB, 0);
6207 movLeft2Result(left, MSB32, result, MSB16, sign);
6209 addSign(result, MSB24, sign);
6211 else if(shCount >= 8){
6214 shiftRLong(left, MSB16, result, sign);
6215 else if(shCount == 0){
6216 movLeft2Result(left, MSB16, result, LSB, 0);
6217 movLeft2Result(left, MSB24, result, MSB16, 0);
6218 movLeft2Result(left, MSB32, result, MSB24, sign);
6219 addSign(result, MSB32, sign);
6222 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6223 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6224 /* the last shift is signed */
6225 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6226 addSign(result, MSB32, sign);
6229 else{ /* 1 <= shCount <= 7 */
6231 shiftRLong(left, LSB, result, sign);
6233 shiftRLong(result, LSB, result, sign);
6236 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6237 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6238 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6243 /*-----------------------------------------------------------------*/
6244 /* genRightShiftLiteral - right shifting by known count */
6245 /*-----------------------------------------------------------------*/
6246 static void genRightShiftLiteral (operand *left,
6252 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6255 D(emitcode(";", "genRightShiftLiteral"););
6257 freeAsmop(right,NULL,ic,TRUE);
6259 aopOp(left,ic,FALSE, FALSE);
6260 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6263 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6267 size = getDataSize(left);
6268 /* test the LEFT size !!! */
6270 /* I suppose that the left size >= result size */
6272 size = getDataSize(result);
6274 movLeft2Result(left, size, result, size, 0);
6277 else if(shCount >= (size * 8)){
6279 /* get sign in acc.7 */
6280 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6281 addSign(result, LSB, sign);
6285 genrshOne (result,left,shCount,sign);
6289 genrshTwo (result,left,shCount,sign);
6293 genrshFour (result,left,shCount,sign);
6299 freeAsmop(left,NULL,ic,TRUE);
6300 freeAsmop(result,NULL,ic,TRUE);
6304 /*-----------------------------------------------------------------*/
6305 /* genSignedRightShift - right shift of signed number */
6306 /*-----------------------------------------------------------------*/
6307 static void genSignedRightShift (iCode *ic)
6309 operand *right, *left, *result;
6312 symbol *tlbl, *tlbl1 ;
6314 D(emitcode(";", "genSignedRightShift "););
6316 /* we do it the hard way put the shift count in b
6317 and loop thru preserving the sign */
6319 right = IC_RIGHT(ic);
6321 result = IC_RESULT(ic);
6323 aopOp(right,ic,FALSE, FALSE);
6326 if ( AOP_TYPE(right) == AOP_LIT) {
6327 genRightShiftLiteral (left,right,result,ic,1);
6331 /* shift count is unknown then we have to form
6332 a loop get the loop count in B : Note: we take
6333 only the lower order byte since shifting
6334 more that 32 bits make no sense anyway, ( the
6335 largest size of an object can be only 32 bits ) */
6337 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6338 emitcode("inc","b");
6339 freeAsmop (right,NULL,ic,TRUE);
6340 aopOp(left,ic,FALSE, FALSE);
6341 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6343 /* now move the left to the result if they are not the
6345 if (!sameRegs(AOP(left),AOP(result)) &&
6346 AOP_SIZE(result) > 1) {
6348 size = AOP_SIZE(result);
6350 _startLazyDPSEvaluation();
6352 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6353 if (*l == '@' && IS_AOP_PREG(result)) {
6355 emitcode("mov","a,%s",l);
6356 aopPut(AOP(result),"a",offset);
6358 aopPut(AOP(result),l,offset);
6361 _endLazyDPSEvaluation();
6364 /* mov the highest order bit to OVR */
6365 tlbl = newiTempLabel(NULL);
6366 tlbl1= newiTempLabel(NULL);
6368 size = AOP_SIZE(result);
6370 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6371 emitcode("rlc","a");
6372 emitcode("mov","ov,c");
6373 /* if it is only one byte then */
6375 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6377 emitcode("sjmp","%05d$",tlbl1->key+100);
6378 emitcode("","%05d$:",tlbl->key+100);
6379 emitcode("mov","c,ov");
6380 emitcode("rrc","a");
6381 emitcode("","%05d$:",tlbl1->key+100);
6382 emitcode("djnz","b,%05d$",tlbl->key+100);
6383 aopPut(AOP(result),"a",0);
6387 reAdjustPreg(AOP(result));
6388 emitcode("sjmp","%05d$",tlbl1->key+100);
6389 emitcode("","%05d$:",tlbl->key+100);
6390 emitcode("mov","c,ov");
6391 _startLazyDPSEvaluation();
6393 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6395 emitcode("rrc","a");
6396 aopPut(AOP(result),"a",offset--);
6398 _endLazyDPSEvaluation();
6399 reAdjustPreg(AOP(result));
6400 emitcode("","%05d$:",tlbl1->key+100);
6401 emitcode("djnz","b,%05d$",tlbl->key+100);
6404 freeAsmop(left,NULL,ic,TRUE);
6405 freeAsmop(result,NULL,ic,TRUE);
6408 /*-----------------------------------------------------------------*/
6409 /* genRightShift - generate code for right shifting */
6410 /*-----------------------------------------------------------------*/
6411 static void genRightShift (iCode *ic)
6413 operand *right, *left, *result;
6417 symbol *tlbl, *tlbl1 ;
6419 D(emitcode(";", "genRightShift "););
6421 /* if signed then we do it the hard way preserve the
6422 sign bit moving it inwards */
6423 retype = getSpec(operandType(IC_RESULT(ic)));
6425 if (!SPEC_USIGN(retype)) {
6426 genSignedRightShift (ic);
6430 /* signed & unsigned types are treated the same : i.e. the
6431 signed is NOT propagated inwards : quoting from the
6432 ANSI - standard : "for E1 >> E2, is equivalent to division
6433 by 2**E2 if unsigned or if it has a non-negative value,
6434 otherwise the result is implementation defined ", MY definition
6435 is that the sign does not get propagated */
6437 right = IC_RIGHT(ic);
6439 result = IC_RESULT(ic);
6441 aopOp(right,ic,FALSE, FALSE);
6444 /* if the shift count is known then do it
6445 as efficiently as possible */
6446 if (AOP_TYPE(right) == AOP_LIT) {
6447 genRightShiftLiteral (left,right,result,ic, 0);
6452 /* shift count is unknown then we have to form
6453 a loop get the loop count in B : Note: we take
6454 only the lower order byte since shifting
6455 more that 32 bits make no sense anyway, ( the
6456 largest size of an object can be only 32 bits ) */
6458 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6459 emitcode("inc","b");
6460 freeAsmop (right,NULL,ic,TRUE);
6461 aopOp(left,ic,FALSE, FALSE);
6462 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6464 /* now move the left to the result if they are not the
6466 if (!sameRegs(AOP(left),AOP(result)) &&
6467 AOP_SIZE(result) > 1) {
6469 size = AOP_SIZE(result);
6471 _startLazyDPSEvaluation();
6473 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6474 if (*l == '@' && IS_AOP_PREG(result)) {
6476 emitcode("mov","a,%s",l);
6477 aopPut(AOP(result),"a",offset);
6479 aopPut(AOP(result),l,offset);
6482 _endLazyDPSEvaluation();
6485 tlbl = newiTempLabel(NULL);
6486 tlbl1= newiTempLabel(NULL);
6487 size = AOP_SIZE(result);
6490 /* if it is only one byte then */
6492 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6494 emitcode("sjmp","%05d$",tlbl1->key+100);
6495 emitcode("","%05d$:",tlbl->key+100);
6497 emitcode("rrc","a");
6498 emitcode("","%05d$:",tlbl1->key+100);
6499 emitcode("djnz","b,%05d$",tlbl->key+100);
6500 aopPut(AOP(result),"a",0);
6504 reAdjustPreg(AOP(result));
6505 emitcode("sjmp","%05d$",tlbl1->key+100);
6506 emitcode("","%05d$:",tlbl->key+100);
6508 _startLazyDPSEvaluation();
6510 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6512 emitcode("rrc","a");
6513 aopPut(AOP(result),"a",offset--);
6515 _endLazyDPSEvaluation();
6516 reAdjustPreg(AOP(result));
6518 emitcode("","%05d$:",tlbl1->key+100);
6519 emitcode("djnz","b,%05d$",tlbl->key+100);
6522 freeAsmop(left,NULL,ic,TRUE);
6523 freeAsmop(result,NULL,ic,TRUE);
6526 /*-----------------------------------------------------------------*/
6527 /* genUnpackBits - generates code for unpacking bits */
6528 /*-----------------------------------------------------------------*/
6529 static void genUnpackBits (operand *result, char *rname, int ptype)
6536 D(emitcode(";", "genUnpackBits "););
6538 etype = getSpec(operandType(result));
6540 /* read the first byte */
6545 emitcode("mov","a,@%s",rname);
6549 emitcode("movx","a,@%s",rname);
6553 emitcode("movx","a,@dptr");
6557 emitcode("clr","a");
6558 emitcode("movc","a","@a+dptr");
6562 emitcode("lcall","__gptrget");
6566 /* if we have bitdisplacement then it fits */
6567 /* into this byte completely or if length is */
6568 /* less than a byte */
6569 if ((shCnt = SPEC_BSTR(etype)) ||
6570 (SPEC_BLEN(etype) <= 8)) {
6572 /* shift right acc */
6575 emitcode("anl","a,#0x%02x",
6576 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6577 aopPut(AOP(result),"a",offset);
6581 /* bit field did not fit in a byte */
6582 rlen = SPEC_BLEN(etype) - 8;
6583 aopPut(AOP(result),"a",offset++);
6590 emitcode("inc","%s",rname);
6591 emitcode("mov","a,@%s",rname);
6595 emitcode("inc","%s",rname);
6596 emitcode("movx","a,@%s",rname);
6600 emitcode("inc","dptr");
6601 emitcode("movx","a,@dptr");
6605 emitcode("clr","a");
6606 emitcode("inc","dptr");
6607 emitcode("movc","a","@a+dptr");
6611 emitcode("inc","dptr");
6612 emitcode("lcall","__gptrget");
6617 /* if we are done */
6621 aopPut(AOP(result),"a",offset++);
6626 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6627 aopPut(AOP(result),"a",offset);
6634 /*-----------------------------------------------------------------*/
6635 /* genDataPointerGet - generates code when ptr offset is known */
6636 /*-----------------------------------------------------------------*/
6637 static void genDataPointerGet (operand *left,
6643 int size , offset = 0;
6644 aopOp(result,ic,TRUE, FALSE);
6646 /* get the string representation of the name */
6647 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6648 size = AOP_SIZE(result);
6649 _startLazyDPSEvaluation();
6652 sprintf(buffer,"(%s + %d)",l+1,offset);
6654 sprintf(buffer,"%s",l+1);
6655 aopPut(AOP(result),buffer,offset++);
6657 _endLazyDPSEvaluation();
6659 freeAsmop(left,NULL,ic,TRUE);
6660 freeAsmop(result,NULL,ic,TRUE);
6663 /*-----------------------------------------------------------------*/
6664 /* genNearPointerGet - emitcode for near pointer fetch */
6665 /*-----------------------------------------------------------------*/
6666 static void genNearPointerGet (operand *left,
6673 link *rtype, *retype;
6674 link *ltype = operandType(left);
6677 rtype = operandType(result);
6678 retype= getSpec(rtype);
6680 aopOp(left,ic,FALSE, FALSE);
6682 /* if left is rematerialisable and
6683 result is not bit variable type and
6684 the left is pointer to data space i.e
6685 lower 128 bytes of space */
6686 if (AOP_TYPE(left) == AOP_IMMD &&
6687 !IS_BITVAR(retype) &&
6688 DCL_TYPE(ltype) == POINTER) {
6689 genDataPointerGet (left,result,ic);
6693 /* if the value is already in a pointer register
6694 then don't need anything more */
6695 if (!AOP_INPREG(AOP(left))) {
6696 /* otherwise get a free pointer register */
6698 preg = getFreePtr(ic,&aop,FALSE);
6699 emitcode("mov","%s,%s",
6701 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6702 rname = preg->name ;
6704 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6706 freeAsmop(left,NULL,ic,TRUE);
6707 aopOp (result,ic,FALSE, FALSE);
6709 /* if bitfield then unpack the bits */
6710 if (IS_BITVAR(retype))
6711 genUnpackBits (result,rname,POINTER);
6713 /* we have can just get the values */
6714 int size = AOP_SIZE(result);
6718 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6720 emitcode("mov","a,@%s",rname);
6721 aopPut(AOP(result),"a",offset);
6723 sprintf(buffer,"@%s",rname);
6724 aopPut(AOP(result),buffer,offset);
6728 emitcode("inc","%s",rname);
6732 /* now some housekeeping stuff */
6734 /* we had to allocate for this iCode */
6735 freeAsmop(NULL,aop,ic,TRUE);
6737 /* we did not allocate which means left
6738 already in a pointer register, then
6739 if size > 0 && this could be used again
6740 we have to point it back to where it
6742 if (AOP_SIZE(result) > 1 &&
6743 !OP_SYMBOL(left)->remat &&
6744 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6746 int size = AOP_SIZE(result) - 1;
6748 emitcode("dec","%s",rname);
6753 freeAsmop(result,NULL,ic,TRUE);
6757 /*-----------------------------------------------------------------*/
6758 /* genPagedPointerGet - emitcode for paged pointer fetch */
6759 /*-----------------------------------------------------------------*/
6760 static void genPagedPointerGet (operand *left,
6767 link *rtype, *retype;
6769 rtype = operandType(result);
6770 retype= getSpec(rtype);
6772 aopOp(left,ic,FALSE, FALSE);
6774 /* if the value is already in a pointer register
6775 then don't need anything more */
6776 if (!AOP_INPREG(AOP(left))) {
6777 /* otherwise get a free pointer register */
6779 preg = getFreePtr(ic,&aop,FALSE);
6780 emitcode("mov","%s,%s",
6782 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6783 rname = preg->name ;
6785 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6787 freeAsmop(left,NULL,ic,TRUE);
6788 aopOp (result,ic,FALSE, FALSE);
6790 /* if bitfield then unpack the bits */
6791 if (IS_BITVAR(retype))
6792 genUnpackBits (result,rname,PPOINTER);
6794 /* we have can just get the values */
6795 int size = AOP_SIZE(result);
6800 emitcode("movx","a,@%s",rname);
6801 aopPut(AOP(result),"a",offset);
6806 emitcode("inc","%s",rname);
6810 /* now some housekeeping stuff */
6812 /* we had to allocate for this iCode */
6813 freeAsmop(NULL,aop,ic,TRUE);
6815 /* we did not allocate which means left
6816 already in a pointer register, then
6817 if size > 0 && this could be used again
6818 we have to point it back to where it
6820 if (AOP_SIZE(result) > 1 &&
6821 !OP_SYMBOL(left)->remat &&
6822 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6824 int size = AOP_SIZE(result) - 1;
6826 emitcode("dec","%s",rname);
6831 freeAsmop(result,NULL,ic,TRUE);
6836 /*-----------------------------------------------------------------*/
6837 /* genFarPointerGet - gget value from far space */
6838 /*-----------------------------------------------------------------*/
6839 static void genFarPointerGet (operand *left,
6840 operand *result, iCode *ic)
6843 link *retype = getSpec(operandType(result));
6845 D(emitcode(";", "genFarPointerGet"););
6847 aopOp(left,ic,FALSE, FALSE);
6849 /* if the operand is already in dptr
6850 then we do nothing else we move the value to dptr */
6851 if (AOP_TYPE(left) != AOP_STR) {
6852 /* if this is remateriazable */
6853 if (AOP_TYPE(left) == AOP_IMMD)
6855 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6859 /* we need to get it byte by byte */
6860 _startLazyDPSEvaluation();
6861 if (AOP_TYPE(left) != AOP_DPTR)
6863 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6864 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6865 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6869 /* We need to generate a load to DPTR indirect through DPTR. */
6870 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6871 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6872 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6873 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6874 emitcode("pop", "dph");
6875 emitcode("pop", "dpl");
6877 _endLazyDPSEvaluation();
6880 /* so dptr know contains the address */
6881 freeAsmop(left,NULL,ic,TRUE);
6882 aopOp(result,ic,FALSE, TRUE);
6884 /* if bit then unpack */
6885 if (IS_BITVAR(retype))
6886 genUnpackBits(result,"dptr",FPOINTER);
6888 size = AOP_SIZE(result);
6892 emitcode("movx","a,@dptr");
6893 aopPut(AOP(result),"a",offset++);
6895 emitcode("inc","dptr");
6899 freeAsmop(result,NULL,ic,TRUE);
6902 /*-----------------------------------------------------------------*/
6903 /* emitcodePointerGet - gget value from code space */
6904 /*-----------------------------------------------------------------*/
6905 static void emitcodePointerGet (operand *left,
6906 operand *result, iCode *ic)
6909 link *retype = getSpec(operandType(result));
6911 aopOp(left,ic,FALSE, FALSE);
6913 /* if the operand is already in dptr
6914 then we do nothing else we move the value to dptr */
6915 if (AOP_TYPE(left) != AOP_STR) {
6916 /* if this is remateriazable */
6917 if (AOP_TYPE(left) == AOP_IMMD)
6918 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6919 else { /* we need to get it byte by byte */
6920 _startLazyDPSEvaluation();
6921 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6922 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6923 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6924 _endLazyDPSEvaluation();
6927 /* so dptr know contains the address */
6928 freeAsmop(left,NULL,ic,TRUE);
6929 aopOp(result,ic,FALSE, FALSE);
6931 /* if bit then unpack */
6932 if (IS_BITVAR(retype))
6933 genUnpackBits(result,"dptr",CPOINTER);
6935 size = AOP_SIZE(result);
6939 emitcode("clr","a");
6940 emitcode("movc","a,@a+dptr");
6941 aopPut(AOP(result),"a",offset++);
6943 emitcode("inc","dptr");
6947 freeAsmop(result,NULL,ic,TRUE);
6950 /*-----------------------------------------------------------------*/
6951 /* genGenPointerGet - gget value from generic pointer space */
6952 /*-----------------------------------------------------------------*/
6953 static void genGenPointerGet (operand *left,
6954 operand *result, iCode *ic)
6957 link *retype = getSpec(operandType(result));
6959 aopOp(left,ic,FALSE, TRUE);
6961 /* if the operand is already in dptr
6962 then we do nothing else we move the value to dptr */
6963 if (AOP_TYPE(left) != AOP_STR) {
6964 /* if this is remateriazable */
6965 if (AOP_TYPE(left) == AOP_IMMD) {
6966 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6967 emitcode("mov","b,#%d",pointerCode(retype));
6969 else { /* we need to get it byte by byte */
6970 _startLazyDPSEvaluation();
6971 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6972 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6973 if (options.model == MODEL_FLAT24)
6975 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6976 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
6980 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6982 _endLazyDPSEvaluation();
6985 /* so dptr know contains the address */
6986 freeAsmop(left,NULL,ic,TRUE);
6987 aopOp(result,ic,FALSE, TRUE);
6989 /* if bit then unpack */
6990 if (IS_BITVAR(retype))
6991 genUnpackBits(result,"dptr",GPOINTER);
6993 size = AOP_SIZE(result);
6997 emitcode("lcall","__gptrget");
6998 aopPut(AOP(result),"a",offset++);
7000 emitcode("inc","dptr");
7004 freeAsmop(result,NULL,ic,TRUE);
7007 /*-----------------------------------------------------------------*/
7008 /* genPointerGet - generate code for pointer get */
7009 /*-----------------------------------------------------------------*/
7010 static void genPointerGet (iCode *ic)
7012 operand *left, *result ;
7016 D(emitcode(";", "genPointerGet "););
7019 result = IC_RESULT(ic) ;
7021 /* depending on the type of pointer we need to
7022 move it to the correct pointer register */
7023 type = operandType(left);
7024 etype = getSpec(type);
7025 /* if left is of type of pointer then it is simple */
7026 if (IS_PTR(type) && !IS_FUNC(type->next))
7027 p_type = DCL_TYPE(type);
7029 /* we have to go by the storage class */
7030 p_type = PTR_TYPE(SPEC_OCLS(etype));
7032 /* if (SPEC_OCLS(etype)->codesp ) { */
7033 /* p_type = CPOINTER ; */
7036 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7037 /* p_type = FPOINTER ; */
7039 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7040 /* p_type = PPOINTER; */
7042 /* if (SPEC_OCLS(etype) == idata ) */
7043 /* p_type = IPOINTER; */
7045 /* p_type = POINTER ; */
7048 /* now that we have the pointer type we assign
7049 the pointer values */
7054 genNearPointerGet (left,result,ic);
7058 genPagedPointerGet(left,result,ic);
7062 genFarPointerGet (left,result,ic);
7066 emitcodePointerGet (left,result,ic);
7070 genGenPointerGet (left,result,ic);
7076 /*-----------------------------------------------------------------*/
7077 /* genPackBits - generates code for packed bit storage */
7078 /*-----------------------------------------------------------------*/
7079 static void genPackBits (link *etype ,
7081 char *rname, int p_type)
7089 blen = SPEC_BLEN(etype);
7090 bstr = SPEC_BSTR(etype);
7092 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7095 /* if the bit lenth is less than or */
7096 /* it exactly fits a byte then */
7097 if (SPEC_BLEN(etype) <= 8 ) {
7098 shCount = SPEC_BSTR(etype) ;
7100 /* shift left acc */
7103 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7108 emitcode ("mov","b,a");
7109 emitcode("mov","a,@%s",rname);
7113 emitcode ("mov","b,a");
7114 emitcode("movx","a,@dptr");
7118 emitcode ("push","b");
7119 emitcode ("push","acc");
7120 emitcode ("lcall","__gptrget");
7121 emitcode ("pop","b");
7125 emitcode ("anl","a,#0x%02x",(unsigned char)
7126 ((unsigned char)(0xFF << (blen+bstr)) |
7127 (unsigned char)(0xFF >> (8-bstr)) ) );
7128 emitcode ("orl","a,b");
7129 if (p_type == GPOINTER)
7130 emitcode("pop","b");
7136 emitcode("mov","@%s,a",rname);
7140 emitcode("movx","@dptr,a");
7144 emitcode("lcall","__gptrput");
7149 if ( SPEC_BLEN(etype) <= 8 )
7152 emitcode("inc","%s",rname);
7153 rLen = SPEC_BLEN(etype) ;
7155 /* now generate for lengths greater than one byte */
7158 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7168 emitcode("mov","@%s,a",rname);
7170 emitcode("mov","@%s,%s",rname,l);
7175 emitcode("movx","@dptr,a");
7180 emitcode("lcall","__gptrput");
7183 emitcode ("inc","%s",rname);
7188 /* last last was not complete */
7190 /* save the byte & read byte */
7193 emitcode ("mov","b,a");
7194 emitcode("mov","a,@%s",rname);
7198 emitcode ("mov","b,a");
7199 emitcode("movx","a,@dptr");
7203 emitcode ("push","b");
7204 emitcode ("push","acc");
7205 emitcode ("lcall","__gptrget");
7206 emitcode ("pop","b");
7210 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7211 emitcode ("orl","a,b");
7214 if (p_type == GPOINTER)
7215 emitcode("pop","b");
7220 emitcode("mov","@%s,a",rname);
7224 emitcode("movx","@dptr,a");
7228 emitcode("lcall","__gptrput");
7232 /*-----------------------------------------------------------------*/
7233 /* genDataPointerSet - remat pointer to data space */
7234 /*-----------------------------------------------------------------*/
7235 static void genDataPointerSet(operand *right,
7239 int size, offset = 0 ;
7240 char *l, buffer[256];
7242 aopOp(right,ic,FALSE, FALSE);
7244 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7245 size = AOP_SIZE(right);
7248 sprintf(buffer,"(%s + %d)",l+1,offset);
7250 sprintf(buffer,"%s",l+1);
7251 emitcode("mov","%s,%s",buffer,
7252 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7255 freeAsmop(right,NULL,ic,TRUE);
7256 freeAsmop(result,NULL,ic,TRUE);
7259 /*-----------------------------------------------------------------*/
7260 /* genNearPointerSet - emitcode for near pointer put */
7261 /*-----------------------------------------------------------------*/
7262 static void genNearPointerSet (operand *right,
7270 link *ptype = operandType(result);
7272 retype= getSpec(operandType(right));
7274 aopOp(result,ic,FALSE, FALSE);
7276 /* if the result is rematerializable &
7277 in data space & not a bit variable */
7278 if (AOP_TYPE(result) == AOP_IMMD &&
7279 DCL_TYPE(ptype) == POINTER &&
7280 !IS_BITVAR(retype)) {
7281 genDataPointerSet (right,result,ic);
7285 /* if the value is already in a pointer register
7286 then don't need anything more */
7287 if (!AOP_INPREG(AOP(result))) {
7288 /* otherwise get a free pointer register */
7290 preg = getFreePtr(ic,&aop,FALSE);
7291 emitcode("mov","%s,%s",
7293 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7294 rname = preg->name ;
7296 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7298 freeAsmop(result,NULL,ic,TRUE);
7299 aopOp (right,ic,FALSE, FALSE);
7301 /* if bitfield then unpack the bits */
7302 if (IS_BITVAR(retype))
7303 genPackBits (retype,right,rname,POINTER);
7305 /* we have can just get the values */
7306 int size = AOP_SIZE(right);
7310 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7313 emitcode("mov","@%s,a",rname);
7315 emitcode("mov","@%s,%s",rname,l);
7317 emitcode("inc","%s",rname);
7322 /* now some housekeeping stuff */
7324 /* we had to allocate for this iCode */
7325 freeAsmop(NULL,aop,ic,TRUE);
7327 /* we did not allocate which means left
7328 already in a pointer register, then
7329 if size > 0 && this could be used again
7330 we have to point it back to where it
7332 if (AOP_SIZE(right) > 1 &&
7333 !OP_SYMBOL(result)->remat &&
7334 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7336 int size = AOP_SIZE(right) - 1;
7338 emitcode("dec","%s",rname);
7343 freeAsmop(right,NULL,ic,TRUE);
7348 /*-----------------------------------------------------------------*/
7349 /* genPagedPointerSet - emitcode for Paged pointer put */
7350 /*-----------------------------------------------------------------*/
7351 static void genPagedPointerSet (operand *right,
7360 retype= getSpec(operandType(right));
7362 aopOp(result,ic,FALSE, FALSE);
7364 /* if the value is already in a pointer register
7365 then don't need anything more */
7366 if (!AOP_INPREG(AOP(result))) {
7367 /* otherwise get a free pointer register */
7369 preg = getFreePtr(ic,&aop,FALSE);
7370 emitcode("mov","%s,%s",
7372 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7373 rname = preg->name ;
7375 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7377 freeAsmop(result,NULL,ic,TRUE);
7378 aopOp (right,ic,FALSE, FALSE);
7380 /* if bitfield then unpack the bits */
7381 if (IS_BITVAR(retype))
7382 genPackBits (retype,right,rname,PPOINTER);
7384 /* we have can just get the values */
7385 int size = AOP_SIZE(right);
7389 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7392 emitcode("movx","@%s,a",rname);
7395 emitcode("inc","%s",rname);
7401 /* now some housekeeping stuff */
7403 /* we had to allocate for this iCode */
7404 freeAsmop(NULL,aop,ic,TRUE);
7406 /* we did not allocate which means left
7407 already in a pointer register, then
7408 if size > 0 && this could be used again
7409 we have to point it back to where it
7411 if (AOP_SIZE(right) > 1 &&
7412 !OP_SYMBOL(result)->remat &&
7413 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7415 int size = AOP_SIZE(right) - 1;
7417 emitcode("dec","%s",rname);
7422 freeAsmop(right,NULL,ic,TRUE);
7427 /*-----------------------------------------------------------------*/
7428 /* genFarPointerSet - set value from far space */
7429 /*-----------------------------------------------------------------*/
7430 static void genFarPointerSet (operand *right,
7431 operand *result, iCode *ic)
7434 link *retype = getSpec(operandType(right));
7436 aopOp(result,ic,FALSE, FALSE);
7438 /* if the operand is already in dptr
7439 then we do nothing else we move the value to dptr */
7440 if (AOP_TYPE(result) != AOP_STR) {
7441 /* if this is remateriazable */
7442 if (AOP_TYPE(result) == AOP_IMMD)
7443 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7446 /* we need to get it byte by byte */
7447 _startLazyDPSEvaluation();
7448 if (AOP_TYPE(result) != AOP_DPTR)
7450 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7451 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7452 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7456 /* We need to generate a load to DPTR indirect through DPTR. */
7457 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7458 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7459 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7460 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7461 emitcode("pop", "dph");
7462 emitcode("pop", "dpl");
7464 _endLazyDPSEvaluation();
7467 /* so dptr know contains the address */
7468 freeAsmop(result,NULL,ic,TRUE);
7469 aopOp(right,ic,FALSE, TRUE);
7471 /* if bit then unpack */
7472 if (IS_BITVAR(retype))
7473 genPackBits(retype,right,"dptr",FPOINTER);
7475 size = AOP_SIZE(right);
7478 _startLazyDPSEvaluation();
7480 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7482 emitcode("movx","@dptr,a");
7484 emitcode("inc","dptr");
7486 _endLazyDPSEvaluation();
7489 freeAsmop(right,NULL,ic,TRUE);
7492 /*-----------------------------------------------------------------*/
7493 /* genGenPointerSet - set value from generic pointer space */
7494 /*-----------------------------------------------------------------*/
7495 static void genGenPointerSet (operand *right,
7496 operand *result, iCode *ic)
7499 link *retype = getSpec(operandType(right));
7501 aopOp(result,ic,FALSE, TRUE);
7503 /* if the operand is already in dptr
7504 then we do nothing else we move the value to dptr */
7505 if (AOP_TYPE(result) != AOP_STR) {
7506 _startLazyDPSEvaluation();
7507 /* if this is remateriazable */
7508 if (AOP_TYPE(result) == AOP_IMMD) {
7509 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7510 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7512 else { /* we need to get it byte by byte */
7513 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7514 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7515 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7516 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7518 _endLazyDPSEvaluation();
7520 /* so dptr know contains the address */
7521 freeAsmop(result,NULL,ic,TRUE);
7522 aopOp(right,ic,FALSE, TRUE);
7524 /* if bit then unpack */
7525 if (IS_BITVAR(retype))
7526 genPackBits(retype,right,"dptr",GPOINTER);
7528 size = AOP_SIZE(right);
7532 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7534 emitcode("lcall","__gptrput");
7536 emitcode("inc","dptr");
7540 freeAsmop(right,NULL,ic,TRUE);
7543 /*-----------------------------------------------------------------*/
7544 /* genPointerSet - stores the value into a pointer location */
7545 /*-----------------------------------------------------------------*/
7546 static void genPointerSet (iCode *ic)
7548 operand *right, *result ;
7552 D(emitcode(";", "genPointerSet "););
7554 right = IC_RIGHT(ic);
7555 result = IC_RESULT(ic) ;
7557 /* depending on the type of pointer we need to
7558 move it to the correct pointer register */
7559 type = operandType(result);
7560 etype = getSpec(type);
7561 /* if left is of type of pointer then it is simple */
7562 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7563 p_type = DCL_TYPE(type);
7566 /* we have to go by the storage class */
7567 p_type = PTR_TYPE(SPEC_OCLS(etype));
7569 /* if (SPEC_OCLS(etype)->codesp ) { */
7570 /* p_type = CPOINTER ; */
7573 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7574 /* p_type = FPOINTER ; */
7576 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7577 /* p_type = PPOINTER ; */
7579 /* if (SPEC_OCLS(etype) == idata ) */
7580 /* p_type = IPOINTER ; */
7582 /* p_type = POINTER ; */
7585 /* now that we have the pointer type we assign
7586 the pointer values */
7591 genNearPointerSet (right,result,ic);
7595 genPagedPointerSet (right,result,ic);
7599 genFarPointerSet (right,result,ic);
7603 genGenPointerSet (right,result,ic);
7609 /*-----------------------------------------------------------------*/
7610 /* genIfx - generate code for Ifx statement */
7611 /*-----------------------------------------------------------------*/
7612 static void genIfx (iCode *ic, iCode *popIc)
7614 operand *cond = IC_COND(ic);
7617 D(emitcode(";", "genIfx "););
7619 aopOp(cond,ic,FALSE, FALSE);
7621 /* get the value into acc */
7622 if (AOP_TYPE(cond) != AOP_CRY)
7626 /* the result is now in the accumulator */
7627 freeAsmop(cond,NULL,ic,TRUE);
7629 /* if there was something to be popped then do it */
7633 /* if the condition is a bit variable */
7634 if (isbit && IS_ITEMP(cond) &&
7636 genIfxJump(ic,SPIL_LOC(cond)->rname);
7638 if (isbit && !IS_ITEMP(cond))
7639 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7646 /*-----------------------------------------------------------------*/
7647 /* genAddrOf - generates code for address of */
7648 /*-----------------------------------------------------------------*/
7649 static void genAddrOf (iCode *ic)
7651 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7654 D(emitcode(";", "genAddrOf "););
7656 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7658 /* if the operand is on the stack then we
7659 need to get the stack offset of this
7662 /* if it has an offset then we need to compute
7665 emitcode("mov","a,_bp");
7666 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7667 aopPut(AOP(IC_RESULT(ic)),"a",0);
7669 /* we can just move _bp */
7670 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7672 /* fill the result with zero */
7673 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7676 if (options.stack10bit && size < (FPTRSIZE - 1))
7679 "*** warning: pointer to stack var truncated.\n");
7686 if (options.stack10bit && offset == 2)
7688 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7692 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7699 /* object not on stack then we need the name */
7700 size = AOP_SIZE(IC_RESULT(ic));
7704 char s[SDCC_NAME_MAX];
7706 sprintf(s,"#(%s >> %d)",
7710 sprintf(s,"#%s",sym->rname);
7711 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7715 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7719 /*-----------------------------------------------------------------*/
7720 /* genFarFarAssign - assignment when both are in far space */
7721 /*-----------------------------------------------------------------*/
7722 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7724 int size = AOP_SIZE(right);
7731 /* This is a net loss for size == 1, but a big gain
7734 D(emitcode(";", "genFarFarAssign (improved)"););
7736 aopOp(result,ic,TRUE, TRUE);
7738 _startLazyDPSEvaluation();
7742 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7746 _endLazyDPSEvaluation();
7747 freeAsmop(result,NULL,ic,FALSE);
7748 freeAsmop(right,NULL,ic,FALSE);
7753 D(emitcode(";", "genFarFarAssign "););
7755 /* first push the right side on to the stack */
7756 _startLazyDPSEvaluation();
7758 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7760 emitcode ("push","acc");
7763 freeAsmop(right,NULL,ic,FALSE);
7764 /* now assign DPTR to result */
7765 aopOp(result,ic,FALSE, FALSE);
7766 size = AOP_SIZE(result);
7768 emitcode ("pop","acc");
7769 aopPut(AOP(result),"a",--offset);
7771 freeAsmop(result,NULL,ic,FALSE);
7772 _endLazyDPSEvaluation();
7776 /*-----------------------------------------------------------------*/
7777 /* genAssign - generate code for assignment */
7778 /*-----------------------------------------------------------------*/
7779 static void genAssign (iCode *ic)
7781 operand *result, *right;
7783 unsigned long lit = 0L;
7785 D(emitcode(";", "genAssign "););
7787 result = IC_RESULT(ic);
7788 right = IC_RIGHT(ic) ;
7790 /* if they are the same */
7791 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7794 aopOp(right,ic,FALSE, FALSE);
7796 emitcode(";", "genAssign: resultIsFar = %s",
7797 isOperandInFarSpace(result) ?
7800 /* special case both in far space */
7801 if ((AOP_TYPE(right) == AOP_DPTR ||
7802 AOP_TYPE(right) == AOP_DPTR2) &&
7803 /* IS_TRUE_SYMOP(result) && */
7804 isOperandInFarSpace(result)) {
7806 genFarFarAssign (result,right,ic);
7810 aopOp(result,ic,TRUE, FALSE);
7812 /* if they are the same registers */
7813 if (sameRegs(AOP(right),AOP(result)))
7816 /* if the result is a bit */
7817 if (AOP_TYPE(result) == AOP_CRY) {
7819 /* if the right size is a literal then
7820 we know what the value is */
7821 if (AOP_TYPE(right) == AOP_LIT) {
7822 if (((int) operandLitValue(right)))
7823 aopPut(AOP(result),one,0);
7825 aopPut(AOP(result),zero,0);
7829 /* the right is also a bit variable */
7830 if (AOP_TYPE(right) == AOP_CRY) {
7831 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7832 aopPut(AOP(result),"c",0);
7838 aopPut(AOP(result),"a",0);
7842 /* bit variables done */
7844 size = AOP_SIZE(result);
7846 if(AOP_TYPE(right) == AOP_LIT)
7847 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7850 (AOP_TYPE(result) != AOP_REG) &&
7851 (AOP_TYPE(right) == AOP_LIT) &&
7852 !IS_FLOAT(operandType(right))
7853 #ifndef LAZY_DPS_OPT
7859 D(emitcode(";", "Kevin's better literal load code"););
7860 _startLazyDPSEvaluation();
7861 while (size && ((unsigned int)((lit >> (offset*8)) & 0xff) != 0))
7864 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
7869 /* And now fill the rest with zeros. */
7872 emitcode("clr","a");
7876 aopPut(AOP(result), "a", offset++);
7878 _endLazyDPSEvaluation();
7880 emitcode("clr","a");
7882 _startLazyDPSEvaluation();
7885 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7886 aopPut(AOP(result),"a",size);
7889 aopGet(AOP(right),size,FALSE,FALSE,FALSE),
7892 _endLazyDPSEvaluation();
7897 _startLazyDPSEvaluation();
7901 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7905 _endLazyDPSEvaluation();
7909 freeAsmop (right,NULL,ic,FALSE);
7910 freeAsmop (result,NULL,ic,TRUE);
7913 /*-----------------------------------------------------------------*/
7914 /* genJumpTab - generates code for jump table */
7915 /*-----------------------------------------------------------------*/
7916 static void genJumpTab (iCode *ic)
7921 D(emitcode(";", "genJumpTab "););
7923 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7924 /* get the condition into accumulator */
7925 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
7927 /* multiply by four! */
7928 emitcode("add","a,acc");
7929 emitcode("add","a,acc");
7930 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7932 jtab = newiTempLabel(NULL);
7933 emitcode("mov","dptr,#%05d$",jtab->key+100);
7934 emitcode("jmp","@a+dptr");
7935 emitcode("","%05d$:",jtab->key+100);
7936 /* now generate the jump labels */
7937 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7938 jtab = setNextItem(IC_JTLABELS(ic)))
7939 emitcode("ljmp","%05d$",jtab->key+100);
7943 /*-----------------------------------------------------------------*/
7944 /* genCast - gen code for casting */
7945 /*-----------------------------------------------------------------*/
7946 static void genCast (iCode *ic)
7948 operand *result = IC_RESULT(ic);
7949 link *ctype = operandType(IC_LEFT(ic));
7950 link *rtype = operandType(IC_RIGHT(ic));
7951 operand *right = IC_RIGHT(ic);
7954 D(emitcode(";", "genCast "););
7956 /* if they are equivalent then do nothing */
7957 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7960 aopOp(right,ic,FALSE, FALSE) ;
7961 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
7963 /* if the result is a bit */
7964 if (AOP_TYPE(result) == AOP_CRY) {
7965 /* if the right size is a literal then
7966 we know what the value is */
7967 if (AOP_TYPE(right) == AOP_LIT) {
7968 if (((int) operandLitValue(right)))
7969 aopPut(AOP(result),one,0);
7971 aopPut(AOP(result),zero,0);
7976 /* the right is also a bit variable */
7977 if (AOP_TYPE(right) == AOP_CRY) {
7978 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7979 aopPut(AOP(result),"c",0);
7985 aopPut(AOP(result),"a",0);
7989 /* if they are the same size : or less */
7990 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7992 /* if they are in the same place */
7993 if (sameRegs(AOP(right),AOP(result)))
7996 /* if they in different places then copy */
7997 size = AOP_SIZE(result);
7999 _startLazyDPSEvaluation();
8002 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8006 _endLazyDPSEvaluation();
8011 /* if the result is of type pointer */
8012 if (IS_PTR(ctype)) {
8015 link *type = operandType(right);
8017 /* pointer to generic pointer */
8018 if (IS_GENPTR(ctype)) {
8023 p_type = DCL_TYPE(type);
8027 #if OLD_CAST_BEHAVIOR
8028 /* KV: we are converting a non-pointer type to
8029 * a generic pointer. This (ifdef'd out) code
8030 * says that the resulting generic pointer
8031 * should have the same class as the storage
8032 * location of the non-pointer variable.
8034 * For example, converting an int (which happens
8035 * to be stored in DATA space) to a pointer results
8036 * in a DATA generic pointer; if the original int
8037 * in XDATA space, so will be the resulting pointer.
8039 * I don't like that behavior, and thus this change:
8040 * all such conversions will be forced to XDATA and
8041 * throw a warning. If you want some non-XDATA
8042 * type, or you want to suppress the warning, you
8043 * must go through an intermediate cast, like so:
8045 * char _generic *gp = (char _xdata *)(intVar);
8047 link *etype = getSpec(type);
8049 /* we have to go by the storage class */
8050 if (SPEC_OCLS(etype) != generic)
8052 p_type = PTR_TYPE(SPEC_OCLS(etype));
8057 /* Converting unknown class (i.e. register variable)
8058 * to generic pointer. This is not good, but
8059 * we'll make a guess (and throw a warning).
8062 werror(W_INT_TO_GEN_PTR_CAST);
8066 /* the first two bytes are known */
8067 size = GPTRSIZE - 1;
8069 _startLazyDPSEvaluation();
8072 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8076 _endLazyDPSEvaluation();
8078 /* the last byte depending on type */
8095 /* this should never happen */
8096 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8097 "got unknown pointer type");
8100 aopPut(AOP(result),l, GPTRSIZE - 1);
8104 /* just copy the pointers */
8105 size = AOP_SIZE(result);
8107 _startLazyDPSEvaluation();
8110 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8114 _endLazyDPSEvaluation();
8118 /* so we now know that the size of destination is greater
8119 than the size of the source */
8120 /* we move to result for the size of source */
8121 size = AOP_SIZE(right);
8123 _startLazyDPSEvaluation();
8126 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8130 _endLazyDPSEvaluation();
8132 /* now depending on the sign of the source && destination */
8133 size = AOP_SIZE(result) - AOP_SIZE(right);
8134 /* if unsigned or not an integral type */
8135 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
8137 aopPut(AOP(result),zero,offset++);
8139 /* we need to extend the sign :{ */
8140 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8143 emitcode("rlc","a");
8144 emitcode("subb","a,acc");
8146 aopPut(AOP(result),"a",offset++);
8149 /* we are done hurray !!!! */
8152 freeAsmop(right,NULL,ic,TRUE);
8153 freeAsmop(result,NULL,ic,TRUE);
8157 /*-----------------------------------------------------------------*/
8158 /* genDjnz - generate decrement & jump if not zero instrucion */
8159 /*-----------------------------------------------------------------*/
8160 static int genDjnz (iCode *ic, iCode *ifx)
8166 /* if the if condition has a false label
8167 then we cannot save */
8171 /* if the minus is not of the form
8173 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8174 !IS_OP_LITERAL(IC_RIGHT(ic)))
8177 if (operandLitValue(IC_RIGHT(ic)) != 1)
8180 /* if the size of this greater than one then no
8182 if (getSize(operandType(IC_RESULT(ic))) > 1)
8185 /* otherwise we can save BIG */
8186 lbl = newiTempLabel(NULL);
8187 lbl1= newiTempLabel(NULL);
8189 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8191 if (IS_AOP_PREG(IC_RESULT(ic))) {
8192 emitcode("dec","%s",
8193 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8194 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8195 emitcode("jnz","%05d$",lbl->key+100);
8197 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8200 emitcode ("sjmp","%05d$",lbl1->key+100);
8201 emitcode ("","%05d$:",lbl->key+100);
8202 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8203 emitcode ("","%05d$:",lbl1->key+100);
8205 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8210 /*-----------------------------------------------------------------*/
8211 /* genReceive - generate code for a receive iCode */
8212 /*-----------------------------------------------------------------*/
8213 static void genReceive (iCode *ic)
8216 D(emitcode(";", "genReceive "););
8218 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8219 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8220 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8221 int size = getSize(operandType(IC_RESULT(ic)));
8222 int offset = fReturnSize_390 - size;
8224 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8225 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8228 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8229 size = AOP_SIZE(IC_RESULT(ic));
8232 emitcode ("pop","acc");
8233 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8238 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8240 assignResultValue(IC_RESULT(ic));
8243 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8246 /*-----------------------------------------------------------------*/
8247 /* gen390Code - generate code for 8051 based controllers */
8248 /*-----------------------------------------------------------------*/
8249 void gen390Code (iCode *lic)
8254 lineHead = lineCurr = NULL;
8256 /* print the allocation information */
8258 printAllocInfo( currFunc, codeOutFile);
8259 /* if debug information required */
8260 /* if (options.debug && currFunc) { */
8262 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8264 if (IS_STATIC(currFunc->etype))
8265 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8267 emitcode("","G$%s$0$0 ==.",currFunc->name);
8270 /* stack pointer name */
8271 if (options.useXstack)
8277 for (ic = lic ; ic ; ic = ic->next ) {
8279 if ( cln != ic->lineno ) {
8280 if ( options.debug ) {
8282 emitcode("","C$%s$%d$%d$%d ==.",
8283 ic->filename,ic->lineno,
8284 ic->level,ic->block);
8287 emitcode(";","%s %d",ic->filename,ic->lineno);
8290 /* if the result is marked as
8291 spilt and rematerializable or code for
8292 this has already been generated then
8294 if (resultRemat(ic) || ic->generated )
8297 /* depending on the operation */
8316 /* IPOP happens only when trying to restore a
8317 spilt live range, if there is an ifx statement
8318 following this pop then the if statement might
8319 be using some of the registers being popped which
8320 would destory the contents of the register so
8321 we need to check for this condition and handle it */
8323 ic->next->op == IFX &&
8324 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8325 genIfx (ic->next,ic);
8343 genEndFunction (ic);
8363 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8380 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8384 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8391 /* note these two are xlated by algebraic equivalence
8392 during parsing SDCC.y */
8393 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8394 "got '>=' or '<=' shouldn't have come here");
8398 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8410 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8414 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8418 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8445 case GET_VALUE_AT_ADDRESS:
8450 if (POINTER_SET(ic))
8477 addSet(&_G.sendSet,ic);
8482 /* piCode(ic,stdout); */
8488 /* now we are ready to call the
8489 peep hole optimizer */
8490 if (!options.nopeep)
8491 peepHole (&lineHead);
8493 /* now do the actual printing */
8494 printLine (lineHead,codeOutFile);