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 -------------------------------------------------------------------------*/
39 #include "SDCCglobl.h"
42 #ifdef HAVE_SYS_ISA_DEFS_H
43 #include <sys/isa_defs.h>
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
55 char *aopLiteral (value *val, int offset);
61 /* this is the down and dirty file with all kinds of
62 kludgy & hacky stuff. This is what it is all about
63 CODE GENERATION for a specific MCU . some of the
64 routines may be reusable, will have to see */
66 static char *zero = "#0x00";
67 static char *one = "#0x01";
72 unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
73 static char *fReturn[] = {"dpl","dph","dpx", "b","a" };
74 static char *accUse[] = {"a","b"};
76 static short rbank = -1;
88 static void saverbank (int, iCode *,bool);
90 #define RESULTONSTACK(x) \
91 (IC_RESULT(x) && IC_RESULT(x)->aop && \
92 IC_RESULT(x)->aop->type == AOP_STK )
94 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
95 #define MOVA(x) { char *_mova_tmp = strdup(x); \
96 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
98 emitcode("mov","a,%s",_mova_tmp); \
102 #define CLRC emitcode("clr","c")
103 #define SETC emitcode("setb","c")
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
108 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
109 0xE0, 0xC0, 0x80, 0x00};
110 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
111 0x07, 0x03, 0x01, 0x00};
118 /*-----------------------------------------------------------------*/
119 /* emitcode - writes the code into a file : for now it is simple */
120 /*-----------------------------------------------------------------*/
121 static void emitcode (char *inst,char *fmt, ...)
124 char lb[MAX_INLINEASM];
131 sprintf(lb,"%s\t",inst);
133 sprintf(lb,"%s",inst);
134 vsprintf(lb+(strlen(lb)),fmt,ap);
138 while (isspace(*lbp)) lbp++;
141 lineCurr = (lineCurr ?
142 connectLine(lineCurr,newLineNode(lb)) :
143 (lineHead = newLineNode(lb)));
144 lineCurr->isInline = _G.inLine;
145 lineCurr->isDebug = _G.debugLine;
149 /*-----------------------------------------------------------------*/
150 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
151 /*-----------------------------------------------------------------*/
152 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
154 bool r0iu = FALSE , r1iu = FALSE;
155 bool r0ou = FALSE , r1ou = FALSE;
157 /* the logic: if r0 & r1 used in the instruction
158 then we are in trouble otherwise */
160 /* first check if r0 & r1 are used by this
161 instruction, in which case we are in trouble */
162 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
163 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
168 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
169 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
171 /* if no usage of r0 then return it */
172 if (!r0iu && !r0ou) {
173 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
174 (*aopp)->type = AOP_R0;
176 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
179 /* if no usage of r1 then return it */
180 if (!r1iu && !r1ou) {
181 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
182 (*aopp)->type = AOP_R1;
184 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R1_IDX);
187 /* now we know they both have usage */
188 /* if r0 not used in this instruction */
190 /* push it if not already pushed */
192 emitcode ("push","%s",
193 ds390_regWithIdx(R0_IDX)->dname);
197 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
198 (*aopp)->type = AOP_R0;
200 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
203 /* if r1 not used then */
206 /* push it if not already pushed */
208 emitcode ("push","%s",
209 ds390_regWithIdx(R1_IDX)->dname);
213 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
214 (*aopp)->type = AOP_R1;
215 return ds390_regWithIdx(R1_IDX);
219 /* I said end of world but not quite end of world yet */
220 /* if this is a result then we can push it on the stack*/
222 (*aopp)->type = AOP_STK;
227 /* other wise this is true end of the world */
228 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
229 "getFreePtr should never reach here");
233 /*-----------------------------------------------------------------*/
234 /* newAsmop - creates a new asmOp */
235 /*-----------------------------------------------------------------*/
236 static asmop *newAsmop (short type)
240 aop = Safe_calloc(1,sizeof(asmop));
245 static int _currentDPS; /* Current processor DPS. */
246 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
247 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
249 /*-----------------------------------------------------------------*/
250 /* genSetDPTR: generate code to select which DPTR is in use (zero */
251 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
252 /* alternate DPTR (DPL1/DPH1/DPX1). */
253 /*-----------------------------------------------------------------*/
254 static void genSetDPTR(int n)
257 /* If we are doing lazy evaluation, simply note the desired
258 * change, but don't emit any code yet.
268 emitcode("mov", "dps, #0x00");
272 emitcode("mov", "dps, #0x01");
276 /*-----------------------------------------------------------------*/
277 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation*/
279 /* Any code that operates on DPTR (NB: not on the individual */
280 /* components, like DPH) *must* call _flushLazyDPS() before using */
281 /* DPTR within a lazy DPS evaluation block. */
283 /* Note that aopPut and aopGet already contain the proper calls to */
284 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
285 /* DPS evaluation block. */
287 /* Also, _flushLazyDPS must be called before any flow control */
288 /* operations that could potentially branch out of the block. */
290 /* Lazy DPS evaluation is simply an optimization (though an */
291 /* important one), so if in doubt, leave it out. */
292 /*-----------------------------------------------------------------*/
293 static void _startLazyDPSEvaluation(void)
300 /*-----------------------------------------------------------------*/
301 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
302 /* desired one. Call before using DPTR within a lazy DPS evaluation*/
304 /*-----------------------------------------------------------------*/
305 static void _flushLazyDPS(void)
313 if (_desiredDPS != _currentDPS)
317 emitcode("inc", "dps");
321 emitcode("dec", "dps");
323 _currentDPS = _desiredDPS;
327 /*-----------------------------------------------------------------*/
328 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
330 /* Forces us back to the safe state (standard DPTR selected). */
331 /*-----------------------------------------------------------------*/
332 static void _endLazyDPSEvaluation(void)
346 /*-----------------------------------------------------------------*/
347 /* pointerCode - returns the code for a pointer type */
348 /*-----------------------------------------------------------------*/
349 static int pointerCode (sym_link *etype)
352 return PTR_TYPE(SPEC_OCLS(etype));
356 /*-----------------------------------------------------------------*/
357 /* aopForSym - for a true symbol */
358 /*-----------------------------------------------------------------*/
359 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
362 memmap *space= SPEC_OCLS(sym->etype);
364 /* if already has one */
368 /* assign depending on the storage class */
369 /* if it is on the stack or indirectly addressable */
370 /* space we need to assign either r0 or r1 to it */
371 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
372 sym->aop = aop = newAsmop(0);
373 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
374 aop->size = getSize(sym->type);
376 /* now assign the address of the variable to
377 the pointer register */
378 if (aop->type != AOP_STK) {
382 emitcode("push","acc");
384 emitcode("mov","a,_bp");
385 emitcode("add","a,#0x%02x",
387 ((char)(sym->stack - _G.nRegsSaved )) :
388 ((char)sym->stack)) & 0xff);
389 emitcode("mov","%s,a",
390 aop->aopu.aop_ptr->name);
393 emitcode("pop","acc");
395 emitcode("mov","%s,#%s",
396 aop->aopu.aop_ptr->name,
398 aop->paged = space->paged;
400 aop->aopu.aop_stk = sym->stack;
404 if (sym->onStack && options.stack10bit)
406 /* It's on the 10 bit stack, which is located in
411 emitcode("push","acc");
413 emitcode("mov","a,_bp");
414 emitcode("add","a,#0x%02x",
416 ((char)(sym->stack - _G.nRegsSaved )) :
417 ((char)sym->stack)) & 0xff);
422 emitcode ("mov","dpx1,#0x40");
423 emitcode ("mov","dph1,#0x00");
424 emitcode ("mov","dpl1, a");
429 emitcode ("mov","dpx,#0x40");
430 emitcode ("mov","dph,#0x00");
431 emitcode ("mov","dpl, a");
435 emitcode("pop","acc");
437 sym->aop = aop = newAsmop((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
438 aop->size = getSize(sym->type);
442 /* if in bit space */
443 if (IN_BITSPACE(space)) {
444 sym->aop = aop = newAsmop (AOP_CRY);
445 aop->aopu.aop_dir = sym->rname ;
446 aop->size = getSize(sym->type);
449 /* if it is in direct space */
450 if (IN_DIRSPACE(space)) {
451 sym->aop = aop = newAsmop (AOP_DIR);
452 aop->aopu.aop_dir = sym->rname ;
453 aop->size = getSize(sym->type);
457 /* special case for a function */
458 if (IS_FUNC(sym->type)) {
459 sym->aop = aop = newAsmop(AOP_IMMD);
460 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
461 strcpy(aop->aopu.aop_immd,sym->rname);
462 aop->size = FPTRSIZE;
466 /* only remaining is far space */
467 /* in which case DPTR gets the address */
468 sym->aop = aop = newAsmop((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
473 emitcode ("mov","dptr,#%s", sym->rname);
478 emitcode ("mov","dptr,#%s", sym->rname);
480 aop->size = getSize(sym->type);
482 /* if it is in code space */
483 if (IN_CODESPACE(space))
489 /*-----------------------------------------------------------------*/
490 /* aopForRemat - rematerialzes an object */
491 /*-----------------------------------------------------------------*/
492 static asmop *aopForRemat (symbol *sym)
494 iCode *ic = sym->rematiCode;
495 asmop *aop = newAsmop(AOP_IMMD);
501 val += (int) operandLitValue(IC_RIGHT(ic));
502 else if (ic->op == '-')
503 val -= (int) operandLitValue(IC_RIGHT(ic));
507 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
511 sprintf(buffer,"(%s %c 0x%04x)",
512 OP_SYMBOL(IC_LEFT(ic))->rname,
513 val >= 0 ? '+' : '-',
516 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
518 aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
519 strcpy(aop->aopu.aop_immd,buffer);
523 /*-----------------------------------------------------------------*/
524 /* regsInCommon - two operands have some registers in common */
525 /*-----------------------------------------------------------------*/
526 static bool regsInCommon (operand *op1, operand *op2)
531 /* if they have registers in common */
532 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
535 sym1 = OP_SYMBOL(op1);
536 sym2 = OP_SYMBOL(op2);
538 if (sym1->nRegs == 0 || sym2->nRegs == 0)
541 for (i = 0 ; i < sym1->nRegs ; i++) {
546 for (j = 0 ; j < sym2->nRegs ;j++ ) {
550 if (sym2->regs[j] == sym1->regs[i])
558 /*-----------------------------------------------------------------*/
559 /* operandsEqu - equivalent */
560 /*-----------------------------------------------------------------*/
561 static bool operandsEqu ( operand *op1, operand *op2)
565 /* if they not symbols */
566 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
569 sym1 = OP_SYMBOL(op1);
570 sym2 = OP_SYMBOL(op2);
572 /* if both are itemps & one is spilt
573 and the other is not then false */
574 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
575 sym1->isspilt != sym2->isspilt )
578 /* if they are the same */
582 if (strcmp(sym1->rname,sym2->rname) == 0)
586 /* if left is a tmp & right is not */
590 (sym1->usl.spillLoc == sym2))
597 (sym2->usl.spillLoc == sym1))
603 /*-----------------------------------------------------------------*/
604 /* sameRegs - two asmops have the same registers */
605 /*-----------------------------------------------------------------*/
606 static bool sameRegs (asmop *aop1, asmop *aop2 )
612 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
619 if (aop1->type != AOP_REG ||
620 aop2->type != AOP_REG )
623 if (aop1->size != aop2->size )
626 for (i = 0 ; i < aop1->size ; i++ )
627 if (aop1->aopu.aop_reg[i] !=
628 aop2->aopu.aop_reg[i] )
634 /*-----------------------------------------------------------------*/
635 /* aopOp - allocates an asmop for an operand : */
636 /*-----------------------------------------------------------------*/
637 static void aopOp (operand *op, iCode *ic, bool result, bool useDP2)
646 /* if this a literal */
647 if (IS_OP_LITERAL(op)) {
648 op->aop = aop = newAsmop(AOP_LIT);
649 aop->aopu.aop_lit = op->operand.valOperand;
650 aop->size = getSize(operandType(op));
654 /* if already has a asmop then continue */
658 /* if the underlying symbol has a aop */
659 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
660 op->aop = OP_SYMBOL(op)->aop;
664 /* if this is a true symbol */
665 if (IS_TRUE_SYMOP(op)) {
666 op->aop = aopForSym(ic,OP_SYMBOL(op),result, useDP2);
670 /* this is a temporary : this has
676 e) can be a return use only */
681 /* if the type is a conditional */
682 if (sym->regType == REG_CND) {
683 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
688 /* if it is spilt then two situations
690 b) has a spill location */
691 if (sym->isspilt || sym->nRegs == 0) {
693 /* rematerialize it NOW */
695 sym->aop = op->aop = aop =
697 aop->size = getSize(sym->type);
703 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
704 aop->size = getSize(sym->type);
705 for ( i = 0 ; i < 2 ; i++ )
706 aop->aopu.aop_str[i] = accUse[i];
715 /* a AOP_STR uses DPTR, but DPTR is already in use;
718 fprintf(stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
721 aop = op->aop = sym->aop = newAsmop(AOP_STR);
722 aop->size = getSize(sym->type);
723 for ( i = 0 ; i < (int) fReturnSize_390 ; i++ )
724 aop->aopu.aop_str[i] = fReturn[i];
728 /* else spill location */
729 sym->aop = op->aop = aop =
730 aopForSym(ic,sym->usl.spillLoc,result, useDP2);
731 aop->size = getSize(sym->type);
735 /* must be in a register */
736 sym->aop = op->aop = aop = newAsmop(AOP_REG);
737 aop->size = sym->nRegs;
738 for ( i = 0 ; i < sym->nRegs ;i++)
739 aop->aopu.aop_reg[i] = sym->regs[i];
742 /*-----------------------------------------------------------------*/
743 /* freeAsmop - free up the asmop given to an operand */
744 /*----------------------------------------------------------------*/
745 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
762 /* depending on the asmop type only three cases need work AOP_RO
763 , AOP_R1 && AOP_STK */
768 emitcode ("pop","ar0");
772 bitVectUnSetBit(ic->rUsed,R0_IDX);
778 emitcode ("pop","ar1");
782 bitVectUnSetBit(ic->rUsed,R1_IDX);
788 int stk = aop->aopu.aop_stk + aop->size;
789 bitVectUnSetBit(ic->rUsed,R0_IDX);
790 bitVectUnSetBit(ic->rUsed,R1_IDX);
792 getFreePtr(ic,&aop,FALSE);
794 if (options.stack10bit)
796 /* I'm not sure what to do here yet... */
799 "*** Warning: probably generating bad code for "
800 "10 bit stack mode.\n");
804 emitcode ("mov","a,_bp");
805 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
806 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
808 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
812 emitcode("pop","acc");
813 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
815 emitcode("dec","%s",aop->aopu.aop_ptr->name);
818 freeAsmop(op,NULL,ic,TRUE);
820 emitcode("pop","ar0");
825 emitcode("pop","ar1");
832 /* all other cases just dealloc */
836 OP_SYMBOL(op)->aop = NULL;
837 /* if the symbol has a spill */
839 SPIL_LOC(op)->aop = NULL;
844 /*------------------------------------------------------------------*/
845 /* aopGet - for fetching value of the aop */
847 /* Set canClobberACC if you are aure it is OK to clobber the value */
848 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe,*/
849 /* just less efficient. */
850 /*------------------------------------------------------------------*/
852 static char *aopGet (asmop *aop,
861 /* offset is greater than
863 if (offset > (aop->size - 1) &&
864 aop->type != AOP_LIT)
867 /* depending on type */
872 /* if we need to increment it */
873 while (offset > aop->coff) {
874 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
878 while (offset < aop->coff) {
879 emitcode("dec","%s",aop->aopu.aop_ptr->name);
885 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
886 return (dname ? "acc" : "a");
888 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
889 rs = Safe_calloc(1,strlen(s)+1);
896 if (aop->type == AOP_DPTR2)
902 emitcode("xch", "a, ap");
908 while (offset > aop->coff) {
909 emitcode ("inc","dptr");
913 while (offset < aop->coff) {
914 emitcode("lcall","__decdptr");
921 emitcode("movc","a,@a+dptr");
924 emitcode("movx","a,@dptr");
927 if (aop->type == AOP_DPTR2)
933 emitcode("xch", "a, ap");
938 return (dname ? "acc" : "a");
942 sprintf (s,"#%s",aop->aopu.aop_immd);
945 sprintf(s,"#(%s >> %d)",
951 rs = Safe_calloc(1,strlen(s)+1);
957 sprintf(s,"(%s + %d)",
961 sprintf(s,"%s",aop->aopu.aop_dir);
962 rs = Safe_calloc(1,strlen(s)+1);
968 return aop->aopu.aop_reg[offset]->dname;
970 return aop->aopu.aop_reg[offset]->name;
974 emitcode("mov","c,%s",aop->aopu.aop_dir);
975 emitcode("rlc","a") ;
976 return (dname ? "acc" : "a");
979 if (!offset && dname)
981 return aop->aopu.aop_str[offset];
984 return aopLiteral (aop->aopu.aop_lit,offset);
988 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
992 return aop->aopu.aop_str[offset];
996 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
997 "aopget got unsupported aop->type");
1000 /*-----------------------------------------------------------------*/
1001 /* aopPut - puts a string for a aop */
1002 /*-----------------------------------------------------------------*/
1003 static void aopPut (asmop *aop, char *s, int offset)
1008 if (aop->size && offset > ( aop->size - 1)) {
1009 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1010 "aopPut got offset > aop->size");
1014 /* will assign value to value */
1015 /* depending on where it is ofcourse */
1016 switch (aop->type) {
1019 sprintf(d,"(%s + %d)",
1020 aop->aopu.aop_dir,offset);
1022 sprintf(d,"%s",aop->aopu.aop_dir);
1025 emitcode("mov","%s,%s",d,s);
1030 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1031 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1033 strcmp(s,"r0") == 0 ||
1034 strcmp(s,"r1") == 0 ||
1035 strcmp(s,"r2") == 0 ||
1036 strcmp(s,"r3") == 0 ||
1037 strcmp(s,"r4") == 0 ||
1038 strcmp(s,"r5") == 0 ||
1039 strcmp(s,"r6") == 0 ||
1040 strcmp(s,"r7") == 0 )
1041 emitcode("mov","%s,%s",
1042 aop->aopu.aop_reg[offset]->dname,s);
1044 emitcode("mov","%s,%s",
1045 aop->aopu.aop_reg[offset]->name,s);
1052 if (aop->type == AOP_DPTR2)
1059 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1060 "aopPut writting to code space");
1064 while (offset > aop->coff) {
1066 emitcode ("inc","dptr");
1069 while (offset < aop->coff) {
1071 emitcode("lcall","__decdptr");
1076 /* if not in accumulater */
1079 emitcode ("movx","@dptr,a");
1081 if (aop->type == AOP_DPTR2)
1089 while (offset > aop->coff) {
1091 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1093 while (offset < aop->coff) {
1095 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1101 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1106 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1108 if (strcmp(s,"r0") == 0 ||
1109 strcmp(s,"r1") == 0 ||
1110 strcmp(s,"r2") == 0 ||
1111 strcmp(s,"r3") == 0 ||
1112 strcmp(s,"r4") == 0 ||
1113 strcmp(s,"r5") == 0 ||
1114 strcmp(s,"r6") == 0 ||
1115 strcmp(s,"r7") == 0 ) {
1117 sprintf(buffer,"a%s",s);
1118 emitcode("mov","@%s,%s",
1119 aop->aopu.aop_ptr->name,buffer);
1121 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1126 if (strcmp(s,"a") == 0)
1127 emitcode("push","acc");
1129 emitcode("push","%s",s);
1134 /* if bit variable */
1135 if (!aop->aopu.aop_dir) {
1136 emitcode("clr","a");
1137 emitcode("rlc","a");
1140 emitcode("clr","%s",aop->aopu.aop_dir);
1143 emitcode("setb","%s",aop->aopu.aop_dir);
1146 emitcode("mov","%s,c",aop->aopu.aop_dir);
1148 lbl = newiTempLabel(NULL);
1150 if (strcmp(s,"a")) {
1153 emitcode("clr","c");
1154 emitcode("jz","%05d$",lbl->key+100);
1155 emitcode("cpl","c");
1156 emitcode("","%05d$:",lbl->key+100);
1157 emitcode("mov","%s,c",aop->aopu.aop_dir);
1164 if (strcmp(aop->aopu.aop_str[offset],s))
1165 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1170 if (!offset && (strcmp(s,"acc") == 0))
1173 if (strcmp(aop->aopu.aop_str[offset],s))
1174 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1178 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1179 "aopPut got unsupported aop->type");
1186 /*-----------------------------------------------------------------*/
1187 /* reAdjustPreg - points a register back to where it should */
1188 /*-----------------------------------------------------------------*/
1189 static void reAdjustPreg (asmop *aop)
1194 if ((size = aop->size) <= 1)
1197 switch (aop->type) {
1201 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1205 if (aop->type == AOP_DPTR2)
1212 emitcode("lcall","__decdptr");
1215 if (aop->type == AOP_DPTR2)
1225 #define AOP(op) op->aop
1226 #define AOP_TYPE(op) AOP(op)->type
1227 #define AOP_SIZE(op) AOP(op)->size
1228 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1229 AOP_TYPE(x) == AOP_R0))
1231 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1232 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1235 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1236 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1237 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1239 /* Workaround for DS80C390 bug: div ab may return bogus results
1240 * if A is accessed in instruction immediately before the div.
1242 * Will be fixed in B4 rev of processor, Dallas claims.
1245 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1246 if (!AOP_NEEDSACC(RIGHT)) \
1248 /* We can load A first, then B, since \
1249 * B (the RIGHT operand) won't clobber A, \
1250 * thus avoiding touching A right before the div. \
1252 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1253 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1255 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1259 /* Just stuff in a nop after loading A. */ \
1260 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1261 L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \
1263 emitcode("nop", "; workaround for DS80C390 div bug."); \
1266 /*-----------------------------------------------------------------*/
1267 /* genNotFloat - generates not for float operations */
1268 /*-----------------------------------------------------------------*/
1269 static void genNotFloat (operand *op, operand *res)
1275 D(emitcode(";", "genNotFloat "););
1277 /* we will put 127 in the first byte of
1279 aopPut(AOP(res),"#127",0);
1280 size = AOP_SIZE(op) - 1;
1283 _startLazyDPSEvaluation();
1284 l = aopGet(op->aop,offset++,FALSE,FALSE,TRUE);
1288 emitcode("orl","a,%s",
1290 offset++,FALSE,FALSE,FALSE));
1292 _endLazyDPSEvaluation();
1293 tlbl = newiTempLabel(NULL);
1295 tlbl = newiTempLabel(NULL);
1296 aopPut(res->aop,one,1);
1297 emitcode("jz","%05d$",(tlbl->key+100));
1298 aopPut(res->aop,zero,1);
1299 emitcode("","%05d$:",(tlbl->key+100));
1301 size = res->aop->size - 2;
1303 /* put zeros in the rest */
1305 aopPut(res->aop,zero,offset++);
1308 /*-----------------------------------------------------------------*/
1309 /* opIsGptr: returns non-zero if the passed operand is */
1310 /* a generic pointer type. */
1311 /*-----------------------------------------------------------------*/
1312 static int opIsGptr(operand *op)
1314 sym_link *type = operandType(op);
1316 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1323 /*-----------------------------------------------------------------*/
1324 /* getDataSize - get the operand data size */
1325 /*-----------------------------------------------------------------*/
1326 static int getDataSize(operand *op)
1329 size = AOP_SIZE(op);
1330 if (size == GPTRSIZE)
1332 sym_link *type = operandType(op);
1333 if (IS_GENPTR(type))
1335 /* generic pointer; arithmetic operations
1336 * should ignore the high byte (pointer type).
1344 /*-----------------------------------------------------------------*/
1345 /* outAcc - output Acc */
1346 /*-----------------------------------------------------------------*/
1347 static void outAcc(operand *result)
1350 size = getDataSize(result);
1353 aopPut(AOP(result),"a",0);
1356 /* unsigned or positive */
1358 aopPut(AOP(result),zero,offset++);
1363 /*-----------------------------------------------------------------*/
1364 /* outBitC - output a bit C */
1365 /*-----------------------------------------------------------------*/
1366 static void outBitC(operand *result)
1368 /* if the result is bit */
1369 if (AOP_TYPE(result) == AOP_CRY)
1371 aopPut(AOP(result),"c",0);
1375 emitcode("clr","a");
1376 emitcode("rlc","a");
1381 /*-----------------------------------------------------------------*/
1382 /* toBoolean - emit code for orl a,operator(sizeop) */
1383 /*-----------------------------------------------------------------*/
1384 static void toBoolean(operand *oper)
1386 int size = AOP_SIZE(oper) - 1;
1389 /* The generic part of a generic pointer should
1390 * not participate in it's truth value.
1392 * i.e. 0x10000000 is zero.
1396 D(emitcode(";", "toBoolean: generic ptr special case."););
1400 _startLazyDPSEvaluation();
1401 if (AOP_NEEDSACC(oper))
1403 emitcode("push", "b");
1404 emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE,FALSE));
1408 MOVA(aopGet(AOP(oper),0,FALSE,FALSE,TRUE));
1412 if (AOP_NEEDSACC(oper))
1414 emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1418 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE,FALSE));
1421 _endLazyDPSEvaluation();
1423 if (AOP_NEEDSACC(oper))
1425 emitcode("mov", "a,b");
1426 emitcode("pop", "b");
1431 /*-----------------------------------------------------------------*/
1432 /* genNot - generate code for ! operation */
1433 /*-----------------------------------------------------------------*/
1434 static void genNot (iCode *ic)
1437 sym_link *optype = operandType(IC_LEFT(ic));
1439 D(emitcode(";", "genNot "););
1441 /* assign asmOps to operand & result */
1442 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1443 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1445 /* if in bit space then a special case */
1446 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1447 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1448 emitcode("cpl","c");
1449 outBitC(IC_RESULT(ic));
1453 /* if type float then do float */
1454 if (IS_FLOAT(optype)) {
1455 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1459 toBoolean(IC_LEFT(ic));
1461 tlbl = newiTempLabel(NULL);
1462 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1463 emitcode("","%05d$:",tlbl->key+100);
1464 outBitC(IC_RESULT(ic));
1467 /* release the aops */
1468 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1469 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1473 /*-----------------------------------------------------------------*/
1474 /* genCpl - generate code for complement */
1475 /*-----------------------------------------------------------------*/
1476 static void genCpl (iCode *ic)
1481 D(emitcode(";", "genCpl "););
1484 /* assign asmOps to operand & result */
1485 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1486 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1488 /* if both are in bit space then
1490 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1491 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1493 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1494 emitcode("cpl","c");
1495 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1499 size = AOP_SIZE(IC_RESULT(ic));
1500 _startLazyDPSEvaluation();
1502 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1504 emitcode("cpl","a");
1505 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1507 _endLazyDPSEvaluation();
1511 /* release the aops */
1512 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1513 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1516 /*-----------------------------------------------------------------*/
1517 /* genUminusFloat - unary minus for floating points */
1518 /*-----------------------------------------------------------------*/
1519 static void genUminusFloat(operand *op,operand *result)
1521 int size ,offset =0 ;
1523 /* for this we just need to flip the
1524 first it then copy the rest in place */
1525 D(emitcode(";", "genUminusFloat"););
1527 _startLazyDPSEvaluation();
1528 size = AOP_SIZE(op) - 1;
1529 l = aopGet(AOP(op),3,FALSE,FALSE,TRUE);
1532 emitcode("cpl","acc.7");
1533 aopPut(AOP(result),"a",3);
1537 aopGet(AOP(op),offset,FALSE,FALSE,FALSE),
1541 _endLazyDPSEvaluation();
1544 /*-----------------------------------------------------------------*/
1545 /* genUminus - unary minus code generation */
1546 /*-----------------------------------------------------------------*/
1547 static void genUminus (iCode *ic)
1550 sym_link *optype, *rtype;
1552 D(emitcode(";", "genUminus "););
1556 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1557 aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
1559 /* if both in bit space then special
1561 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1562 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1564 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1565 emitcode("cpl","c");
1566 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1570 optype = operandType(IC_LEFT(ic));
1571 rtype = operandType(IC_RESULT(ic));
1573 /* if float then do float stuff */
1574 if (IS_FLOAT(optype)) {
1575 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1579 /* otherwise subtract from zero */
1580 size = AOP_SIZE(IC_LEFT(ic));
1582 _startLazyDPSEvaluation();
1584 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE);
1585 if (!strcmp(l,"a")) {
1588 emitcode("cpl","a");
1589 emitcode("addc", "a,#0");
1593 emitcode("clr","a");
1594 emitcode("subb","a,%s",l);
1596 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1598 _endLazyDPSEvaluation();
1600 /* if any remaining bytes in the result */
1601 /* we just need to propagate the sign */
1602 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1603 emitcode("rlc","a");
1604 emitcode("subb","a,acc");
1606 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1610 /* release the aops */
1611 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1612 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1615 /*-----------------------------------------------------------------*/
1616 /* saveRegisters - will look for a call and save the registers */
1617 /*-----------------------------------------------------------------*/
1618 static void saveRegisters(iCode *lic)
1626 for (ic = lic ; ic ; ic = ic->next)
1627 if (ic->op == CALL || ic->op == PCALL)
1631 fprintf(stderr,"found parameter push with no function call\n");
1635 /* if the registers have been saved already then
1637 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1640 /* find the registers in use at this time
1641 and push them away to safety */
1642 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1646 if (options.useXstack) {
1647 if (bitVectBitValue(rsave,R0_IDX))
1648 emitcode("mov","b,r0");
1649 emitcode("mov","r0,%s",spname);
1650 for (i = 0 ; i < ds390_nRegs ; i++) {
1651 if (bitVectBitValue(rsave,i)) {
1653 emitcode("mov","a,b");
1655 emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
1656 emitcode("movx","@r0,a");
1657 emitcode("inc","r0");
1660 emitcode("mov","%s,r0",spname);
1661 if (bitVectBitValue(rsave,R0_IDX))
1662 emitcode("mov","r0,b");
1664 for (i = 0 ; i < ds390_nRegs ; i++) {
1665 if (bitVectBitValue(rsave,i))
1666 emitcode("push","%s",ds390_regWithIdx(i)->dname);
1669 detype = getSpec(operandType(IC_LEFT(ic)));
1671 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1672 IS_ISR(currFunc->etype) &&
1675 saverbank(SPEC_BANK(detype),ic,TRUE);
1678 /*-----------------------------------------------------------------*/
1679 /* unsaveRegisters - pop the pushed registers */
1680 /*-----------------------------------------------------------------*/
1681 static void unsaveRegisters (iCode *ic)
1685 /* find the registers in use at this time
1686 and push them away to safety */
1687 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1690 if (options.useXstack) {
1691 emitcode("mov","r0,%s",spname);
1692 for (i = ds390_nRegs ; i >= 0 ; i--) {
1693 if (bitVectBitValue(rsave,i)) {
1694 emitcode("dec","r0");
1695 emitcode("movx","a,@r0");
1697 emitcode("mov","b,a");
1699 emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
1703 emitcode("mov","%s,r0",spname);
1704 if (bitVectBitValue(rsave,R0_IDX))
1705 emitcode("mov","r0,b");
1707 for (i = ds390_nRegs ; i >= 0 ; i--) {
1708 if (bitVectBitValue(rsave,i))
1709 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
1715 /*-----------------------------------------------------------------*/
1717 /*-----------------------------------------------------------------*/
1718 static void pushSide(operand * oper, int size)
1721 _startLazyDPSEvaluation();
1723 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE,FALSE);
1724 if (AOP_TYPE(oper) != AOP_REG &&
1725 AOP_TYPE(oper) != AOP_DIR &&
1727 emitcode("mov","a,%s",l);
1728 emitcode("push","acc");
1730 emitcode("push","%s",l);
1732 _endLazyDPSEvaluation();
1735 /*-----------------------------------------------------------------*/
1736 /* assignResultValue - */
1737 /*-----------------------------------------------------------------*/
1738 static void assignResultValue(operand * oper)
1741 int size = AOP_SIZE(oper);
1743 _startLazyDPSEvaluation();
1745 aopPut(AOP(oper),fReturn[offset],offset);
1748 _endLazyDPSEvaluation();
1752 /*-----------------------------------------------------------------*/
1753 /* genXpush - pushes onto the external stack */
1754 /*-----------------------------------------------------------------*/
1755 static void genXpush (iCode *ic)
1757 asmop *aop = newAsmop(0);
1759 int size,offset = 0;
1761 D(emitcode(";", "genXpush "););
1763 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1764 r = getFreePtr(ic,&aop,FALSE);
1767 emitcode("mov","%s,_spx",r->name);
1769 size = AOP_SIZE(IC_LEFT(ic));
1770 _startLazyDPSEvaluation();
1773 char *l = aopGet(AOP(IC_LEFT(ic)),
1774 offset++,FALSE,FALSE,TRUE);
1776 emitcode("movx","@%s,a",r->name);
1777 emitcode("inc","%s",r->name);
1780 _endLazyDPSEvaluation();
1783 emitcode("mov","_spx,%s",r->name);
1785 freeAsmop(NULL,aop,ic,TRUE);
1786 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1789 /*-----------------------------------------------------------------*/
1790 /* genIpush - genrate code for pushing this gets a little complex */
1791 /*-----------------------------------------------------------------*/
1792 static void genIpush (iCode *ic)
1794 int size, offset = 0 ;
1797 D(emitcode(";", "genIpush "););
1800 /* if this is not a parm push : ie. it is spill push
1801 and spill push is always done on the local stack */
1802 if (!ic->parmPush) {
1804 /* and the item is spilt then do nothing */
1805 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1808 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1809 size = AOP_SIZE(IC_LEFT(ic));
1810 /* push it on the stack */
1811 _startLazyDPSEvaluation();
1813 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,TRUE);
1818 emitcode("push","%s",l);
1820 _endLazyDPSEvaluation();
1824 /* this is a paramter push: in this case we call
1825 the routine to find the call and save those
1826 registers that need to be saved */
1829 /* if use external stack then call the external
1830 stack pushing routine */
1831 if (options.useXstack) {
1836 /* then do the push */
1837 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1839 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1840 size = AOP_SIZE(IC_LEFT(ic));
1842 _startLazyDPSEvaluation();
1844 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE,FALSE);
1845 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1846 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1848 emitcode("mov","a,%s",l);
1849 emitcode("push","acc");
1851 emitcode("push","%s",l);
1853 _endLazyDPSEvaluation();
1855 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1858 /*-----------------------------------------------------------------*/
1859 /* genIpop - recover the registers: can happen only for spilling */
1860 /*-----------------------------------------------------------------*/
1861 static void genIpop (iCode *ic)
1865 D(emitcode(";", "genIpop "););
1868 /* if the temp was not pushed then */
1869 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1872 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1873 size = AOP_SIZE(IC_LEFT(ic));
1875 _startLazyDPSEvaluation();
1878 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1881 _endLazyDPSEvaluation();
1883 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1886 /*-----------------------------------------------------------------*/
1887 /* unsaverbank - restores the resgister bank from stack */
1888 /*-----------------------------------------------------------------*/
1889 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1896 if (options.useXstack) {
1898 r = getFreePtr(ic,&aop,FALSE);
1901 emitcode("mov","%s,_spx",r->name);
1902 emitcode("movx","a,@%s",r->name);
1903 emitcode("mov","psw,a");
1904 emitcode("dec","%s",r->name);
1907 emitcode ("pop","psw");
1910 for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
1911 if (options.useXstack) {
1912 emitcode("movx","a,@%s",r->name);
1913 emitcode("mov","(%s+%d),a",
1914 regs390[i].base,8*bank+regs390[i].offset);
1915 emitcode("dec","%s",r->name);
1918 emitcode("pop","(%s+%d)",
1919 regs390[i].base,8*bank+regs390[i].offset);
1922 if (options.useXstack) {
1924 emitcode("mov","_spx,%s",r->name);
1925 freeAsmop(NULL,aop,ic,TRUE);
1930 /*-----------------------------------------------------------------*/
1931 /* saverbank - saves an entire register bank on the stack */
1932 /*-----------------------------------------------------------------*/
1933 static void saverbank (int bank, iCode *ic, bool pushPsw)
1939 if (options.useXstack) {
1942 r = getFreePtr(ic,&aop,FALSE);
1943 emitcode("mov","%s,_spx",r->name);
1947 for (i = 0 ; i < ds390_nRegs ;i++) {
1948 if (options.useXstack) {
1949 emitcode("inc","%s",r->name);
1950 emitcode("mov","a,(%s+%d)",
1951 regs390[i].base,8*bank+regs390[i].offset);
1952 emitcode("movx","@%s,a",r->name);
1954 emitcode("push","(%s+%d)",
1955 regs390[i].base,8*bank+regs390[i].offset);
1959 if (options.useXstack) {
1960 emitcode("mov","a,psw");
1961 emitcode("movx","@%s,a",r->name);
1962 emitcode("inc","%s",r->name);
1963 emitcode("mov","_spx,%s",r->name);
1964 freeAsmop (NULL,aop,ic,TRUE);
1967 emitcode("push","psw");
1969 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1975 /*-----------------------------------------------------------------*/
1976 /* genCall - generates a call statement */
1977 /*-----------------------------------------------------------------*/
1978 static void genCall (iCode *ic)
1982 D(emitcode(";", "genCall "););
1984 /* if caller saves & we have not saved then */
1988 /* if we are calling a function that is not using
1989 the same register bank then we need to save the
1990 destination registers on the stack */
1991 detype = getSpec(operandType(IC_LEFT(ic)));
1993 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1994 IS_ISR(currFunc->etype) &&
1997 saverbank(SPEC_BANK(detype),ic,TRUE);
1999 /* if send set is not empty the assign */
2003 for (sic = setFirstItem(_G.sendSet) ; sic ;
2004 sic = setNextItem(_G.sendSet))
2006 int size, offset = 0;
2008 aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
2009 size = AOP_SIZE(IC_LEFT(sic));
2011 _startLazyDPSEvaluation();
2013 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2014 FALSE, FALSE, TRUE);
2015 if (strcmp(l,fReturn[offset]))
2016 emitcode("mov","%s,%s",
2021 _endLazyDPSEvaluation();
2022 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2027 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2028 OP_SYMBOL(IC_LEFT(ic))->rname :
2029 OP_SYMBOL(IC_LEFT(ic))->name));
2031 /* if we need assign a result value */
2032 if ((IS_ITEMP(IC_RESULT(ic)) &&
2033 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2034 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2035 IS_TRUE_SYMOP(IC_RESULT(ic)) )
2037 if (isOperandInFarSpace(IC_RESULT(ic))
2038 && getSize(operandType(IC_RESULT(ic))) <= 2)
2040 int size = getSize(operandType(IC_RESULT(ic)));
2042 /* Special case for 1 or 2 byte return in far space. */
2043 emitcode(";", "Kevin function call abuse #1");
2048 emitcode("mov", "b,%s", fReturn[1]);
2051 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
2052 aopPut(AOP(IC_RESULT(ic)),"a",0);
2056 aopPut(AOP(IC_RESULT(ic)),"b",1);
2058 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2063 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2066 assignResultValue(IC_RESULT(ic));
2068 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2072 /* adjust the stack for parameters if
2074 if (IC_LEFT(ic)->parmBytes) {
2076 if (IC_LEFT(ic)->parmBytes > 3) {
2077 emitcode("mov","a,%s",spname);
2078 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2079 emitcode("mov","%s,a",spname);
2081 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2082 emitcode("dec","%s",spname);
2086 /* if register bank was saved then pop them */
2088 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2090 /* if we hade saved some registers then unsave them */
2091 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2092 unsaveRegisters (ic);
2097 /*-----------------------------------------------------------------*/
2098 /* genPcall - generates a call by pointer statement */
2099 /*-----------------------------------------------------------------*/
2100 static void genPcall (iCode *ic)
2103 symbol *rlbl = newiTempLabel(NULL);
2105 D(emitcode(";", "genPcall "););
2108 /* if caller saves & we have not saved then */
2112 /* if we are calling a function that is not using
2113 the same register bank then we need to save the
2114 destination registers on the stack */
2115 detype = getSpec(operandType(IC_LEFT(ic)));
2117 IS_ISR(currFunc->etype) &&
2118 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2119 saverbank(SPEC_BANK(detype),ic,TRUE);
2122 /* push the return address on to the stack */
2123 emitcode("mov","a,#%05d$",(rlbl->key+100));
2124 emitcode("push","acc");
2125 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
2126 emitcode("push","acc");
2128 if (options.model == MODEL_FLAT24)
2130 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
2131 emitcode("push","acc");
2134 /* now push the calling address */
2135 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2137 pushSide(IC_LEFT(ic), FPTRSIZE);
2139 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2141 /* if send set is not empty the assign */
2145 for (sic = setFirstItem(_G.sendSet) ; sic ;
2146 sic = setNextItem(_G.sendSet))
2148 int size, offset = 0;
2150 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
2151 size = AOP_SIZE(IC_LEFT(sic));
2152 _startLazyDPSEvaluation();
2155 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2157 if (strcmp(l,fReturn[offset]))
2159 emitcode("mov","%s,%s",
2165 _endLazyDPSEvaluation();
2166 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2172 emitcode("","%05d$:",(rlbl->key+100));
2175 /* if we need assign a result value */
2176 if ((IS_ITEMP(IC_RESULT(ic)) &&
2177 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2178 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2179 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2182 aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
2185 assignResultValue(IC_RESULT(ic));
2187 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2190 /* adjust the stack for parameters if
2192 if (IC_LEFT(ic)->parmBytes) {
2194 if (IC_LEFT(ic)->parmBytes > 3) {
2195 emitcode("mov","a,%s",spname);
2196 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2197 emitcode("mov","%s,a",spname);
2199 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2200 emitcode("dec","%s",spname);
2204 /* if register bank was saved then unsave them */
2206 (SPEC_BANK(currFunc->etype) !=
2208 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2210 /* if we hade saved some registers then
2213 unsaveRegisters (ic);
2217 /*-----------------------------------------------------------------*/
2218 /* resultRemat - result is rematerializable */
2219 /*-----------------------------------------------------------------*/
2220 static int resultRemat (iCode *ic)
2222 if (SKIP_IC(ic) || ic->op == IFX)
2225 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2226 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2227 if (sym->remat && !POINTER_SET(ic))
2234 #if defined(__BORLANDC__) || defined(_MSC_VER)
2235 #define STRCASECMP stricmp
2237 #define STRCASECMP strcasecmp
2240 /*-----------------------------------------------------------------*/
2241 /* inExcludeList - return 1 if the string is in exclude Reg list */
2242 /*-----------------------------------------------------------------*/
2243 static bool inExcludeList(char *s)
2247 if (options.excludeRegs[i] &&
2248 STRCASECMP(options.excludeRegs[i],"none") == 0)
2251 for ( i = 0 ; options.excludeRegs[i]; i++) {
2252 if (options.excludeRegs[i] &&
2253 STRCASECMP(s,options.excludeRegs[i]) == 0)
2259 /*-----------------------------------------------------------------*/
2260 /* genFunction - generated code for function entry */
2261 /*-----------------------------------------------------------------*/
2262 static void genFunction (iCode *ic)
2267 D(emitcode(";", "genFunction "););
2270 /* create the function header */
2271 emitcode(";","-----------------------------------------");
2272 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2273 emitcode(";","-----------------------------------------");
2275 emitcode("","%s:",sym->rname);
2276 fetype = getSpec(operandType(IC_LEFT(ic)));
2278 /* if critical function then turn interrupts off */
2279 if (SPEC_CRTCL(fetype))
2280 emitcode("clr","ea");
2282 /* here we need to generate the equates for the
2283 register bank if required */
2284 if (SPEC_BANK(fetype) != rbank) {
2287 rbank = SPEC_BANK(fetype);
2288 for ( i = 0 ; i < ds390_nRegs ; i++ ) {
2289 if (strcmp(regs390[i].base,"0") == 0)
2290 emitcode("","%s = 0x%02x",
2292 8*rbank+regs390[i].offset);
2294 emitcode ("","%s = %s + 0x%02x",
2297 8*rbank+regs390[i].offset);
2301 /* if this is an interrupt service routine then
2302 save acc, b, dpl, dph */
2303 if (IS_ISR(sym->etype)) {
2305 if (!inExcludeList("acc"))
2306 emitcode ("push","acc");
2307 if (!inExcludeList("b"))
2308 emitcode ("push","b");
2309 if (!inExcludeList("dpl"))
2310 emitcode ("push","dpl");
2311 if (!inExcludeList("dph"))
2312 emitcode ("push","dph");
2313 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2315 emitcode ("push", "dpx");
2316 /* Make sure we're using standard DPTR */
2317 emitcode ("push", "dps");
2318 emitcode ("mov", "dps, #0x00");
2319 if (options.stack10bit)
2321 /* This ISR could conceivably use DPTR2. Better save it. */
2322 emitcode ("push", "dpl1");
2323 emitcode ("push", "dph1");
2324 emitcode ("push", "dpx1");
2325 emitcode ("push", "ap");
2328 /* if this isr has no bank i.e. is going to
2329 run with bank 0 , then we need to save more
2331 if (!SPEC_BANK(sym->etype)) {
2333 /* if this function does not call any other
2334 function then we can be economical and
2335 save only those registers that are used */
2336 if (! sym->hasFcall) {
2339 /* if any registers used */
2340 if (sym->regsUsed) {
2341 /* save the registers used */
2342 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2343 if (bitVectBitValue(sym->regsUsed,i) ||
2344 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2345 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2350 /* this function has a function call cannot
2351 determines register usage so we will have the
2353 saverbank(0,ic,FALSE);
2357 /* if callee-save to be used for this function
2358 then save the registers being used in this function */
2359 if (sym->calleeSave) {
2362 /* if any registers used */
2363 if (sym->regsUsed) {
2364 /* save the registers used */
2365 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2366 if (bitVectBitValue(sym->regsUsed,i) ||
2367 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2368 emitcode("push","%s",ds390_regWithIdx(i)->dname);
2376 /* set the register bank to the desired value */
2377 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2378 emitcode("push","psw");
2379 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2382 if (IS_RENT(sym->etype) || options.stackAuto) {
2384 if (options.useXstack) {
2385 emitcode("mov","r0,%s",spname);
2386 emitcode("mov","a,_bp");
2387 emitcode("movx","@r0,a");
2388 emitcode("inc","%s",spname);
2392 /* set up the stack */
2393 emitcode ("push","_bp"); /* save the callers stack */
2395 emitcode ("mov","_bp,%s",spname);
2398 /* adjust the stack for the function */
2403 werror(W_STACK_OVERFLOW,sym->name);
2405 if (i > 3 && sym->recvSize < 4) {
2407 emitcode ("mov","a,sp");
2408 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2409 emitcode ("mov","sp,a");
2414 emitcode("inc","sp");
2419 emitcode ("mov","a,_spx");
2420 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2421 emitcode ("mov","_spx,a");
2426 /*-----------------------------------------------------------------*/
2427 /* genEndFunction - generates epilogue for functions */
2428 /*-----------------------------------------------------------------*/
2429 static void genEndFunction (iCode *ic)
2431 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2433 D(emitcode(";", "genEndFunction "););
2435 if (IS_RENT(sym->etype) || options.stackAuto)
2437 emitcode ("mov","%s,_bp",spname);
2440 /* if use external stack but some variables were
2441 added to the local stack then decrement the
2443 if (options.useXstack && sym->stack) {
2444 emitcode("mov","a,sp");
2445 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2446 emitcode("mov","sp,a");
2450 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2451 if (options.useXstack) {
2452 emitcode("mov","r0,%s",spname);
2453 emitcode("movx","a,@r0");
2454 emitcode("mov","_bp,a");
2455 emitcode("dec","%s",spname);
2459 emitcode ("pop","_bp");
2463 /* restore the register bank */
2464 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2465 emitcode ("pop","psw");
2467 if (IS_ISR(sym->etype)) {
2469 /* now we need to restore the registers */
2470 /* if this isr has no bank i.e. is going to
2471 run with bank 0 , then we need to save more
2473 if (!SPEC_BANK(sym->etype)) {
2475 /* if this function does not call any other
2476 function then we can be economical and
2477 save only those registers that are used */
2478 if (! sym->hasFcall) {
2481 /* if any registers used */
2482 if (sym->regsUsed) {
2483 /* save the registers used */
2484 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2485 if (bitVectBitValue(sym->regsUsed,i) ||
2486 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2487 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2492 /* this function has a function call cannot
2493 determines register usage so we will have the
2495 unsaverbank(0,ic,FALSE);
2499 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2501 if (options.stack10bit)
2503 emitcode ("pop", "ap");
2504 emitcode ("pop", "dpx1");
2505 emitcode ("pop", "dph1");
2506 emitcode ("pop", "dpl1");
2508 emitcode ("pop", "dps");
2509 emitcode ("pop", "dpx");
2511 if (!inExcludeList("dph"))
2512 emitcode ("pop","dph");
2513 if (!inExcludeList("dpl"))
2514 emitcode ("pop","dpl");
2515 if (!inExcludeList("b"))
2516 emitcode ("pop","b");
2517 if (!inExcludeList("acc"))
2518 emitcode ("pop","acc");
2520 if (SPEC_CRTCL(sym->etype))
2521 emitcode("setb","ea");
2523 /* if debug then send end of function */
2524 /* if (options.debug && currFunc) { */
2527 emitcode("","C$%s$%d$%d$%d ==.",
2528 ic->filename,currFunc->lastLine,
2529 ic->level,ic->block);
2530 if (IS_STATIC(currFunc->etype))
2531 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2533 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2537 emitcode ("reti","");
2540 if (SPEC_CRTCL(sym->etype))
2541 emitcode("setb","ea");
2543 if (sym->calleeSave) {
2546 /* if any registers used */
2547 if (sym->regsUsed) {
2548 /* save the registers used */
2549 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2550 if (bitVectBitValue(sym->regsUsed,i) ||
2551 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2552 emitcode("pop","%s",ds390_regWithIdx(i)->dname);
2558 /* if debug then send end of function */
2561 emitcode("","C$%s$%d$%d$%d ==.",
2562 ic->filename,currFunc->lastLine,
2563 ic->level,ic->block);
2564 if (IS_STATIC(currFunc->etype))
2565 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2567 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2571 emitcode ("ret","");
2576 /*-----------------------------------------------------------------*/
2577 /* genRet - generate code for return statement */
2578 /*-----------------------------------------------------------------*/
2579 static void genRet (iCode *ic)
2581 int size,offset = 0 , pushed = 0;
2583 D(emitcode(";", "genRet "););
2585 /* if we have no return value then
2586 just generate the "ret" */
2590 /* we have something to return then
2591 move the return value into place */
2592 aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
2593 size = AOP_SIZE(IC_LEFT(ic));
2595 _startLazyDPSEvaluation();
2598 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2599 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2601 emitcode("push","%s",l);
2604 l = aopGet(AOP(IC_LEFT(ic)),offset,
2606 if (strcmp(fReturn[offset],l))
2607 emitcode("mov","%s,%s",fReturn[offset++],l);
2610 _endLazyDPSEvaluation();
2615 if (strcmp(fReturn[pushed],"a"))
2616 emitcode("pop",fReturn[pushed]);
2618 emitcode("pop","acc");
2621 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2624 /* generate a jump to the return label
2625 if the next is not the return statement */
2626 if (!(ic->next && ic->next->op == LABEL &&
2627 IC_LABEL(ic->next) == returnLabel))
2629 emitcode("ljmp","%05d$",(returnLabel->key+100));
2633 /*-----------------------------------------------------------------*/
2634 /* genLabel - generates a label */
2635 /*-----------------------------------------------------------------*/
2636 static void genLabel (iCode *ic)
2638 /* special case never generate */
2639 if (IC_LABEL(ic) == entryLabel)
2642 D(emitcode(";", "genLabel "););
2644 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2647 /*-----------------------------------------------------------------*/
2648 /* genGoto - generates a ljmp */
2649 /*-----------------------------------------------------------------*/
2650 static void genGoto (iCode *ic)
2652 D(emitcode(";", "genGoto "););
2653 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2656 /*-----------------------------------------------------------------*/
2657 /* findLabelBackwards: walks back through the iCode chain looking */
2658 /* for the given label. Returns number of iCode instructions */
2659 /* between that label and given ic. */
2660 /* Returns zero if label not found. */
2661 /*-----------------------------------------------------------------*/
2662 static int findLabelBackwards(iCode *ic, int key)
2671 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2673 /* printf("findLabelBackwards = %d\n", count); */
2681 /*-----------------------------------------------------------------*/
2682 /* genPlusIncr :- does addition with increment if possible */
2683 /*-----------------------------------------------------------------*/
2684 static bool genPlusIncr (iCode *ic)
2686 unsigned int icount ;
2687 unsigned int size = getDataSize(IC_RESULT(ic));
2689 /* will try to generate an increment */
2690 /* if the right side is not a literal
2692 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2695 /* if the literal value of the right hand side
2696 is greater than 4 then it is not worth it */
2697 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2700 /* if increment 16 bits in register */
2702 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2703 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2704 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2711 /* If the next instruction is a goto and the goto target
2712 * is <= 5 instructions previous to this, we can generate
2713 * jumps straight to that target.
2715 if (ic->next && ic->next->op == GOTO
2716 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2717 && labelRange <= 5 )
2719 emitcode(";", "tail increment optimized (range %d)", labelRange);
2720 tlbl = IC_LABEL(ic->next);
2725 tlbl = newiTempLabel(NULL);
2728 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
2729 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2730 IS_AOP_PREG(IC_RESULT(ic)))
2731 emitcode("cjne","%s,#0x00,%05d$"
2732 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2735 emitcode("clr","a");
2736 emitcode("cjne","a,%s,%05d$"
2737 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
2741 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
2744 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2745 IS_AOP_PREG(IC_RESULT(ic)))
2746 emitcode("cjne","%s,#0x00,%05d$"
2747 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2750 emitcode("cjne","a,%s,%05d$"
2751 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
2754 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
2758 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2759 IS_AOP_PREG(IC_RESULT(ic)))
2760 emitcode("cjne","%s,#0x00,%05d$"
2761 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2764 emitcode("cjne","a,%s,%05d$"
2765 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
2768 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
2773 emitcode("","%05d$:",tlbl->key+100);
2778 /* if the sizes are greater than 1 then we cannot */
2779 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2780 AOP_SIZE(IC_LEFT(ic)) > 1 )
2783 /* we can if the aops of the left & result match or
2784 if they are in registers and the registers are the
2787 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2788 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
2789 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2792 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,TRUE));
2793 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2794 aopPut(AOP(IC_RESULT(ic)),"a",0);
2797 _startLazyDPSEvaluation();
2800 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE,FALSE));
2802 _endLazyDPSEvaluation();
2811 /*-----------------------------------------------------------------*/
2812 /* outBitAcc - output a bit in acc */
2813 /*-----------------------------------------------------------------*/
2814 static void outBitAcc(operand *result)
2816 symbol *tlbl = newiTempLabel(NULL);
2817 /* if the result is a bit */
2818 if (AOP_TYPE(result) == AOP_CRY){
2819 aopPut(AOP(result),"a",0);
2822 emitcode("jz","%05d$",tlbl->key+100);
2823 emitcode("mov","a,%s",one);
2824 emitcode("","%05d$:",tlbl->key+100);
2829 /*-----------------------------------------------------------------*/
2830 /* genPlusBits - generates code for addition of two bits */
2831 /*-----------------------------------------------------------------*/
2832 static void genPlusBits (iCode *ic)
2834 D(emitcode(";", "genPlusBits "););
2835 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2836 symbol *lbl = newiTempLabel(NULL);
2837 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2838 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2839 emitcode("cpl","c");
2840 emitcode("","%05d$:",(lbl->key+100));
2841 outBitC(IC_RESULT(ic));
2844 emitcode("clr","a");
2845 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2846 emitcode("rlc","a");
2847 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2848 emitcode("addc","a,#0x00");
2849 outAcc(IC_RESULT(ic));
2853 static void adjustArithmeticResult(iCode *ic)
2855 if (opIsGptr(IC_RESULT(ic)) &&
2856 opIsGptr(IC_LEFT(ic)) &&
2857 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2859 aopPut(AOP(IC_RESULT(ic)),
2860 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE,FALSE),
2864 if (opIsGptr(IC_RESULT(ic)) &&
2865 opIsGptr(IC_RIGHT(ic)) &&
2866 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2868 aopPut(AOP(IC_RESULT(ic)),
2869 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE,FALSE),
2873 if (opIsGptr(IC_RESULT(ic)) &&
2874 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2875 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2876 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2877 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2879 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2880 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2884 #define AOP_OP_3(ic) \
2885 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2886 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2887 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
2888 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2889 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2890 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2892 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2894 "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2897 #define AOP_OP_3_NOFATAL(ic, rc) \
2898 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2899 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2900 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2901 isOperandInFarSpace(IC_RESULT(ic))) \
2903 /* No can do; DPTR & DPTR2 in use, and we need another. */ \
2908 aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
2909 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
2911 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
2912 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
2914 /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
2916 "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \
2920 #define AOP_OP_2(ic) \
2921 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
2922 aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
2924 #define AOP_SET_LOCALS(ic) \
2925 left = IC_LEFT(ic); \
2926 right = IC_RIGHT(ic); \
2927 result = IC_RESULT(ic);
2929 /*-----------------------------------------------------------------*/
2930 /* genPlus - generates code for addition */
2931 /*-----------------------------------------------------------------*/
2932 static void genPlus (iCode *ic)
2934 int size, offset = 0;
2935 bool pushResult = FALSE;
2938 D(emitcode(";", "genPlus "););
2940 /* special cases :- */
2942 AOP_OP_3_NOFATAL(ic, pushResult);
2945 D(emitcode(";", "genPlus: must push result: 3 ops in far space"););
2950 /* if literal, literal on the right or
2951 if left requires ACC or right is already
2953 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT)
2954 || ((AOP_NEEDSACC(IC_LEFT(ic))) && !(AOP_NEEDSACC(IC_RIGHT(ic))))
2955 || AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC )
2957 operand *t = IC_RIGHT(ic);
2958 IC_RIGHT(ic) = IC_LEFT(ic);
2960 emitcode(";", "Swapped plus args.");
2963 /* if both left & right are in bit
2965 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2966 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2971 /* if left in bit space & right literal */
2972 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2973 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2974 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2975 /* if result in bit space */
2976 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2977 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2978 emitcode("cpl","c");
2979 outBitC(IC_RESULT(ic));
2981 size = getDataSize(IC_RESULT(ic));
2982 _startLazyDPSEvaluation();
2984 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
2985 emitcode("addc","a,#00");
2986 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2988 _endLazyDPSEvaluation();
2993 /* if I can do an increment instead
2994 of add then GOOD for ME */
2995 if (genPlusIncr (ic) == TRUE)
2997 emitcode(";", "did genPlusIncr");
3002 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3004 _startLazyDPSEvaluation();
3007 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3009 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3011 emitcode("add","a,%s",
3012 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3014 emitcode("addc","a,%s",
3015 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3017 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,TRUE));
3019 emitcode("add","a,%s",
3020 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3022 emitcode("addc","a,%s",
3023 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,FALSE));
3027 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3031 emitcode("push", "acc");
3035 _endLazyDPSEvaluation();
3039 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3041 size = getDataSize(IC_LEFT(ic));
3042 rSize = getDataSize(IC_RESULT(ic));
3044 /* If the pushed data is bigger than the result,
3045 * simply discard unused bytes. Icky, but works.
3047 * Should we throw a warning here? We're losing data...
3049 while (size > rSize)
3051 D(emitcode(";", "discarding unused result byte."););
3052 emitcode("pop", "acc");
3058 emitcode("clr", "a");
3059 /* Conversly, we haven't pushed enough here.
3060 * just zero-pad, and all is well.
3062 while (size < rSize)
3064 emitcode("push", "acc");
3070 _startLazyDPSEvaluation();
3073 emitcode("pop", "acc");
3074 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3076 _endLazyDPSEvaluation();
3079 adjustArithmeticResult(ic);
3082 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3083 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3084 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3087 /*-----------------------------------------------------------------*/
3088 /* genMinusDec :- does subtraction with deccrement if possible */
3089 /*-----------------------------------------------------------------*/
3090 static bool genMinusDec (iCode *ic)
3092 unsigned int icount ;
3093 unsigned int size = getDataSize(IC_RESULT(ic));
3095 /* will try to generate an increment */
3096 /* if the right side is not a literal
3098 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3101 /* if the literal value of the right hand side
3102 is greater than 4 then it is not worth it */
3103 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
3106 /* if decrement 16 bits in register */
3107 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3108 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3109 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3116 /* If the next instruction is a goto and the goto target
3117 * is <= 5 instructions previous to this, we can generate
3118 * jumps straight to that target.
3120 if (ic->next && ic->next->op == GOTO
3121 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
3122 && labelRange <= 5 )
3124 emitcode(";", "tail decrement optimized (range %d)", labelRange);
3125 tlbl = IC_LABEL(ic->next);
3130 tlbl = newiTempLabel(NULL);
3134 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE));
3135 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3136 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3137 IS_AOP_PREG(IC_RESULT(ic)))
3138 emitcode("cjne","%s,#0xff,%05d$"
3139 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3142 emitcode("mov","a,#0xff");
3143 emitcode("cjne","a,%s,%05d$"
3144 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE,FALSE)
3147 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE));
3150 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3151 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3152 IS_AOP_PREG(IC_RESULT(ic)))
3153 emitcode("cjne","%s,#0xff,%05d$"
3154 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3157 emitcode("cjne","a,%s,%05d$"
3158 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE,FALSE)
3161 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE));
3165 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
3166 AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
3167 IS_AOP_PREG(IC_RESULT(ic)))
3168 emitcode("cjne","%s,#0xff,%05d$"
3169 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3172 emitcode("cjne","a,%s,%05d$"
3173 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE,FALSE)
3176 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE,FALSE));
3180 emitcode("","%05d$:",tlbl->key+100);
3185 /* if the sizes are greater than 1 then we cannot */
3186 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3187 AOP_SIZE(IC_LEFT(ic)) > 1 )
3190 /* we can if the aops of the left & result match or
3191 if they are in registers and the registers are the
3194 AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3195 AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
3196 sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3198 _startLazyDPSEvaluation();
3201 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3203 _endLazyDPSEvaluation();
3211 /*-----------------------------------------------------------------*/
3212 /* addSign - complete with sign */
3213 /*-----------------------------------------------------------------*/
3214 static void addSign(operand *result, int offset, int sign)
3216 int size = (getDataSize(result) - offset);
3219 emitcode("rlc","a");
3220 emitcode("subb","a,acc");
3222 aopPut(AOP(result),"a",offset++);
3225 aopPut(AOP(result),zero,offset++);
3229 /*-----------------------------------------------------------------*/
3230 /* genMinusBits - generates code for subtraction of two bits */
3231 /*-----------------------------------------------------------------*/
3232 static void genMinusBits (iCode *ic)
3234 symbol *lbl = newiTempLabel(NULL);
3236 D(emitcode(";", "genMinusBits "););
3238 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3239 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3240 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3241 emitcode("cpl","c");
3242 emitcode("","%05d$:",(lbl->key+100));
3243 outBitC(IC_RESULT(ic));
3246 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3247 emitcode("subb","a,acc");
3248 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3249 emitcode("inc","a");
3250 emitcode("","%05d$:",(lbl->key+100));
3251 aopPut(AOP(IC_RESULT(ic)),"a",0);
3252 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3256 /*-----------------------------------------------------------------*/
3257 /* genMinus - generates code for subtraction */
3258 /*-----------------------------------------------------------------*/
3259 static void genMinus (iCode *ic)
3261 int size, offset = 0;
3263 unsigned long lit = 0L;
3264 bool pushResult = FALSE;
3266 D(emitcode(";", "genMinus "););
3268 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
3269 aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
3270 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
3271 (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
3277 aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
3279 /* special cases :- */
3280 /* if both left & right are in bit space */
3281 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3282 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3287 /* if I can do an decrement instead
3288 of subtract then GOOD for ME */
3289 if (genMinusDec (ic) == TRUE)
3294 size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
3296 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
3300 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3305 /* if literal, add a,#-lit, else normal subb */
3306 _startLazyDPSEvaluation();
3308 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE,TRUE));
3309 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3310 emitcode("subb","a,%s",
3311 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE,FALSE));
3313 /* first add without previous c */
3315 emitcode("add","a,#0x%02x",
3316 (unsigned int)(lit & 0x0FFL));
3318 emitcode("addc","a,#0x%02x",
3319 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3324 emitcode("push", "acc");
3328 aopPut(AOP(IC_RESULT(ic)),"a",offset);
3332 _endLazyDPSEvaluation();
3336 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
3338 size = getDataSize(IC_LEFT(ic));
3339 rSize = getDataSize(IC_RESULT(ic));
3341 /* If the pushed data is bigger than the result,
3342 * simply discard unused bytes. Icky, but works.
3344 * Should we throw a warning here? We're losing data...
3346 while (size > getDataSize(IC_RESULT(ic)))
3348 emitcode(";", "discarding unused result byte.");
3349 emitcode("pop", "acc");
3355 emitcode("clr", "a");
3356 /* Conversly, we haven't pushed enough here.
3357 * just zero-pad, and all is well.
3359 while (size < rSize)
3361 emitcode("push", "acc");
3369 emitcode("pop", "acc");
3370 aopPut(AOP(IC_RESULT(ic)), "a", --offset);
3374 adjustArithmeticResult(ic);
3377 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3378 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3379 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3383 /*-----------------------------------------------------------------*/
3384 /* genMultbits :- multiplication of bits */
3385 /*-----------------------------------------------------------------*/
3386 static void genMultbits (operand *left,
3390 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3391 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3396 /*-----------------------------------------------------------------*/
3397 /* genMultOneByte : 8 bit multiplication & division */
3398 /*-----------------------------------------------------------------*/
3399 static void genMultOneByte (operand *left,
3403 sym_link *opetype = operandType(result);
3408 /* (if two literals, the value is computed before) */
3409 /* if one literal, literal on the right */
3410 if (AOP_TYPE(left) == AOP_LIT){
3416 size = AOP_SIZE(result);
3417 /* signed or unsigned */
3418 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3419 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3421 emitcode("mul","ab");
3422 /* if result size = 1, mul signed = mul unsigned */
3423 aopPut(AOP(result),"a",0);
3425 if (SPEC_USIGN(opetype)){
3426 aopPut(AOP(result),"b",1);
3428 /* for filling the MSBs */
3429 emitcode("clr","a");
3432 emitcode("mov","a,b");
3434 /* adjust the MSB if left or right neg */
3436 /* if one literal */
3437 if (AOP_TYPE(right) == AOP_LIT){
3438 /* AND literal negative */
3439 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3440 /* adjust MSB (c==0 after mul) */
3441 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3445 lbl = newiTempLabel(NULL);
3446 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3447 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3448 emitcode("","%05d$:",(lbl->key+100));
3449 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3450 lbl = newiTempLabel(NULL);
3451 emitcode("jc","%05d$",(lbl->key+100));
3452 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3453 emitcode("","%05d$:",(lbl->key+100));
3456 lbl = newiTempLabel(NULL);
3457 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3458 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3459 emitcode("","%05d$:",(lbl->key+100));
3460 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE,FALSE));
3461 lbl = newiTempLabel(NULL);
3462 emitcode("jc","%05d$",(lbl->key+100));
3463 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3464 emitcode("","%05d$:",(lbl->key+100));
3466 aopPut(AOP(result),"a",1);
3469 emitcode("rlc","a");
3470 emitcode("subb","a,acc");
3477 aopPut(AOP(result),"a",offset++);
3481 /*-----------------------------------------------------------------*/
3482 /* genMult - generates code for multiplication */
3483 /*-----------------------------------------------------------------*/
3484 static void genMult (iCode *ic)
3486 operand *left = IC_LEFT(ic);
3487 operand *right = IC_RIGHT(ic);
3488 operand *result= IC_RESULT(ic);
3490 D(emitcode(";", "genMult "););
3492 /* assign the amsops */
3495 /* special cases first */
3497 if (AOP_TYPE(left) == AOP_CRY &&
3498 AOP_TYPE(right)== AOP_CRY) {
3499 genMultbits(left,right,result);
3503 /* if both are of size == 1 */
3504 if (AOP_SIZE(left) == 1 &&
3505 AOP_SIZE(right) == 1 ) {
3506 genMultOneByte(left,right,result);
3510 /* should have been converted to function call */
3514 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3515 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3516 freeAsmop(result,NULL,ic,TRUE);
3519 /*-----------------------------------------------------------------*/
3520 /* genDivbits :- division of bits */
3521 /*-----------------------------------------------------------------*/
3522 static void genDivbits (operand *left,
3529 /* the result must be bit */
3530 LOAD_AB_FOR_DIV(left, right, l);
3531 emitcode("div","ab");
3532 emitcode("rrc","a");
3533 aopPut(AOP(result),"c",0);
3536 /*-----------------------------------------------------------------*/
3537 /* genDivOneByte : 8 bit division */
3538 /*-----------------------------------------------------------------*/
3539 static void genDivOneByte (operand *left,
3543 sym_link *opetype = operandType(result);
3548 size = AOP_SIZE(result) - 1;
3550 /* signed or unsigned */
3551 if (SPEC_USIGN(opetype)) {
3552 /* unsigned is easy */
3553 LOAD_AB_FOR_DIV(left, right, l);
3554 emitcode("div","ab");
3555 aopPut(AOP(result),"a",0);
3557 aopPut(AOP(result),zero,offset++);
3561 /* signed is a little bit more difficult */
3563 /* save the signs of the operands */
3564 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3566 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE,FALSE));
3567 emitcode("push","acc"); /* save it on the stack */
3569 /* now sign adjust for both left & right */
3570 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3572 lbl = newiTempLabel(NULL);
3573 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3574 emitcode("cpl","a");
3575 emitcode("inc","a");
3576 emitcode("","%05d$:",(lbl->key+100));
3577 emitcode("mov","b,a");
3579 /* sign adjust left side */
3580 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3583 lbl = newiTempLabel(NULL);
3584 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3585 emitcode("cpl","a");
3586 emitcode("inc","a");
3587 emitcode("","%05d$:",(lbl->key+100));
3589 /* now the division */
3590 emitcode("nop", "; workaround for DS80C390 div bug.");
3591 emitcode("div","ab");
3592 /* we are interested in the lower order
3594 emitcode("mov","b,a");
3595 lbl = newiTempLabel(NULL);
3596 emitcode("pop","acc");
3597 /* if there was an over flow we don't
3598 adjust the sign of the result */
3599 emitcode("jb","ov,%05d$",(lbl->key+100));
3600 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3602 emitcode("clr","a");
3603 emitcode("subb","a,b");
3604 emitcode("mov","b,a");
3605 emitcode("","%05d$:",(lbl->key+100));
3607 /* now we are done */
3608 aopPut(AOP(result),"b",0);
3610 emitcode("mov","c,b.7");
3611 emitcode("subb","a,acc");
3614 aopPut(AOP(result),"a",offset++);
3618 /*-----------------------------------------------------------------*/
3619 /* genDiv - generates code for division */
3620 /*-----------------------------------------------------------------*/
3621 static void genDiv (iCode *ic)
3623 operand *left = IC_LEFT(ic);
3624 operand *right = IC_RIGHT(ic);
3625 operand *result= IC_RESULT(ic);
3627 D(emitcode(";", "genDiv "););
3629 /* assign the amsops */
3632 /* special cases first */
3634 if (AOP_TYPE(left) == AOP_CRY &&
3635 AOP_TYPE(right)== AOP_CRY) {
3636 genDivbits(left,right,result);
3640 /* if both are of size == 1 */
3641 if (AOP_SIZE(left) == 1 &&
3642 AOP_SIZE(right) == 1 ) {
3643 genDivOneByte(left,right,result);
3647 /* should have been converted to function call */
3650 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3651 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3652 freeAsmop(result,NULL,ic,TRUE);
3655 /*-----------------------------------------------------------------*/
3656 /* genModbits :- modulus of bits */
3657 /*-----------------------------------------------------------------*/
3658 static void genModbits (operand *left,
3665 /* the result must be bit */
3666 LOAD_AB_FOR_DIV(left, right, l);
3667 emitcode("div","ab");
3668 emitcode("mov","a,b");
3669 emitcode("rrc","a");
3670 aopPut(AOP(result),"c",0);
3673 /*-----------------------------------------------------------------*/
3674 /* genModOneByte : 8 bit modulus */
3675 /*-----------------------------------------------------------------*/
3676 static void genModOneByte (operand *left,
3680 sym_link *opetype = operandType(result);
3684 /* signed or unsigned */
3685 if (SPEC_USIGN(opetype)) {
3686 /* unsigned is easy */
3687 LOAD_AB_FOR_DIV(left, right, l);
3688 emitcode("div","ab");
3689 aopPut(AOP(result),"b",0);
3693 /* signed is a little bit more difficult */
3695 /* save the signs of the operands */
3696 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3699 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
3700 emitcode("push","acc"); /* save it on the stack */
3702 /* now sign adjust for both left & right */
3703 l = aopGet(AOP(right),0,FALSE,FALSE,TRUE);
3706 lbl = newiTempLabel(NULL);
3707 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3708 emitcode("cpl","a");
3709 emitcode("inc","a");
3710 emitcode("","%05d$:",(lbl->key+100));
3711 emitcode("mov","b,a");
3713 /* sign adjust left side */
3714 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
3717 lbl = newiTempLabel(NULL);
3718 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3719 emitcode("cpl","a");
3720 emitcode("inc","a");
3721 emitcode("","%05d$:",(lbl->key+100));
3723 /* now the multiplication */
3724 emitcode("nop", "; workaround for DS80C390 div bug.");
3725 emitcode("div","ab");
3726 /* we are interested in the lower order
3728 lbl = newiTempLabel(NULL);
3729 emitcode("pop","acc");
3730 /* if there was an over flow we don't
3731 adjust the sign of the result */
3732 emitcode("jb","ov,%05d$",(lbl->key+100));
3733 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3735 emitcode("clr","a");
3736 emitcode("subb","a,b");
3737 emitcode("mov","b,a");
3738 emitcode("","%05d$:",(lbl->key+100));
3740 /* now we are done */
3741 aopPut(AOP(result),"b",0);
3745 /*-----------------------------------------------------------------*/
3746 /* genMod - generates code for division */
3747 /*-----------------------------------------------------------------*/
3748 static void genMod (iCode *ic)
3750 operand *left = IC_LEFT(ic);
3751 operand *right = IC_RIGHT(ic);
3752 operand *result= IC_RESULT(ic);
3754 D(emitcode(";", "genMod "););
3756 /* assign the amsops */
3759 /* special cases first */
3761 if (AOP_TYPE(left) == AOP_CRY &&
3762 AOP_TYPE(right)== AOP_CRY) {
3763 genModbits(left,right,result);
3767 /* if both are of size == 1 */
3768 if (AOP_SIZE(left) == 1 &&
3769 AOP_SIZE(right) == 1 ) {
3770 genModOneByte(left,right,result);
3774 /* should have been converted to function call */
3778 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3779 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3780 freeAsmop(result,NULL,ic,TRUE);
3783 /*-----------------------------------------------------------------*/
3784 /* genIfxJump :- will create a jump depending on the ifx */
3785 /*-----------------------------------------------------------------*/
3786 static void genIfxJump (iCode *ic, char *jval)
3789 symbol *tlbl = newiTempLabel(NULL);
3792 D(emitcode(";", "genIfxJump "););
3794 /* if true label then we jump if condition
3796 if ( IC_TRUE(ic) ) {
3798 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3799 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3802 /* false label is present */
3803 jlbl = IC_FALSE(ic) ;
3804 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3805 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3807 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3808 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3810 emitcode(inst,"%05d$",tlbl->key+100);
3811 emitcode("ljmp","%05d$",jlbl->key+100);
3812 emitcode("","%05d$:",tlbl->key+100);
3814 /* mark the icode as generated */
3818 /*-----------------------------------------------------------------*/
3819 /* genCmp :- greater or less than comparison */
3820 /*-----------------------------------------------------------------*/
3821 static void genCmp (operand *left,operand *right,
3822 iCode *ic, iCode *ifx, int sign)
3824 int size, offset = 0 ;
3825 unsigned long lit = 0L;
3828 D(emitcode(";", "genCmp"););
3830 result = IC_RESULT(ic);
3832 /* if left & right are bit variables */
3833 if (AOP_TYPE(left) == AOP_CRY &&
3834 AOP_TYPE(right) == AOP_CRY ) {
3835 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3836 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3838 /* subtract right from left if at the
3839 end the carry flag is set then we know that
3840 left is greater than right */
3841 size = max(AOP_SIZE(left),AOP_SIZE(right));
3843 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3844 if((size == 1) && !sign &&
3845 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3846 symbol *lbl = newiTempLabel(NULL);
3847 emitcode("cjne","%s,%s,%05d$",
3848 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
3849 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
3851 emitcode("","%05d$:",lbl->key+100);
3853 if (AOP_TYPE(right) == AOP_LIT)
3855 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3856 /* optimize if(x < 0) or if(x >= 0) */
3865 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE,TRUE));
3867 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3868 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3870 aopOp(result,ic,FALSE, FALSE);
3872 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx)
3874 freeAsmop(result,NULL,ic,TRUE);
3875 genIfxJump (ifx,"acc.7");
3880 emitcode("rlc","a");
3882 goto release_freedLR;
3890 emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
3891 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
3892 emitcode(";", "genCmp #2");
3893 if (sign && (size == 0))
3895 emitcode(";", "genCmp #3");
3896 emitcode("xrl","a,#0x80");
3897 if (AOP_TYPE(right) == AOP_LIT)
3899 unsigned long lit = (unsigned long)
3900 floatFromVal(AOP(right)->aopu.aop_lit);
3901 emitcode(";", "genCmp #3.1");
3902 emitcode("subb","a,#0x%02x",
3903 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3907 emitcode(";", "genCmp #3.2");
3908 if (AOP_NEEDSACC(right))
3910 emitcode("push", "acc");
3912 emitcode("mov","b,%s",aopGet(AOP(right),offset++,
3913 FALSE,FALSE,FALSE));
3914 emitcode("xrl","b,#0x80");
3915 if (AOP_NEEDSACC(right))
3917 emitcode("pop", "acc");
3919 emitcode("subb","a,b");
3926 emitcode(";", "genCmp #4");
3927 if (AOP_NEEDSACC(right))
3930 emitcode(";", "genCmp #4.1");
3931 emitcode("xch", "a, b");
3932 MOVA(aopGet(AOP(right),offset++,FALSE,FALSE,TRUE));
3933 emitcode("xch", "a, b");
3938 emitcode(";", "genCmp #4.2");
3939 s = aopGet(AOP(right),offset++,FALSE,FALSE,FALSE);
3942 emitcode("subb","a,%s",s);
3949 /* Don't need the left & right operands any more; do need the result. */
3950 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3951 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3953 aopOp(result,ic,FALSE, FALSE);
3957 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result))
3963 /* if the result is used in the next
3964 ifx conditional branch then generate
3965 code a little differently */
3968 genIfxJump (ifx,"c");
3974 /* leave the result in acc */
3976 freeAsmop(result,NULL,ic,TRUE);
3979 /*-----------------------------------------------------------------*/
3980 /* genCmpGt :- greater than comparison */
3981 /*-----------------------------------------------------------------*/
3982 static void genCmpGt (iCode *ic, iCode *ifx)
3984 operand *left, *right;
3985 sym_link *letype , *retype;
3988 D(emitcode(";", "genCmpGt "););
3991 right= IC_RIGHT(ic);
3993 letype = getSpec(operandType(left));
3994 retype =getSpec(operandType(right));
3995 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3997 /* assign the left & right amsops */
4000 genCmp(right, left, ic, ifx, sign);
4003 /*-----------------------------------------------------------------*/
4004 /* genCmpLt - less than comparisons */
4005 /*-----------------------------------------------------------------*/
4006 static void genCmpLt (iCode *ic, iCode *ifx)
4008 operand *left, *right;
4009 sym_link *letype , *retype;
4012 D(emitcode(";", "genCmpLt "););
4015 right= IC_RIGHT(ic);
4017 letype = getSpec(operandType(left));
4018 retype =getSpec(operandType(right));
4019 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4021 /* assign the left & right amsops */
4024 genCmp(left, right, ic, ifx, sign);
4027 /*-----------------------------------------------------------------*/
4028 /* gencjneshort - compare and jump if not equal */
4029 /*-----------------------------------------------------------------*/
4030 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4032 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4034 unsigned long lit = 0L;
4036 D(emitcode(";", "gencjneshort"););
4038 /* if the left side is a literal or
4039 if the right is in a pointer register and left
4041 if ((AOP_TYPE(left) == AOP_LIT) ||
4042 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4048 if(AOP_TYPE(right) == AOP_LIT)
4049 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4051 if (opIsGptr(left) || opIsGptr(right))
4053 /* We are comparing a generic pointer to something.
4054 * Exclude the generic type byte from the comparison.
4057 D(emitcode(";", "cjneshort: generic ptr special case.");)
4061 /* if the right side is a literal then anything goes */
4062 if (AOP_TYPE(right) == AOP_LIT &&
4063 AOP_TYPE(left) != AOP_DIR ) {
4065 char *l = aopGet(AOP(left), offset, FALSE, FALSE,TRUE);
4067 emitcode("cjne","a,%s,%05d$",
4068 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
4074 /* if the right side is in a register or in direct space or
4075 if the left is a pointer register & right is not */
4076 else if (AOP_TYPE(right) == AOP_REG ||
4077 AOP_TYPE(right) == AOP_DIR ||
4078 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4079 (IS_AOP_PREG(left) && !IS_AOP_PREG(right)))
4083 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4084 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4085 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4086 emitcode("jnz","%05d$",lbl->key+100);
4088 emitcode("cjne","a,%s,%05d$",
4089 aopGet(AOP(right),offset,FALSE,TRUE,FALSE),
4094 /* right is a pointer reg need both a & b */
4096 char *l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
4098 emitcode("mov","b,%s",l);
4099 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4100 emitcode("cjne","a,b,%05d$",lbl->key+100);
4106 /*-----------------------------------------------------------------*/
4107 /* gencjne - compare and jump if not equal */
4108 /*-----------------------------------------------------------------*/
4109 static void gencjne(operand *left, operand *right, symbol *lbl)
4111 symbol *tlbl = newiTempLabel(NULL);
4113 D(emitcode(";", "gencjne"););
4115 gencjneshort(left, right, lbl);
4117 emitcode("mov","a,%s",one);
4118 emitcode("sjmp","%05d$",tlbl->key+100);
4119 emitcode("","%05d$:",lbl->key+100);
4120 emitcode("clr","a");
4121 emitcode("","%05d$:",tlbl->key+100);
4124 /*-----------------------------------------------------------------*/
4125 /* genCmpEq - generates code for equal to */
4126 /*-----------------------------------------------------------------*/
4127 static void genCmpEq (iCode *ic, iCode *ifx)
4129 operand *left, *right, *result;
4131 D(emitcode(";", "genCmpEq "););
4136 /* if literal, literal on the right or
4137 if the right is in a pointer register and left
4139 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4140 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4141 operand *t = IC_RIGHT(ic);
4142 IC_RIGHT(ic) = IC_LEFT(ic);
4146 if (ifx && /* !AOP_SIZE(result) */
4147 OP_SYMBOL(result) &&
4148 OP_SYMBOL(result)->regType == REG_CND)
4151 /* if they are both bit variables */
4152 if (AOP_TYPE(left) == AOP_CRY &&
4153 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4154 if(AOP_TYPE(right) == AOP_LIT){
4155 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4157 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4158 emitcode("cpl","c");
4159 } else if(lit == 1L) {
4160 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4162 emitcode("clr","c");
4164 /* AOP_TYPE(right) == AOP_CRY */
4166 symbol *lbl = newiTempLabel(NULL);
4167 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4168 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
4169 emitcode("cpl","c");
4170 emitcode("","%05d$:",(lbl->key+100));
4172 /* if true label then we jump if condition
4174 tlbl = newiTempLabel(NULL);
4175 if ( IC_TRUE(ifx) ) {
4176 emitcode("jnc","%05d$",tlbl->key+100);
4177 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4179 emitcode("jc","%05d$",tlbl->key+100);
4180 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4182 emitcode("","%05d$:",tlbl->key+100);
4184 tlbl = newiTempLabel(NULL);
4185 gencjneshort(left, right, tlbl);
4186 if ( IC_TRUE(ifx) ) {
4187 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
4188 emitcode("","%05d$:",tlbl->key+100);
4190 symbol *lbl = newiTempLabel(NULL);
4191 emitcode("sjmp","%05d$",lbl->key+100);
4192 emitcode("","%05d$:",tlbl->key+100);
4193 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
4194 emitcode("","%05d$:",lbl->key+100);
4197 /* mark the icode as generated */
4200 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4201 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
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));
4227 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4228 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4230 aopOp(result,ic,TRUE, FALSE);
4233 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4238 genIfxJump (ifx,"c");
4241 /* if the result is used in an arithmetic operation
4242 then put the result in place */
4245 gencjne(left,right,newiTempLabel(NULL));
4247 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4248 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4250 aopOp(result,ic,TRUE, FALSE);
4252 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4253 aopPut(AOP(result),"a",0);
4257 genIfxJump (ifx,"a");
4260 /* if the result is used in an arithmetic operation
4261 then put the result in place */
4262 if (AOP_TYPE(result) != AOP_CRY)
4264 /* leave the result in acc */
4268 freeAsmop(result,NULL,ic,TRUE);
4271 /*-----------------------------------------------------------------*/
4272 /* ifxForOp - returns the icode containing the ifx for operand */
4273 /*-----------------------------------------------------------------*/
4274 static iCode *ifxForOp ( operand *op, iCode *ic )
4276 /* if true symbol then needs to be assigned */
4277 if (IS_TRUE_SYMOP(op))
4280 /* if this has register type condition and
4281 the next instruction is ifx with the same operand
4282 and live to of the operand is upto the ifx only then */
4284 ic->next->op == IFX &&
4285 IC_COND(ic->next)->key == op->key &&
4286 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4291 /*-----------------------------------------------------------------*/
4292 /* genAndOp - for && operation */
4293 /*-----------------------------------------------------------------*/
4294 static void genAndOp (iCode *ic)
4296 operand *left,*right, *result;
4299 D(emitcode(";", "genAndOp "););
4301 /* note here that && operations that are in an
4302 if statement are taken away by backPatchLabels
4303 only those used in arthmetic operations remain */
4307 /* if both are bit variables */
4308 if (AOP_TYPE(left) == AOP_CRY &&
4309 AOP_TYPE(right) == AOP_CRY ) {
4310 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4311 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4314 tlbl = newiTempLabel(NULL);
4316 emitcode("jz","%05d$",tlbl->key+100);
4318 emitcode("","%05d$:",tlbl->key+100);
4322 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4323 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4324 freeAsmop(result,NULL,ic,TRUE);
4328 /*-----------------------------------------------------------------*/
4329 /* genOrOp - for || operation */
4330 /*-----------------------------------------------------------------*/
4331 static void genOrOp (iCode *ic)
4333 operand *left,*right, *result;
4336 D(emitcode(";", "genOrOp "););
4338 /* note here that || operations that are in an
4339 if statement are taken away by backPatchLabels
4340 only those used in arthmetic operations remain */
4344 /* if both are bit variables */
4345 if (AOP_TYPE(left) == AOP_CRY &&
4346 AOP_TYPE(right) == AOP_CRY ) {
4347 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4348 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
4351 tlbl = newiTempLabel(NULL);
4353 emitcode("jnz","%05d$",tlbl->key+100);
4355 emitcode("","%05d$:",tlbl->key+100);
4359 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4360 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4361 freeAsmop(result,NULL,ic,TRUE);
4364 /*-----------------------------------------------------------------*/
4365 /* isLiteralBit - test if lit == 2^n */
4366 /*-----------------------------------------------------------------*/
4367 static int isLiteralBit(unsigned long lit)
4369 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4370 0x100L,0x200L,0x400L,0x800L,
4371 0x1000L,0x2000L,0x4000L,0x8000L,
4372 0x10000L,0x20000L,0x40000L,0x80000L,
4373 0x100000L,0x200000L,0x400000L,0x800000L,
4374 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4375 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4378 for(idx = 0; idx < 32; idx++)
4384 /*-----------------------------------------------------------------*/
4385 /* continueIfTrue - */
4386 /*-----------------------------------------------------------------*/
4387 static void continueIfTrue (iCode *ic)
4390 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4394 /*-----------------------------------------------------------------*/
4396 /*-----------------------------------------------------------------*/
4397 static void jumpIfTrue (iCode *ic)
4400 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4404 /*-----------------------------------------------------------------*/
4405 /* jmpTrueOrFalse - */
4406 /*-----------------------------------------------------------------*/
4407 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4409 // ugly but optimized by peephole
4411 symbol *nlbl = newiTempLabel(NULL);
4412 emitcode("sjmp","%05d$",nlbl->key+100);
4413 emitcode("","%05d$:",tlbl->key+100);
4414 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
4415 emitcode("","%05d$:",nlbl->key+100);
4418 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
4419 emitcode("","%05d$:",tlbl->key+100);
4424 /*-----------------------------------------------------------------*/
4425 /* genAnd - code for and */
4426 /*-----------------------------------------------------------------*/
4427 static void genAnd (iCode *ic, iCode *ifx)
4429 operand *left, *right, *result;
4431 unsigned long lit = 0L;
4435 D(emitcode(";", "genAnd "););
4441 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4443 AOP_TYPE(left), AOP_TYPE(right));
4444 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4446 AOP_SIZE(left), AOP_SIZE(right));
4449 /* if left is a literal & right is not then exchange them */
4450 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4451 AOP_NEEDSACC(left)) {
4452 operand *tmp = right ;
4457 /* if result = right then exchange them */
4458 if(sameRegs(AOP(result),AOP(right))){
4459 operand *tmp = right ;
4464 /* if right is bit then exchange them */
4465 if (AOP_TYPE(right) == AOP_CRY &&
4466 AOP_TYPE(left) != AOP_CRY){
4467 operand *tmp = right ;
4471 if(AOP_TYPE(right) == AOP_LIT)
4472 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4474 size = AOP_SIZE(result);
4477 // result = bit & yy;
4478 if (AOP_TYPE(left) == AOP_CRY){
4479 // c = bit & literal;
4480 if(AOP_TYPE(right) == AOP_LIT){
4482 if(size && sameRegs(AOP(result),AOP(left)))
4485 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4488 if(size && (AOP_TYPE(result) == AOP_CRY)){
4489 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4492 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4496 emitcode("clr","c");
4499 if (AOP_TYPE(right) == AOP_CRY){
4501 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4502 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4505 MOVA(aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4507 emitcode("rrc","a");
4508 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4516 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4517 genIfxJump(ifx, "c");
4521 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4522 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4523 if((AOP_TYPE(right) == AOP_LIT) &&
4524 (AOP_TYPE(result) == AOP_CRY) &&
4525 (AOP_TYPE(left) != AOP_CRY)){
4526 int posbit = isLiteralBit(lit);
4530 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE,TRUE));
4533 emitcode("mov","c,acc.%d",posbit&0x07);
4537 sprintf(buffer,"acc.%d",posbit&0x07);
4538 genIfxJump(ifx, buffer);
4543 symbol *tlbl = newiTempLabel(NULL);
4544 int sizel = AOP_SIZE(left);
4546 emitcode("setb","c");
4548 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4549 MOVA( aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4551 if((posbit = isLiteralBit(bytelit)) != 0)
4552 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
4554 if(bytelit != 0x0FFL)
4555 emitcode("anl","a,%s",
4556 aopGet(AOP(right),offset,FALSE,TRUE,FALSE));
4557 emitcode("jnz","%05d$",tlbl->key+100);
4562 // bit = left & literal
4564 emitcode("clr","c");
4565 emitcode("","%05d$:",tlbl->key+100);
4567 // if(left & literal)
4570 jmpTrueOrFalse(ifx, tlbl);
4578 /* if left is same as result */
4579 if(sameRegs(AOP(result),AOP(left))){
4580 for(;size--; offset++) {
4581 if(AOP_TYPE(right) == AOP_LIT){
4582 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4586 aopPut(AOP(result),zero,offset);
4588 if (IS_AOP_PREG(result)) {
4589 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4590 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4591 aopPut(AOP(result),"a",offset);
4593 emitcode("anl","%s,%s",
4594 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4595 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4597 if (AOP_TYPE(left) == AOP_ACC)
4598 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4600 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4601 if (IS_AOP_PREG(result)) {
4602 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4603 aopPut(AOP(result),"a",offset);
4606 emitcode("anl","%s,a",
4607 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4612 // left & result in different registers
4613 if(AOP_TYPE(result) == AOP_CRY){
4615 // if(size), result in bit
4616 // if(!size && ifx), conditional oper: if(left & right)
4617 symbol *tlbl = newiTempLabel(NULL);
4618 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4620 emitcode("setb","c");
4622 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4623 emitcode("anl","a,%s",
4624 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4625 emitcode("jnz","%05d$",tlbl->key+100);
4630 emitcode("","%05d$:",tlbl->key+100);
4633 jmpTrueOrFalse(ifx, tlbl);
4636 for(;(size--);offset++)
4639 // result = left & right
4640 if(AOP_TYPE(right) == AOP_LIT)
4642 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4645 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4649 else if (bytelit == 0)
4651 aopPut(AOP(result),zero,offset);
4654 D(emitcode(";", "better literal AND."););
4655 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4656 emitcode("anl", "a, %s", aopGet(AOP(right),offset,
4657 FALSE,FALSE,FALSE));
4662 // faster than result <- left, anl result,right
4663 // and better if result is SFR
4664 if (AOP_TYPE(left) == AOP_ACC)
4666 emitcode("anl","a,%s",aopGet(AOP(right),offset,
4667 FALSE,FALSE,FALSE));
4671 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4672 emitcode("anl","a,%s",
4673 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4676 aopPut(AOP(result),"a",offset);
4682 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4683 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4684 freeAsmop(result,NULL,ic,TRUE);
4687 /*-----------------------------------------------------------------*/
4688 /* genOr - code for or */
4689 /*-----------------------------------------------------------------*/
4690 static void genOr (iCode *ic, iCode *ifx)
4692 operand *left, *right, *result;
4694 unsigned long lit = 0L;
4696 D(emitcode(";", "genOr "););
4702 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4704 AOP_TYPE(left), AOP_TYPE(right));
4705 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4707 AOP_SIZE(left), AOP_SIZE(right));
4710 /* if left is a literal & right is not then exchange them */
4711 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4712 AOP_NEEDSACC(left)) {
4713 operand *tmp = right ;
4718 /* if result = right then exchange them */
4719 if(sameRegs(AOP(result),AOP(right))){
4720 operand *tmp = right ;
4725 /* if right is bit then exchange them */
4726 if (AOP_TYPE(right) == AOP_CRY &&
4727 AOP_TYPE(left) != AOP_CRY){
4728 operand *tmp = right ;
4732 if(AOP_TYPE(right) == AOP_LIT)
4733 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4735 size = AOP_SIZE(result);
4739 if (AOP_TYPE(left) == AOP_CRY){
4740 if(AOP_TYPE(right) == AOP_LIT){
4741 // c = bit & literal;
4743 // lit != 0 => result = 1
4744 if(AOP_TYPE(result) == AOP_CRY){
4746 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4748 continueIfTrue(ifx);
4751 emitcode("setb","c");
4753 // lit == 0 => result = left
4754 if(size && sameRegs(AOP(result),AOP(left)))
4756 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4759 if (AOP_TYPE(right) == AOP_CRY){
4761 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4762 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4766 symbol *tlbl = newiTempLabel(NULL);
4767 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4768 emitcode("setb","c");
4769 emitcode("jb","%s,%05d$",
4770 AOP(left)->aopu.aop_dir,tlbl->key+100);
4772 emitcode("jnz","%05d$",tlbl->key+100);
4773 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4774 jmpTrueOrFalse(ifx, tlbl);
4778 emitcode("","%05d$:",tlbl->key+100);
4787 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4788 genIfxJump(ifx, "c");
4792 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4793 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4794 if((AOP_TYPE(right) == AOP_LIT) &&
4795 (AOP_TYPE(result) == AOP_CRY) &&
4796 (AOP_TYPE(left) != AOP_CRY)){
4800 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4802 continueIfTrue(ifx);
4805 // lit = 0, result = boolean(left)
4807 emitcode("setb","c");
4810 symbol *tlbl = newiTempLabel(NULL);
4811 emitcode("jnz","%05d$",tlbl->key+100);
4813 emitcode("","%05d$:",tlbl->key+100);
4815 genIfxJump (ifx,"a");
4823 /* if left is same as result */
4824 if(sameRegs(AOP(result),AOP(left)))
4826 for(;size--; offset++)
4828 if(AOP_TYPE(right) == AOP_LIT){
4829 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4835 if (IS_AOP_PREG(left))
4837 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4838 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4839 aopPut(AOP(result),"a",offset);
4843 emitcode("orl","%s,%s",
4844 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
4845 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4851 if (AOP_TYPE(left) == AOP_ACC)
4853 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
4857 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4858 if (IS_AOP_PREG(left))
4860 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4861 aopPut(AOP(result),"a",offset);
4865 emitcode("orl","%s,a",
4866 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
4874 // left & result in different registers
4875 if(AOP_TYPE(result) == AOP_CRY)
4878 // if(size), result in bit
4879 // if(!size && ifx), conditional oper: if(left | right)
4880 symbol *tlbl = newiTempLabel(NULL);
4881 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4883 emitcode("setb","c");
4885 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4886 emitcode("orl","a,%s",
4887 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4888 emitcode("jnz","%05d$",tlbl->key+100);
4893 emitcode("","%05d$:",tlbl->key+100);
4896 jmpTrueOrFalse(ifx, tlbl);
4900 for(;(size--);offset++)
4903 // result = left & right
4904 if(AOP_TYPE(right) == AOP_LIT)
4906 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4909 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
4913 D(emitcode(";", "better literal OR."););
4914 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
4915 emitcode("orl", "a, %s", aopGet(AOP(right),offset,
4916 FALSE,FALSE,FALSE));
4921 // faster than result <- left, anl result,right
4922 // and better if result is SFR
4923 if (AOP_TYPE(left) == AOP_ACC)
4925 emitcode("orl","a,%s",aopGet(AOP(right),offset,
4926 FALSE,FALSE,FALSE));
4930 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
4931 emitcode("orl","a,%s",
4932 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
4935 aopPut(AOP(result),"a",offset);
4941 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4942 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4943 freeAsmop(result,NULL,ic,TRUE);
4946 /*-----------------------------------------------------------------*/
4947 /* genXor - code for xclusive or */
4948 /*-----------------------------------------------------------------*/
4949 static void genXor (iCode *ic, iCode *ifx)
4951 operand *left, *right, *result;
4953 unsigned long lit = 0L;
4955 D(emitcode(";", "genXor "););
4961 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4963 AOP_TYPE(left), AOP_TYPE(right));
4964 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4966 AOP_SIZE(left), AOP_SIZE(right));
4969 /* if left is a literal & right is not ||
4970 if left needs acc & right does not */
4971 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4972 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4973 operand *tmp = right ;
4978 /* if result = right then exchange them */
4979 if(sameRegs(AOP(result),AOP(right))){
4980 operand *tmp = right ;
4985 /* if right is bit then exchange them */
4986 if (AOP_TYPE(right) == AOP_CRY &&
4987 AOP_TYPE(left) != AOP_CRY){
4988 operand *tmp = right ;
4992 if(AOP_TYPE(right) == AOP_LIT)
4993 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4995 size = AOP_SIZE(result);
4999 if (AOP_TYPE(left) == AOP_CRY){
5000 if(AOP_TYPE(right) == AOP_LIT){
5001 // c = bit & literal;
5003 // lit>>1 != 0 => result = 1
5004 if(AOP_TYPE(result) == AOP_CRY){
5006 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5008 continueIfTrue(ifx);
5011 emitcode("setb","c");
5015 // lit == 0, result = left
5016 if(size && sameRegs(AOP(result),AOP(left)))
5018 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5020 // lit == 1, result = not(left)
5021 if(size && sameRegs(AOP(result),AOP(left))){
5022 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5025 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5026 emitcode("cpl","c");
5033 symbol *tlbl = newiTempLabel(NULL);
5034 if (AOP_TYPE(right) == AOP_CRY){
5036 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5039 int sizer = AOP_SIZE(right);
5041 // if val>>1 != 0, result = 1
5042 emitcode("setb","c");
5044 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE,TRUE));
5046 // test the msb of the lsb
5047 emitcode("anl","a,#0xfe");
5048 emitcode("jnz","%05d$",tlbl->key+100);
5052 emitcode("rrc","a");
5054 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5055 emitcode("cpl","c");
5056 emitcode("","%05d$:",(tlbl->key+100));
5063 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5064 genIfxJump(ifx, "c");
5068 if(sameRegs(AOP(result),AOP(left))){
5069 /* if left is same as result */
5070 for(;size--; offset++) {
5071 if(AOP_TYPE(right) == AOP_LIT){
5072 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5075 if (IS_AOP_PREG(left)) {
5076 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5077 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5078 aopPut(AOP(result),"a",offset);
5080 emitcode("xrl","%s,%s",
5081 aopGet(AOP(left),offset,FALSE,TRUE,FALSE),
5082 aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5084 if (AOP_TYPE(left) == AOP_ACC)
5085 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE,FALSE));
5087 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5088 if (IS_AOP_PREG(left)) {
5089 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5090 aopPut(AOP(result),"a",offset);
5092 emitcode("xrl","%s,a",
5093 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5098 // left & result in different registers
5099 if(AOP_TYPE(result) == AOP_CRY){
5101 // if(size), result in bit
5102 // if(!size && ifx), conditional oper: if(left ^ right)
5103 symbol *tlbl = newiTempLabel(NULL);
5104 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5106 emitcode("setb","c");
5108 if((AOP_TYPE(right) == AOP_LIT) &&
5109 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5110 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5112 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5113 emitcode("xrl","a,%s",
5114 aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
5116 emitcode("jnz","%05d$",tlbl->key+100);
5121 emitcode("","%05d$:",tlbl->key+100);
5124 jmpTrueOrFalse(ifx, tlbl);
5125 } else for(;(size--);offset++)
5128 // result = left & right
5129 if(AOP_TYPE(right) == AOP_LIT)
5131 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5134 aopGet(AOP(left),offset,FALSE,FALSE,FALSE),
5138 D(emitcode(";", "better literal XOR."););
5139 MOVA(aopGet(AOP(left),offset,FALSE,FALSE,TRUE));
5140 emitcode("xrl", "a, %s", aopGet(AOP(right),offset,
5141 FALSE,FALSE,FALSE));
5145 // faster than result <- left, anl result,right
5146 // and better if result is SFR
5147 if (AOP_TYPE(left) == AOP_ACC)
5149 emitcode("xrl","a,%s",aopGet(AOP(right),offset,
5150 FALSE,FALSE,FALSE));
5154 MOVA(aopGet(AOP(right),offset,FALSE,FALSE,TRUE));
5155 emitcode("xrl","a,%s",
5156 aopGet(AOP(left),offset,FALSE,TRUE,FALSE));
5159 aopPut(AOP(result),"a",offset);
5164 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5165 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5166 freeAsmop(result,NULL,ic,TRUE);
5169 /*-----------------------------------------------------------------*/
5170 /* genInline - write the inline code out */
5171 /*-----------------------------------------------------------------*/
5172 static void genInline (iCode *ic)
5174 char buffer[MAX_INLINEASM];
5178 D(emitcode(";", "genInline "););
5180 _G.inLine += (!options.asmpeep);
5181 strcpy(buffer,IC_INLINE(ic));
5183 /* emit each line as a code */
5202 /* emitcode("",buffer); */
5203 _G.inLine -= (!options.asmpeep);
5206 /*-----------------------------------------------------------------*/
5207 /* genRRC - rotate right with carry */
5208 /*-----------------------------------------------------------------*/
5209 static void genRRC (iCode *ic)
5211 operand *left , *result ;
5212 int size, offset = 0;
5215 D(emitcode(";", "genRRC "););
5217 /* rotate right with carry */
5219 result=IC_RESULT(ic);
5220 aopOp (left,ic,FALSE, FALSE);
5221 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5223 /* move it to the result */
5224 size = AOP_SIZE(result);
5228 _startLazyDPSEvaluation();
5230 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5232 emitcode("rrc","a");
5233 if (AOP_SIZE(result) > 1)
5234 aopPut(AOP(result),"a",offset--);
5236 _endLazyDPSEvaluation();
5238 /* now we need to put the carry into the
5239 highest order byte of the result */
5240 if (AOP_SIZE(result) > 1) {
5241 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE,TRUE);
5244 emitcode("mov","acc.7,c");
5245 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5246 freeAsmop(left,NULL,ic,TRUE);
5247 freeAsmop(result,NULL,ic,TRUE);
5250 /*-----------------------------------------------------------------*/
5251 /* genRLC - generate code for rotate left with carry */
5252 /*-----------------------------------------------------------------*/
5253 static void genRLC (iCode *ic)
5255 operand *left , *result ;
5256 int size, offset = 0;
5259 D(emitcode(";", "genRLC "););
5261 /* rotate right with carry */
5263 result=IC_RESULT(ic);
5264 aopOp (left,ic,FALSE, FALSE);
5265 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5267 /* move it to the result */
5268 size = AOP_SIZE(result);
5271 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5273 emitcode("add","a,acc");
5274 if (AOP_SIZE(result) > 1)
5276 aopPut(AOP(result),"a",offset++);
5279 _startLazyDPSEvaluation();
5281 l = aopGet(AOP(left),offset,FALSE,FALSE,TRUE);
5283 emitcode("rlc","a");
5284 if (AOP_SIZE(result) > 1)
5285 aopPut(AOP(result),"a",offset++);
5287 _endLazyDPSEvaluation();
5289 /* now we need to put the carry into the
5290 highest order byte of the result */
5291 if (AOP_SIZE(result) > 1) {
5292 l = aopGet(AOP(result),0,FALSE,FALSE,TRUE);
5295 emitcode("mov","acc.0,c");
5296 aopPut(AOP(result),"a",0);
5297 freeAsmop(left,NULL,ic,TRUE);
5298 freeAsmop(result,NULL,ic,TRUE);
5301 /*-----------------------------------------------------------------*/
5302 /* genGetHbit - generates code get highest order bit */
5303 /*-----------------------------------------------------------------*/
5304 static void genGetHbit (iCode *ic)
5306 operand *left, *result;
5308 result=IC_RESULT(ic);
5309 aopOp (left,ic,FALSE, FALSE);
5310 aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
5312 D(emitcode(";", "genGetHbit "););
5314 /* get the highest order byte into a */
5315 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE,TRUE));
5316 if(AOP_TYPE(result) == AOP_CRY){
5317 emitcode("rlc","a");
5322 emitcode("anl","a,#0x01");
5327 freeAsmop(left,NULL,ic,TRUE);
5328 freeAsmop(result,NULL,ic,TRUE);
5331 /*-----------------------------------------------------------------*/
5332 /* AccRol - rotate left accumulator by known count */
5333 /*-----------------------------------------------------------------*/
5334 static void AccRol (int shCount)
5336 shCount &= 0x0007; // shCount : 0..7
5348 emitcode("swap","a");
5352 emitcode("swap","a");
5355 emitcode("swap","a");
5368 /*-----------------------------------------------------------------*/
5369 /* AccLsh - left shift accumulator by known count */
5370 /*-----------------------------------------------------------------*/
5371 static void AccLsh (int shCount)
5375 emitcode("add","a,acc");
5378 emitcode("add","a,acc");
5379 emitcode("add","a,acc");
5381 /* rotate left accumulator */
5383 /* and kill the lower order bits */
5384 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5389 /*-----------------------------------------------------------------*/
5390 /* AccRsh - right shift accumulator by known count */
5391 /*-----------------------------------------------------------------*/
5392 static void AccRsh (int shCount)
5397 emitcode("rrc","a");
5399 /* rotate right accumulator */
5400 AccRol(8 - shCount);
5401 /* and kill the higher order bits */
5402 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5409 /*-----------------------------------------------------------------*/
5410 /* AccSRsh - signed right shift accumulator by known count */
5411 /*-----------------------------------------------------------------*/
5412 static void AccSRsh (int shCount)
5417 emitcode("mov","c,acc.7");
5418 emitcode("rrc","a");
5419 } else if(shCount == 2){
5420 emitcode("mov","c,acc.7");
5421 emitcode("rrc","a");
5422 emitcode("mov","c,acc.7");
5423 emitcode("rrc","a");
5425 tlbl = newiTempLabel(NULL);
5426 /* rotate right accumulator */
5427 AccRol(8 - shCount);
5428 /* and kill the higher order bits */
5429 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5430 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5431 emitcode("orl","a,#0x%02x",
5432 (unsigned char)~SRMask[shCount]);
5433 emitcode("","%05d$:",tlbl->key+100);
5441 /*-----------------------------------------------------------------*/
5442 /* shiftR1Left2Result - shift right one byte from left to result */
5443 /*-----------------------------------------------------------------*/
5444 static void shiftR1Left2Result (operand *left, int offl,
5445 operand *result, int offr,
5446 int shCount, int sign)
5448 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5449 /* shift right accumulator */
5454 aopPut(AOP(result),"a",offr);
5460 /*-----------------------------------------------------------------*/
5461 /* shiftL1Left2Result - shift left one byte from left to result */
5462 /*-----------------------------------------------------------------*/
5463 static void shiftL1Left2Result (operand *left, int offl,
5464 operand *result, int offr, int shCount)
5467 l = aopGet(AOP(left),offl,FALSE,FALSE,TRUE);
5469 /* shift left accumulator */
5471 aopPut(AOP(result),"a",offr);
5477 /*-----------------------------------------------------------------*/
5478 /* movLeft2Result - move byte from left to result */
5479 /*-----------------------------------------------------------------*/
5480 static void movLeft2Result (operand *left, int offl,
5481 operand *result, int offr, int sign)
5484 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5485 l = aopGet(AOP(left),offl,FALSE,FALSE,FALSE);
5487 if (*l == '@' && (IS_AOP_PREG(result))) {
5488 emitcode("mov","a,%s",l);
5489 aopPut(AOP(result),"a",offr);
5492 aopPut(AOP(result),l,offr);
5494 /* MSB sign in acc.7 ! */
5495 if(getDataSize(left) == offl+1){
5496 emitcode("mov","a,%s",l);
5497 aopPut(AOP(result),"a",offr);
5507 /*-----------------------------------------------------------------*/
5508 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5509 /*-----------------------------------------------------------------*/
5510 static void AccAXRrl1 (char *x)
5512 emitcode("rrc","a");
5513 emitcode("xch","a,%s", x);
5514 emitcode("rrc","a");
5515 emitcode("xch","a,%s", x);
5521 /*-----------------------------------------------------------------*/
5522 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5523 /*-----------------------------------------------------------------*/
5524 static void AccAXLrl1 (char *x)
5526 emitcode("xch","a,%s",x);
5527 emitcode("rlc","a");
5528 emitcode("xch","a,%s",x);
5529 emitcode("rlc","a");
5535 /*-----------------------------------------------------------------*/
5536 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5537 /*-----------------------------------------------------------------*/
5538 static void AccAXLsh1 (char *x)
5540 emitcode("xch","a,%s",x);
5541 emitcode("add","a,acc");
5542 emitcode("xch","a,%s",x);
5543 emitcode("rlc","a");
5549 /*-----------------------------------------------------------------*/
5550 /* AccAXLsh - left shift a:x by known count (0..7) */
5551 /*-----------------------------------------------------------------*/
5552 static void AccAXLsh (char *x, int shCount)
5566 case 5 : // AAAAABBB:CCCCCDDD
5567 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5568 emitcode("anl","a,#0x%02x",
5569 SLMask[shCount]); // BBB00000:CCCCCDDD
5570 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5571 AccRol(shCount); // DDDCCCCC:BBB00000
5572 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5573 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5574 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5575 emitcode("anl","a,#0x%02x",
5576 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5577 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5578 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5580 case 6 : // AAAAAABB:CCCCCCDD
5581 emitcode("anl","a,#0x%02x",
5582 SRMask[shCount]); // 000000BB:CCCCCCDD
5583 emitcode("mov","c,acc.0"); // c = B
5584 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5585 AccAXRrl1(x); // BCCCCCCD:D000000B
5586 AccAXRrl1(x); // BBCCCCCC:DD000000
5588 case 7 : // a:x <<= 7
5589 emitcode("anl","a,#0x%02x",
5590 SRMask[shCount]); // 0000000B:CCCCCCCD
5591 emitcode("mov","c,acc.0"); // c = B
5592 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5593 AccAXRrl1(x); // BCCCCCCC:D0000000
5603 /*-----------------------------------------------------------------*/
5604 /* AccAXRsh - right shift a:x known count (0..7) */
5605 /*-----------------------------------------------------------------*/
5606 static void AccAXRsh (char *x, int shCount)
5613 AccAXRrl1(x); // 0->a:x
5617 AccAXRrl1(x); // 0->a:x
5619 AccAXRrl1(x); // 0->a:x
5623 case 5 : // AAAAABBB:CCCCCDDD = a:x
5624 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5625 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5626 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5627 emitcode("anl","a,#0x%02x",
5628 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5629 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5630 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5631 emitcode("anl","a,#0x%02x",
5632 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5633 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5634 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5635 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5637 case 6 : // AABBBBBB:CCDDDDDD
5638 emitcode("mov","c,acc.7");
5639 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5640 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5641 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5642 emitcode("anl","a,#0x%02x",
5643 SRMask[shCount]); // 000000AA:BBBBBBCC
5645 case 7 : // ABBBBBBB:CDDDDDDD
5646 emitcode("mov","c,acc.7"); // c = A
5647 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5648 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5649 emitcode("anl","a,#0x%02x",
5650 SRMask[shCount]); // 0000000A:BBBBBBBC
5660 /*-----------------------------------------------------------------*/
5661 /* AccAXRshS - right shift signed a:x known count (0..7) */
5662 /*-----------------------------------------------------------------*/
5663 static void AccAXRshS (char *x, int shCount)
5670 emitcode("mov","c,acc.7");
5671 AccAXRrl1(x); // s->a:x
5674 emitcode("mov","c,acc.7");
5675 AccAXRrl1(x); // s->a:x
5676 emitcode("mov","c,acc.7");
5677 AccAXRrl1(x); // s->a:x
5681 case 5 : // AAAAABBB:CCCCCDDD = a:x
5682 tlbl = newiTempLabel(NULL);
5683 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5684 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5685 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5686 emitcode("anl","a,#0x%02x",
5687 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5688 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5689 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5690 emitcode("anl","a,#0x%02x",
5691 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5692 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5693 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5694 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5695 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5696 emitcode("orl","a,#0x%02x",
5697 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5698 emitcode("","%05d$:",tlbl->key+100);
5699 break; // SSSSAAAA:BBBCCCCC
5700 case 6 : // AABBBBBB:CCDDDDDD
5701 tlbl = newiTempLabel(NULL);
5702 emitcode("mov","c,acc.7");
5703 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5704 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5705 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5706 emitcode("anl","a,#0x%02x",
5707 SRMask[shCount]); // 000000AA:BBBBBBCC
5708 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5709 emitcode("orl","a,#0x%02x",
5710 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5711 emitcode("","%05d$:",tlbl->key+100);
5713 case 7 : // ABBBBBBB:CDDDDDDD
5714 tlbl = newiTempLabel(NULL);
5715 emitcode("mov","c,acc.7"); // c = A
5716 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5717 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5718 emitcode("anl","a,#0x%02x",
5719 SRMask[shCount]); // 0000000A:BBBBBBBC
5720 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5721 emitcode("orl","a,#0x%02x",
5722 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5723 emitcode("","%05d$:",tlbl->key+100);
5733 /*-----------------------------------------------------------------*/
5734 /* shiftL2Left2Result - shift left two bytes from left to result */
5735 /*-----------------------------------------------------------------*/
5736 static void shiftL2Left2Result (operand *left, int offl,
5737 operand *result, int offr, int shCount)
5739 if(sameRegs(AOP(result), AOP(left)) &&
5740 ((offl + MSB16) == offr)){
5741 /* don't crash result[offr] */
5742 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5743 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5745 movLeft2Result(left,offl, result, offr, 0);
5746 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5748 /* ax << shCount (x = lsb(result))*/
5749 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE), shCount);
5750 aopPut(AOP(result),"a",offr+MSB16);
5756 /*-----------------------------------------------------------------*/
5757 /* shiftR2Left2Result - shift right two bytes from left to result */
5758 /*-----------------------------------------------------------------*/
5759 static void shiftR2Left2Result (operand *left, int offl,
5760 operand *result, int offr,
5761 int shCount, int sign)
5763 if(sameRegs(AOP(result), AOP(left)) &&
5764 ((offl + MSB16) == offr)){
5765 /* don't crash result[offr] */
5766 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5767 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE,FALSE));
5769 movLeft2Result(left,offl, result, offr, 0);
5770 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE,TRUE));
5772 /* a:x >> shCount (x = lsb(result))*/
5774 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5776 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE,FALSE) , shCount);
5777 if(getDataSize(result) > 1)
5778 aopPut(AOP(result),"a",offr+MSB16);
5784 /*-----------------------------------------------------------------*/
5785 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5786 /*-----------------------------------------------------------------*/
5787 static void shiftLLeftOrResult (operand *left, int offl,
5788 operand *result, int offr, int shCount)
5790 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5791 /* shift left accumulator */
5793 /* or with result */
5794 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5795 /* back to result */
5796 aopPut(AOP(result),"a",offr);
5802 /*-----------------------------------------------------------------*/
5803 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5804 /*-----------------------------------------------------------------*/
5805 static void shiftRLeftOrResult (operand *left, int offl,
5806 operand *result, int offr, int shCount)
5808 MOVA(aopGet(AOP(left),offl,FALSE,FALSE,TRUE));
5809 /* shift right accumulator */
5811 /* or with result */
5812 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE,FALSE));
5813 /* back to result */
5814 aopPut(AOP(result),"a",offr);
5820 /*-----------------------------------------------------------------*/
5821 /* genlshOne - left shift a one byte quantity by known count */
5822 /*-----------------------------------------------------------------*/
5823 static void genlshOne (operand *result, operand *left, int shCount)
5825 D(emitcode(";", "genlshOne "););
5826 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5832 /*-----------------------------------------------------------------*/
5833 /* genlshTwo - left shift two bytes by known amount != 0 */
5834 /*-----------------------------------------------------------------*/
5835 static void genlshTwo (operand *result,operand *left, int shCount)
5839 D(emitcode(";", "genlshTwo "););
5841 size = getDataSize(result);
5843 /* if shCount >= 8 */
5849 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5851 movLeft2Result(left, LSB, result, MSB16, 0);
5853 aopPut(AOP(result),zero,LSB);
5856 /* 1 <= shCount <= 7 */
5859 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5861 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5868 /*-----------------------------------------------------------------*/
5869 /* shiftLLong - shift left one long from left to result */
5870 /* offl = LSB or MSB16 */
5871 /*-----------------------------------------------------------------*/
5872 static void shiftLLong (operand *left, operand *result, int offr )
5875 int size = AOP_SIZE(result);
5877 if(size >= LSB+offr){
5878 l = aopGet(AOP(left),LSB,FALSE,FALSE,TRUE);
5880 emitcode("add","a,acc");
5881 if (sameRegs(AOP(left),AOP(result)) &&
5882 size >= MSB16+offr && offr != LSB )
5883 emitcode("xch","a,%s",
5884 aopGet(AOP(left),LSB+offr,FALSE,FALSE,FALSE));
5886 aopPut(AOP(result),"a",LSB+offr);
5889 if(size >= MSB16+offr){
5890 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5891 l = aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE);
5894 emitcode("rlc","a");
5895 if (sameRegs(AOP(left),AOP(result)) &&
5896 size >= MSB24+offr && offr != LSB)
5897 emitcode("xch","a,%s",
5898 aopGet(AOP(left),MSB16+offr,FALSE,FALSE,FALSE));
5900 aopPut(AOP(result),"a",MSB16+offr);
5903 if(size >= MSB24+offr){
5904 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5905 l = aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE);
5908 emitcode("rlc","a");
5909 if (sameRegs(AOP(left),AOP(result)) &&
5910 size >= MSB32+offr && offr != LSB )
5911 emitcode("xch","a,%s",
5912 aopGet(AOP(left),MSB24+offr,FALSE,FALSE,FALSE));
5914 aopPut(AOP(result),"a",MSB24+offr);
5917 if(size > MSB32+offr){
5918 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5919 l = aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE);
5922 emitcode("rlc","a");
5923 aopPut(AOP(result),"a",MSB32+offr);
5926 aopPut(AOP(result),zero,LSB);
5932 /*-----------------------------------------------------------------*/
5933 /* genlshFour - shift four byte by a known amount != 0 */
5934 /*-----------------------------------------------------------------*/
5935 static void genlshFour (operand *result, operand *left, int shCount)
5939 D(emitcode(";", "genlshFour "););
5941 size = AOP_SIZE(result);
5943 /* if shifting more that 3 bytes */
5944 if (shCount >= 24 ) {
5947 /* lowest order of left goes to the highest
5948 order of the destination */
5949 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5951 movLeft2Result(left, LSB, result, MSB32, 0);
5952 aopPut(AOP(result),zero,LSB);
5953 aopPut(AOP(result),zero,MSB16);
5954 aopPut(AOP(result),zero,MSB32);
5958 /* more than two bytes */
5959 else if ( shCount >= 16 ) {
5960 /* lower order two bytes goes to higher order two bytes */
5962 /* if some more remaining */
5964 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5966 movLeft2Result(left, MSB16, result, MSB32, 0);
5967 movLeft2Result(left, LSB, result, MSB24, 0);
5969 aopPut(AOP(result),zero,MSB16);
5970 aopPut(AOP(result),zero,LSB);
5974 /* if more than 1 byte */
5975 else if ( shCount >= 8 ) {
5976 /* lower order three bytes goes to higher order three bytes */
5980 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5982 movLeft2Result(left, LSB, result, MSB16, 0);
5984 else{ /* size = 4 */
5986 movLeft2Result(left, MSB24, result, MSB32, 0);
5987 movLeft2Result(left, MSB16, result, MSB24, 0);
5988 movLeft2Result(left, LSB, result, MSB16, 0);
5989 aopPut(AOP(result),zero,LSB);
5991 else if(shCount == 1)
5992 shiftLLong(left, result, MSB16);
5994 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5995 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5996 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5997 aopPut(AOP(result),zero,LSB);
6002 /* 1 <= shCount <= 7 */
6003 else if(shCount <= 2){
6004 shiftLLong(left, result, LSB);
6006 shiftLLong(result, result, LSB);
6008 /* 3 <= shCount <= 7, optimize */
6010 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6011 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6012 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6019 /*-----------------------------------------------------------------*/
6020 /* genLeftShiftLiteral - left shifting by known count */
6021 /*-----------------------------------------------------------------*/
6022 static void genLeftShiftLiteral (operand *left,
6027 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6030 D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
6032 freeAsmop(right,NULL,ic,TRUE);
6034 aopOp(left,ic,FALSE, FALSE);
6035 aopOp(result,ic,FALSE, TRUE);
6037 size = getSize(operandType(result));
6040 emitcode("; shift left ","result %d, left %d",size,
6044 /* I suppose that the left size >= result size */
6047 movLeft2Result(left, size, result, size, 0);
6051 else if(shCount >= (size * 8))
6053 aopPut(AOP(result),zero,size);
6057 genlshOne (result,left,shCount);
6061 case 3: /* bug: this is for generic pointers, I bet. */
6062 genlshTwo (result,left,shCount);
6066 genlshFour (result,left,shCount);
6070 freeAsmop(left,NULL,ic,TRUE);
6071 freeAsmop(result,NULL,ic,TRUE);
6075 /*-----------------------------------------------------------------*/
6076 /* genLeftShift - generates code for left shifting */
6077 /*-----------------------------------------------------------------*/
6078 static void genLeftShift (iCode *ic)
6080 operand *left,*right, *result;
6083 symbol *tlbl , *tlbl1;
6085 D(emitcode(";", "genLeftShift "););
6087 right = IC_RIGHT(ic);
6089 result = IC_RESULT(ic);
6091 aopOp(right,ic,FALSE, FALSE);
6094 /* if the shift count is known then do it
6095 as efficiently as possible */
6096 if (AOP_TYPE(right) == AOP_LIT) {
6097 genLeftShiftLiteral (left,right,result,ic);
6102 /* shift count is unknown then we have to form
6103 a loop get the loop count in B : Note: we take
6104 only the lower order byte since shifting
6105 more that 32 bits make no sense anyway, ( the
6106 largest size of an object can be only 32 bits ) */
6108 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6109 emitcode("inc","b");
6110 freeAsmop (right,NULL,ic,TRUE);
6111 aopOp(left,ic,FALSE, FALSE);
6112 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6114 /* now move the left to the result if they are not the
6116 if (!sameRegs(AOP(left),AOP(result)) &&
6117 AOP_SIZE(result) > 1) {
6119 size = AOP_SIZE(result);
6121 _startLazyDPSEvaluation();
6123 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6124 if (*l == '@' && (IS_AOP_PREG(result))) {
6126 emitcode("mov","a,%s",l);
6127 aopPut(AOP(result),"a",offset);
6129 aopPut(AOP(result),l,offset);
6132 _endLazyDPSEvaluation();
6135 tlbl = newiTempLabel(NULL);
6136 size = AOP_SIZE(result);
6138 tlbl1 = newiTempLabel(NULL);
6140 /* if it is only one byte then */
6142 symbol *tlbl1 = newiTempLabel(NULL);
6144 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6146 emitcode("sjmp","%05d$",tlbl1->key+100);
6147 emitcode("","%05d$:",tlbl->key+100);
6148 emitcode("add","a,acc");
6149 emitcode("","%05d$:",tlbl1->key+100);
6150 emitcode("djnz","b,%05d$",tlbl->key+100);
6151 aopPut(AOP(result),"a",0);
6155 reAdjustPreg(AOP(result));
6157 emitcode("sjmp","%05d$",tlbl1->key+100);
6158 emitcode("","%05d$:",tlbl->key+100);
6159 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6161 emitcode("add","a,acc");
6162 aopPut(AOP(result),"a",offset++);
6163 _startLazyDPSEvaluation();
6165 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6167 emitcode("rlc","a");
6168 aopPut(AOP(result),"a",offset++);
6170 _endLazyDPSEvaluation();
6171 reAdjustPreg(AOP(result));
6173 emitcode("","%05d$:",tlbl1->key+100);
6174 emitcode("djnz","b,%05d$",tlbl->key+100);
6176 freeAsmop(left,NULL,ic,TRUE);
6177 freeAsmop(result,NULL,ic,TRUE);
6182 /*-----------------------------------------------------------------*/
6183 /* genrshOne - right shift a one byte quantity by known count */
6184 /*-----------------------------------------------------------------*/
6185 static void genrshOne (operand *result, operand *left,
6186 int shCount, int sign)
6188 D(emitcode(";", "genrshOne"););
6189 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6195 /*-----------------------------------------------------------------*/
6196 /* genrshTwo - right shift two bytes by known amount != 0 */
6197 /*-----------------------------------------------------------------*/
6198 static void genrshTwo (operand *result,operand *left,
6199 int shCount, int sign)
6201 D(emitcode(";", "genrshTwo"););
6203 /* if shCount >= 8 */
6207 shiftR1Left2Result(left, MSB16, result, LSB,
6210 movLeft2Result(left, MSB16, result, LSB, sign);
6211 addSign(result, MSB16, sign);
6214 /* 1 <= shCount <= 7 */
6216 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6222 /*-----------------------------------------------------------------*/
6223 /* shiftRLong - shift right one long from left to result */
6224 /* offl = LSB or MSB16 */
6225 /*-----------------------------------------------------------------*/
6226 static void shiftRLong (operand *left, int offl,
6227 operand *result, int sign)
6230 emitcode("clr","c");
6231 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE,TRUE));
6233 emitcode("mov","c,acc.7");
6234 emitcode("rrc","a");
6235 aopPut(AOP(result),"a",MSB32-offl);
6237 /* add sign of "a" */
6238 addSign(result, MSB32, sign);
6240 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE,TRUE));
6241 emitcode("rrc","a");
6242 aopPut(AOP(result),"a",MSB24-offl);
6244 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE,TRUE));
6245 emitcode("rrc","a");
6246 aopPut(AOP(result),"a",MSB16-offl);
6249 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE,TRUE));
6250 emitcode("rrc","a");
6251 aopPut(AOP(result),"a",LSB);
6258 /*-----------------------------------------------------------------*/
6259 /* genrshFour - shift four byte by a known amount != 0 */
6260 /*-----------------------------------------------------------------*/
6261 static void genrshFour (operand *result, operand *left,
6262 int shCount, int sign)
6264 D(emitcode(";", "genrshFour"););
6266 /* if shifting more that 3 bytes */
6267 if(shCount >= 24 ) {
6270 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6272 movLeft2Result(left, MSB32, result, LSB, sign);
6273 addSign(result, MSB16, sign);
6275 else if(shCount >= 16){
6278 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6280 movLeft2Result(left, MSB24, result, LSB, 0);
6281 movLeft2Result(left, MSB32, result, MSB16, sign);
6283 addSign(result, MSB24, sign);
6285 else if(shCount >= 8){
6288 shiftRLong(left, MSB16, result, sign);
6289 else if(shCount == 0){
6290 movLeft2Result(left, MSB16, result, LSB, 0);
6291 movLeft2Result(left, MSB24, result, MSB16, 0);
6292 movLeft2Result(left, MSB32, result, MSB24, sign);
6293 addSign(result, MSB32, sign);
6296 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6297 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6298 /* the last shift is signed */
6299 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6300 addSign(result, MSB32, sign);
6303 else{ /* 1 <= shCount <= 7 */
6305 shiftRLong(left, LSB, result, sign);
6307 shiftRLong(result, LSB, result, sign);
6310 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6311 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6312 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6320 /*-----------------------------------------------------------------*/
6321 /* genRightShiftLiteral - right shifting by known count */
6322 /*-----------------------------------------------------------------*/
6323 static void genRightShiftLiteral (operand *left,
6329 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6332 D(emitcode(";", "genRightShiftLiteral"););
6334 freeAsmop(right,NULL,ic,TRUE);
6336 aopOp(left,ic,FALSE, FALSE);
6337 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6340 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6344 size = getDataSize(left);
6345 /* test the LEFT size !!! */
6347 /* I suppose that the left size >= result size */
6349 size = getDataSize(result);
6351 movLeft2Result(left, size, result, size, 0);
6354 else if(shCount >= (size * 8)){
6356 /* get sign in acc.7 */
6357 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE,TRUE));
6358 addSign(result, LSB, sign);
6362 genrshOne (result,left,shCount,sign);
6366 genrshTwo (result,left,shCount,sign);
6370 genrshFour (result,left,shCount,sign);
6376 freeAsmop(left,NULL,ic,TRUE);
6377 freeAsmop(result,NULL,ic,TRUE);
6382 /*-----------------------------------------------------------------*/
6383 /* genSignedRightShift - right shift of signed number */
6384 /*-----------------------------------------------------------------*/
6385 static void genSignedRightShift (iCode *ic)
6387 operand *right, *left, *result;
6390 symbol *tlbl, *tlbl1 ;
6392 D(emitcode(";", "genSignedRightShift "););
6394 /* we do it the hard way put the shift count in b
6395 and loop thru preserving the sign */
6397 right = IC_RIGHT(ic);
6399 result = IC_RESULT(ic);
6401 aopOp(right,ic,FALSE, FALSE);
6404 if ( AOP_TYPE(right) == AOP_LIT) {
6405 genRightShiftLiteral (left,right,result,ic,1);
6409 /* shift count is unknown then we have to form
6410 a loop get the loop count in B : Note: we take
6411 only the lower order byte since shifting
6412 more that 32 bits make no sense anyway, ( the
6413 largest size of an object can be only 32 bits ) */
6415 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6416 emitcode("inc","b");
6417 freeAsmop (right,NULL,ic,TRUE);
6418 aopOp(left,ic,FALSE, FALSE);
6419 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6421 /* now move the left to the result if they are not the
6423 if (!sameRegs(AOP(left),AOP(result)) &&
6424 AOP_SIZE(result) > 1) {
6426 size = AOP_SIZE(result);
6428 _startLazyDPSEvaluation();
6430 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6431 if (*l == '@' && IS_AOP_PREG(result)) {
6433 emitcode("mov","a,%s",l);
6434 aopPut(AOP(result),"a",offset);
6436 aopPut(AOP(result),l,offset);
6439 _endLazyDPSEvaluation();
6442 /* mov the highest order bit to OVR */
6443 tlbl = newiTempLabel(NULL);
6444 tlbl1= newiTempLabel(NULL);
6446 size = AOP_SIZE(result);
6448 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE,FALSE));
6449 emitcode("rlc","a");
6450 emitcode("mov","ov,c");
6451 /* if it is only one byte then */
6453 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6455 emitcode("sjmp","%05d$",tlbl1->key+100);
6456 emitcode("","%05d$:",tlbl->key+100);
6457 emitcode("mov","c,ov");
6458 emitcode("rrc","a");
6459 emitcode("","%05d$:",tlbl1->key+100);
6460 emitcode("djnz","b,%05d$",tlbl->key+100);
6461 aopPut(AOP(result),"a",0);
6465 reAdjustPreg(AOP(result));
6466 emitcode("sjmp","%05d$",tlbl1->key+100);
6467 emitcode("","%05d$:",tlbl->key+100);
6468 emitcode("mov","c,ov");
6469 _startLazyDPSEvaluation();
6471 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6473 emitcode("rrc","a");
6474 aopPut(AOP(result),"a",offset--);
6476 _endLazyDPSEvaluation();
6477 reAdjustPreg(AOP(result));
6478 emitcode("","%05d$:",tlbl1->key+100);
6479 emitcode("djnz","b,%05d$",tlbl->key+100);
6482 freeAsmop(left,NULL,ic,TRUE);
6483 freeAsmop(result,NULL,ic,TRUE);
6486 /*-----------------------------------------------------------------*/
6487 /* genRightShift - generate code for right shifting */
6488 /*-----------------------------------------------------------------*/
6489 static void genRightShift (iCode *ic)
6491 operand *right, *left, *result;
6495 symbol *tlbl, *tlbl1 ;
6497 D(emitcode(";", "genRightShift "););
6499 /* if signed then we do it the hard way preserve the
6500 sign bit moving it inwards */
6501 retype = getSpec(operandType(IC_RESULT(ic)));
6503 if (!SPEC_USIGN(retype)) {
6504 genSignedRightShift (ic);
6508 /* signed & unsigned types are treated the same : i.e. the
6509 signed is NOT propagated inwards : quoting from the
6510 ANSI - standard : "for E1 >> E2, is equivalent to division
6511 by 2**E2 if unsigned or if it has a non-negative value,
6512 otherwise the result is implementation defined ", MY definition
6513 is that the sign does not get propagated */
6515 right = IC_RIGHT(ic);
6517 result = IC_RESULT(ic);
6519 aopOp(right,ic,FALSE, FALSE);
6522 /* if the shift count is known then do it
6523 as efficiently as possible */
6524 if (AOP_TYPE(right) == AOP_LIT) {
6525 genRightShiftLiteral (left,right,result,ic, 0);
6530 /* shift count is unknown then we have to form
6531 a loop get the loop count in B : Note: we take
6532 only the lower order byte since shifting
6533 more that 32 bits make no sense anyway, ( the
6534 largest size of an object can be only 32 bits ) */
6536 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,FALSE));
6537 emitcode("inc","b");
6538 freeAsmop (right,NULL,ic,TRUE);
6539 aopOp(left,ic,FALSE, FALSE);
6540 aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
6542 /* now move the left to the result if they are not the
6544 if (!sameRegs(AOP(left),AOP(result)) &&
6545 AOP_SIZE(result) > 1) {
6547 size = AOP_SIZE(result);
6549 _startLazyDPSEvaluation();
6551 l = aopGet(AOP(left),offset,FALSE,TRUE,FALSE);
6552 if (*l == '@' && IS_AOP_PREG(result)) {
6554 emitcode("mov","a,%s",l);
6555 aopPut(AOP(result),"a",offset);
6557 aopPut(AOP(result),l,offset);
6560 _endLazyDPSEvaluation();
6563 tlbl = newiTempLabel(NULL);
6564 tlbl1= newiTempLabel(NULL);
6565 size = AOP_SIZE(result);
6568 /* if it is only one byte then */
6570 l = aopGet(AOP(left),0,FALSE,FALSE,TRUE);
6572 emitcode("sjmp","%05d$",tlbl1->key+100);
6573 emitcode("","%05d$:",tlbl->key+100);
6575 emitcode("rrc","a");
6576 emitcode("","%05d$:",tlbl1->key+100);
6577 emitcode("djnz","b,%05d$",tlbl->key+100);
6578 aopPut(AOP(result),"a",0);
6582 reAdjustPreg(AOP(result));
6583 emitcode("sjmp","%05d$",tlbl1->key+100);
6584 emitcode("","%05d$:",tlbl->key+100);
6586 _startLazyDPSEvaluation();
6588 l = aopGet(AOP(result),offset,FALSE,FALSE,TRUE);
6590 emitcode("rrc","a");
6591 aopPut(AOP(result),"a",offset--);
6593 _endLazyDPSEvaluation();
6594 reAdjustPreg(AOP(result));
6596 emitcode("","%05d$:",tlbl1->key+100);
6597 emitcode("djnz","b,%05d$",tlbl->key+100);
6600 freeAsmop(left,NULL,ic,TRUE);
6601 freeAsmop(result,NULL,ic,TRUE);
6604 /*-----------------------------------------------------------------*/
6605 /* genUnpackBits - generates code for unpacking bits */
6606 /*-----------------------------------------------------------------*/
6607 static void genUnpackBits (operand *result, char *rname, int ptype)
6614 D(emitcode(";", "genUnpackBits "););
6616 etype = getSpec(operandType(result));
6618 /* read the first byte */
6623 emitcode("mov","a,@%s",rname);
6627 emitcode("movx","a,@%s",rname);
6631 emitcode("movx","a,@dptr");
6635 emitcode("clr","a");
6636 emitcode("movc","a","@a+dptr");
6640 emitcode("lcall","__gptrget");
6644 /* if we have bitdisplacement then it fits */
6645 /* into this byte completely or if length is */
6646 /* less than a byte */
6647 if ((shCnt = SPEC_BSTR(etype)) ||
6648 (SPEC_BLEN(etype) <= 8)) {
6650 /* shift right acc */
6653 emitcode("anl","a,#0x%02x",
6654 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6655 aopPut(AOP(result),"a",offset);
6659 /* bit field did not fit in a byte */
6660 rlen = SPEC_BLEN(etype) - 8;
6661 aopPut(AOP(result),"a",offset++);
6668 emitcode("inc","%s",rname);
6669 emitcode("mov","a,@%s",rname);
6673 emitcode("inc","%s",rname);
6674 emitcode("movx","a,@%s",rname);
6678 emitcode("inc","dptr");
6679 emitcode("movx","a,@dptr");
6683 emitcode("clr","a");
6684 emitcode("inc","dptr");
6685 emitcode("movc","a","@a+dptr");
6689 emitcode("inc","dptr");
6690 emitcode("lcall","__gptrget");
6695 /* if we are done */
6699 aopPut(AOP(result),"a",offset++);
6704 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6705 aopPut(AOP(result),"a",offset);
6712 /*-----------------------------------------------------------------*/
6713 /* genDataPointerGet - generates code when ptr offset is known */
6714 /*-----------------------------------------------------------------*/
6715 static void genDataPointerGet (operand *left,
6721 int size , offset = 0;
6722 aopOp(result,ic,TRUE, FALSE);
6724 /* get the string representation of the name */
6725 l = aopGet(AOP(left),0,FALSE,TRUE,FALSE);
6726 size = AOP_SIZE(result);
6727 _startLazyDPSEvaluation();
6730 sprintf(buffer,"(%s + %d)",l+1,offset);
6732 sprintf(buffer,"%s",l+1);
6733 aopPut(AOP(result),buffer,offset++);
6735 _endLazyDPSEvaluation();
6737 freeAsmop(left,NULL,ic,TRUE);
6738 freeAsmop(result,NULL,ic,TRUE);
6741 /*-----------------------------------------------------------------*/
6742 /* genNearPointerGet - emitcode for near pointer fetch */
6743 /*-----------------------------------------------------------------*/
6744 static void genNearPointerGet (operand *left,
6751 sym_link *rtype, *retype, *letype;
6752 sym_link *ltype = operandType(left);
6755 rtype = operandType(result);
6756 retype= getSpec(rtype);
6757 letype= getSpec(ltype);
6759 aopOp(left,ic,FALSE, FALSE);
6761 /* if left is rematerialisable and
6762 result is not bit variable type and
6763 the left is pointer to data space i.e
6764 lower 128 bytes of space */
6765 if (AOP_TYPE(left) == AOP_IMMD &&
6766 !IS_BITVAR(retype) &&
6767 !IS_BITVAR(letype) &&
6768 DCL_TYPE(ltype) == POINTER) {
6769 genDataPointerGet (left,result,ic);
6773 /* if the value is already in a pointer register
6774 then don't need anything more */
6775 if (!AOP_INPREG(AOP(left))) {
6776 /* otherwise get a free pointer register */
6778 preg = getFreePtr(ic,&aop,FALSE);
6779 emitcode("mov","%s,%s",
6781 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6782 rname = preg->name ;
6784 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6786 freeAsmop(left,NULL,ic,TRUE);
6787 aopOp (result,ic,FALSE, FALSE);
6789 /* if bitfield then unpack the bits */
6790 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6791 genUnpackBits (result,rname,POINTER);
6793 /* we have can just get the values */
6794 int size = AOP_SIZE(result);
6798 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6800 emitcode("mov","a,@%s",rname);
6801 aopPut(AOP(result),"a",offset);
6803 sprintf(buffer,"@%s",rname);
6804 aopPut(AOP(result),buffer,offset);
6808 emitcode("inc","%s",rname);
6812 /* now some housekeeping stuff */
6814 /* we had to allocate for this iCode */
6815 freeAsmop(NULL,aop,ic,TRUE);
6817 /* we did not allocate which means left
6818 already in a pointer register, then
6819 if size > 0 && this could be used again
6820 we have to point it back to where it
6822 if (AOP_SIZE(result) > 1 &&
6823 !OP_SYMBOL(left)->remat &&
6824 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6826 int size = AOP_SIZE(result) - 1;
6828 emitcode("dec","%s",rname);
6833 freeAsmop(result,NULL,ic,TRUE);
6837 /*-----------------------------------------------------------------*/
6838 /* genPagedPointerGet - emitcode for paged pointer fetch */
6839 /*-----------------------------------------------------------------*/
6840 static void genPagedPointerGet (operand *left,
6847 sym_link *rtype, *retype, *letype;
6849 rtype = operandType(result);
6850 retype= getSpec(rtype);
6851 letype= getSpec(operandType(left));
6852 aopOp(left,ic,FALSE, FALSE);
6854 /* if the value is already in a pointer register
6855 then don't need anything more */
6856 if (!AOP_INPREG(AOP(left))) {
6857 /* otherwise get a free pointer register */
6859 preg = getFreePtr(ic,&aop,FALSE);
6860 emitcode("mov","%s,%s",
6862 aopGet(AOP(left),0,FALSE,TRUE,FALSE));
6863 rname = preg->name ;
6865 rname = aopGet(AOP(left),0,FALSE,FALSE,FALSE);
6867 freeAsmop(left,NULL,ic,TRUE);
6868 aopOp (result,ic,FALSE, FALSE);
6870 /* if bitfield then unpack the bits */
6871 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6872 genUnpackBits (result,rname,PPOINTER);
6874 /* we have can just get the values */
6875 int size = AOP_SIZE(result);
6880 emitcode("movx","a,@%s",rname);
6881 aopPut(AOP(result),"a",offset);
6886 emitcode("inc","%s",rname);
6890 /* now some housekeeping stuff */
6892 /* we had to allocate for this iCode */
6893 freeAsmop(NULL,aop,ic,TRUE);
6895 /* we did not allocate which means left
6896 already in a pointer register, then
6897 if size > 0 && this could be used again
6898 we have to point it back to where it
6900 if (AOP_SIZE(result) > 1 &&
6901 !OP_SYMBOL(left)->remat &&
6902 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6904 int size = AOP_SIZE(result) - 1;
6906 emitcode("dec","%s",rname);
6911 freeAsmop(result,NULL,ic,TRUE);
6916 /*-----------------------------------------------------------------*/
6917 /* genFarPointerGet - gget value from far space */
6918 /*-----------------------------------------------------------------*/
6919 static void genFarPointerGet (operand *left,
6920 operand *result, iCode *ic)
6923 sym_link *retype = getSpec(operandType(result));
6924 sym_link *letype = getSpec(operandType(left));
6925 D(emitcode(";", "genFarPointerGet"););
6927 aopOp(left,ic,FALSE, FALSE);
6929 /* if the operand is already in dptr
6930 then we do nothing else we move the value to dptr */
6931 if (AOP_TYPE(left) != AOP_STR) {
6932 /* if this is remateriazable */
6933 if (AOP_TYPE(left) == AOP_IMMD)
6935 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
6939 /* we need to get it byte by byte */
6940 _startLazyDPSEvaluation();
6941 if (AOP_TYPE(left) != AOP_DPTR)
6943 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
6944 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
6945 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6949 /* We need to generate a load to DPTR indirect through DPTR. */
6950 D(emitcode(";", "genFarPointerGet -- indirection special case."););
6951 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
6952 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
6953 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
6954 emitcode("pop", "dph");
6955 emitcode("pop", "dpl");
6957 _endLazyDPSEvaluation();
6960 /* so dptr know contains the address */
6961 freeAsmop(left,NULL,ic,TRUE);
6962 aopOp(result,ic,FALSE, TRUE);
6964 /* if bit then unpack */
6965 if (IS_BITVAR(retype) || IS_BITVAR(letype))
6966 genUnpackBits(result,"dptr",FPOINTER);
6968 size = AOP_SIZE(result);
6971 _startLazyDPSEvaluation();
6977 emitcode("movx","a,@dptr");
6979 emitcode("inc","dptr");
6981 aopPut(AOP(result),"a",offset++);
6983 _endLazyDPSEvaluation();
6986 freeAsmop(result,NULL,ic,TRUE);
6989 /*-----------------------------------------------------------------*/
6990 /* emitcodePointerGet - gget value from code space */
6991 /*-----------------------------------------------------------------*/
6992 static void emitcodePointerGet (operand *left,
6993 operand *result, iCode *ic)
6996 sym_link *retype = getSpec(operandType(result));
6998 aopOp(left,ic,FALSE, FALSE);
7000 /* if the operand is already in dptr
7001 then we do nothing else we move the value to dptr */
7002 if (AOP_TYPE(left) != AOP_STR) {
7003 /* if this is remateriazable */
7004 if (AOP_TYPE(left) == AOP_IMMD)
7006 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7009 { /* we need to get it byte by byte */
7010 _startLazyDPSEvaluation();
7011 if (AOP_TYPE(left) != AOP_DPTR)
7013 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7014 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7015 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7019 /* We need to generate a load to DPTR indirect through DPTR. */
7020 D(emitcode(";", "gencodePointerGet -- indirection special case."););
7021 emitcode("push", "%s", aopGet(AOP(left),0,FALSE,TRUE,TRUE));
7022 emitcode("push", "%s", aopGet(AOP(left),1,FALSE,TRUE,TRUE));
7023 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7024 emitcode("pop", "dph");
7025 emitcode("pop", "dpl");
7027 _endLazyDPSEvaluation();
7030 /* so dptr know contains the address */
7031 freeAsmop(left,NULL,ic,TRUE);
7032 aopOp(result,ic,FALSE, TRUE);
7034 /* if bit then unpack */
7035 if (IS_BITVAR(retype))
7036 genUnpackBits(result,"dptr",CPOINTER);
7038 size = AOP_SIZE(result);
7041 _startLazyDPSEvaluation();
7047 emitcode("clr","a");
7048 emitcode("movc","a,@a+dptr");
7050 emitcode("inc","dptr");
7051 aopPut(AOP(result),"a",offset++);
7053 _endLazyDPSEvaluation();
7056 freeAsmop(result,NULL,ic,TRUE);
7059 /*-----------------------------------------------------------------*/
7060 /* genGenPointerGet - gget value from generic pointer space */
7061 /*-----------------------------------------------------------------*/
7062 static void genGenPointerGet (operand *left,
7063 operand *result, iCode *ic)
7066 sym_link *retype = getSpec(operandType(result));
7067 sym_link *letype = getSpec(operandType(left));
7069 aopOp(left,ic,FALSE, TRUE);
7071 /* if the operand is already in dptr
7072 then we do nothing else we move the value to dptr */
7073 if (AOP_TYPE(left) != AOP_STR) {
7074 /* if this is remateriazable */
7075 if (AOP_TYPE(left) == AOP_IMMD) {
7076 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE,FALSE));
7077 emitcode("mov","b,#%d",pointerCode(retype));
7079 else { /* we need to get it byte by byte */
7080 _startLazyDPSEvaluation();
7081 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
7082 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
7083 emitcode("mov","dpx,%s",aopGet(AOP(left),2,FALSE,FALSE,TRUE));
7084 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE,TRUE));
7085 _endLazyDPSEvaluation();
7088 /* so dptr know contains the address */
7089 freeAsmop(left,NULL,ic,TRUE);
7090 aopOp(result,ic,FALSE, TRUE);
7092 /* if bit then unpack */
7093 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7094 genUnpackBits(result,"dptr",GPOINTER);
7096 size = AOP_SIZE(result);
7100 emitcode("lcall","__gptrget");
7101 aopPut(AOP(result),"a",offset++);
7103 emitcode("inc","dptr");
7107 freeAsmop(result,NULL,ic,TRUE);
7110 /*-----------------------------------------------------------------*/
7111 /* genPointerGet - generate code for pointer get */
7112 /*-----------------------------------------------------------------*/
7113 static void genPointerGet (iCode *ic)
7115 operand *left, *result ;
7116 sym_link *type, *etype;
7119 D(emitcode(";", "genPointerGet "););
7122 result = IC_RESULT(ic) ;
7124 /* depending on the type of pointer we need to
7125 move it to the correct pointer register */
7126 type = operandType(left);
7127 etype = getSpec(type);
7128 /* if left is of type of pointer then it is simple */
7129 if (IS_PTR(type) && !IS_FUNC(type->next))
7130 p_type = DCL_TYPE(type);
7132 /* we have to go by the storage class */
7133 p_type = PTR_TYPE(SPEC_OCLS(etype));
7136 /* now that we have the pointer type we assign
7137 the pointer values */
7142 genNearPointerGet (left,result,ic);
7146 genPagedPointerGet(left,result,ic);
7150 genFarPointerGet (left,result,ic);
7154 emitcodePointerGet (left,result,ic);
7158 genGenPointerGet (left,result,ic);
7164 /*-----------------------------------------------------------------*/
7165 /* genPackBits - generates code for packed bit storage */
7166 /*-----------------------------------------------------------------*/
7167 static void genPackBits (sym_link *etype ,
7169 char *rname, int p_type)
7177 blen = SPEC_BLEN(etype);
7178 bstr = SPEC_BSTR(etype);
7180 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7183 /* if the bit lenth is less than or */
7184 /* it exactly fits a byte then */
7185 if (SPEC_BLEN(etype) <= 8 ) {
7186 shCount = SPEC_BSTR(etype) ;
7188 /* shift left acc */
7191 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7196 emitcode ("mov","b,a");
7197 emitcode("mov","a,@%s",rname);
7201 emitcode ("mov","b,a");
7202 emitcode("movx","a,@dptr");
7206 emitcode ("push","b");
7207 emitcode ("push","acc");
7208 emitcode ("lcall","__gptrget");
7209 emitcode ("pop","b");
7213 emitcode ("anl","a,#0x%02x",(unsigned char)
7214 ((unsigned char)(0xFF << (blen+bstr)) |
7215 (unsigned char)(0xFF >> (8-bstr)) ) );
7216 emitcode ("orl","a,b");
7217 if (p_type == GPOINTER)
7218 emitcode("pop","b");
7224 emitcode("mov","@%s,a",rname);
7228 emitcode("movx","@dptr,a");
7232 emitcode("lcall","__gptrput");
7237 if ( SPEC_BLEN(etype) <= 8 )
7240 emitcode("inc","%s",rname);
7241 rLen = SPEC_BLEN(etype) ;
7243 /* now generate for lengths greater than one byte */
7246 l = aopGet(AOP(right),offset++,FALSE,TRUE,FALSE);
7256 emitcode("mov","@%s,a",rname);
7258 emitcode("mov","@%s,%s",rname,l);
7263 emitcode("movx","@dptr,a");
7268 emitcode("lcall","__gptrput");
7271 emitcode ("inc","%s",rname);
7276 /* last last was not complete */
7278 /* save the byte & read byte */
7281 emitcode ("mov","b,a");
7282 emitcode("mov","a,@%s",rname);
7286 emitcode ("mov","b,a");
7287 emitcode("movx","a,@dptr");
7291 emitcode ("push","b");
7292 emitcode ("push","acc");
7293 emitcode ("lcall","__gptrget");
7294 emitcode ("pop","b");
7298 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << rLen) );
7299 emitcode ("orl","a,b");
7302 if (p_type == GPOINTER)
7303 emitcode("pop","b");
7308 emitcode("mov","@%s,a",rname);
7312 emitcode("movx","@dptr,a");
7316 emitcode("lcall","__gptrput");
7320 /*-----------------------------------------------------------------*/
7321 /* genDataPointerSet - remat pointer to data space */
7322 /*-----------------------------------------------------------------*/
7323 static void genDataPointerSet(operand *right,
7327 int size, offset = 0 ;
7328 char *l, buffer[256];
7330 aopOp(right,ic,FALSE, FALSE);
7332 l = aopGet(AOP(result),0,FALSE,TRUE,FALSE);
7333 size = AOP_SIZE(right);
7336 sprintf(buffer,"(%s + %d)",l+1,offset);
7338 sprintf(buffer,"%s",l+1);
7339 emitcode("mov","%s,%s",buffer,
7340 aopGet(AOP(right),offset++,FALSE,FALSE,FALSE));
7343 freeAsmop(right,NULL,ic,TRUE);
7344 freeAsmop(result,NULL,ic,TRUE);
7347 /*-----------------------------------------------------------------*/
7348 /* genNearPointerSet - emitcode for near pointer put */
7349 /*-----------------------------------------------------------------*/
7350 static void genNearPointerSet (operand *right,
7357 sym_link *retype, *letype;
7358 sym_link *ptype = operandType(result);
7360 retype= getSpec(operandType(right));
7361 letype= getSpec(ptype);
7363 aopOp(result,ic,FALSE, FALSE);
7365 /* if the result is rematerializable &
7366 in data space & not a bit variable */
7367 if (AOP_TYPE(result) == AOP_IMMD &&
7368 DCL_TYPE(ptype) == POINTER &&
7369 !IS_BITVAR(retype) &&
7370 !IS_BITVAR(letype)) {
7371 genDataPointerSet (right,result,ic);
7375 /* if the value is already in a pointer register
7376 then don't need anything more */
7377 if (!AOP_INPREG(AOP(result))) {
7378 /* otherwise get a free pointer register */
7380 preg = getFreePtr(ic,&aop,FALSE);
7381 emitcode("mov","%s,%s",
7383 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7384 rname = preg->name ;
7386 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7388 freeAsmop(result,NULL,ic,TRUE);
7389 aopOp (right,ic,FALSE, FALSE);
7391 /* if bitfield then unpack the bits */
7392 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7393 genPackBits ((IS_BITVAR(retype) ? retype : letype),right,rname,POINTER);
7395 /* we have can just get the values */
7396 int size = AOP_SIZE(right);
7400 l = aopGet(AOP(right),offset,FALSE,TRUE,FALSE);
7403 emitcode("mov","@%s,a",rname);
7405 emitcode("mov","@%s,%s",rname,l);
7407 emitcode("inc","%s",rname);
7412 /* now some housekeeping stuff */
7414 /* we had to allocate for this iCode */
7415 freeAsmop(NULL,aop,ic,TRUE);
7417 /* we did not allocate which means left
7418 already in a pointer register, then
7419 if size > 0 && this could be used again
7420 we have to point it back to where it
7422 if (AOP_SIZE(right) > 1 &&
7423 !OP_SYMBOL(result)->remat &&
7424 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7426 int size = AOP_SIZE(right) - 1;
7428 emitcode("dec","%s",rname);
7433 freeAsmop(right,NULL,ic,TRUE);
7438 /*-----------------------------------------------------------------*/
7439 /* genPagedPointerSet - emitcode for Paged pointer put */
7440 /*-----------------------------------------------------------------*/
7441 static void genPagedPointerSet (operand *right,
7448 sym_link *retype, *letype;
7450 retype= getSpec(operandType(right));
7451 letype= getSpec(operandType(result));
7453 aopOp(result,ic,FALSE, FALSE);
7455 /* if the value is already in a pointer register
7456 then don't need anything more */
7457 if (!AOP_INPREG(AOP(result))) {
7458 /* otherwise get a free pointer register */
7460 preg = getFreePtr(ic,&aop,FALSE);
7461 emitcode("mov","%s,%s",
7463 aopGet(AOP(result),0,FALSE,TRUE,FALSE));
7464 rname = preg->name ;
7466 rname = aopGet(AOP(result),0,FALSE,FALSE,FALSE);
7468 freeAsmop(result,NULL,ic,TRUE);
7469 aopOp (right,ic,FALSE, FALSE);
7471 /* if bitfield then unpack the bits */
7472 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7473 genPackBits ((IS_BITVAR(retype) ? retype : letype) ,right,rname,PPOINTER);
7475 /* we have can just get the values */
7476 int size = AOP_SIZE(right);
7480 l = aopGet(AOP(right),offset,FALSE,TRUE,TRUE);
7483 emitcode("movx","@%s,a",rname);
7486 emitcode("inc","%s",rname);
7492 /* now some housekeeping stuff */
7494 /* we had to allocate for this iCode */
7495 freeAsmop(NULL,aop,ic,TRUE);
7497 /* we did not allocate which means left
7498 already in a pointer register, then
7499 if size > 0 && this could be used again
7500 we have to point it back to where it
7502 if (AOP_SIZE(right) > 1 &&
7503 !OP_SYMBOL(result)->remat &&
7504 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7506 int size = AOP_SIZE(right) - 1;
7508 emitcode("dec","%s",rname);
7513 freeAsmop(right,NULL,ic,TRUE);
7518 /*-----------------------------------------------------------------*/
7519 /* genFarPointerSet - set value from far space */
7520 /*-----------------------------------------------------------------*/
7521 static void genFarPointerSet (operand *right,
7522 operand *result, iCode *ic)
7525 sym_link *retype = getSpec(operandType(right));
7526 sym_link *letype = getSpec(operandType(result));
7528 aopOp(result,ic,FALSE, FALSE);
7530 /* if the operand is already in dptr
7531 then we do nothing else we move the value to dptr */
7532 if (AOP_TYPE(result) != AOP_STR) {
7533 /* if this is remateriazable */
7534 if (AOP_TYPE(result) == AOP_IMMD)
7535 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7538 /* we need to get it byte by byte */
7539 _startLazyDPSEvaluation();
7540 if (AOP_TYPE(result) != AOP_DPTR)
7542 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7543 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7544 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7548 /* We need to generate a load to DPTR indirect through DPTR. */
7549 D(emitcode(";", "genFarPointerSet -- indirection special case."););
7550 emitcode("push", "%s", aopGet(AOP(result),0,FALSE,TRUE,TRUE));
7551 emitcode("push", "%s", aopGet(AOP(result),1,FALSE,TRUE,TRUE));
7552 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7553 emitcode("pop", "dph");
7554 emitcode("pop", "dpl");
7556 _endLazyDPSEvaluation();
7559 /* so dptr know contains the address */
7560 freeAsmop(result,NULL,ic,TRUE);
7561 aopOp(right,ic,FALSE, TRUE);
7563 /* if bit then unpack */
7564 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7565 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",FPOINTER);
7567 size = AOP_SIZE(right);
7570 _startLazyDPSEvaluation();
7572 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7578 emitcode("movx","@dptr,a");
7580 emitcode("inc","dptr");
7582 _endLazyDPSEvaluation();
7585 freeAsmop(right,NULL,ic,TRUE);
7588 /*-----------------------------------------------------------------*/
7589 /* genGenPointerSet - set value from generic pointer space */
7590 /*-----------------------------------------------------------------*/
7591 static void genGenPointerSet (operand *right,
7592 operand *result, iCode *ic)
7595 sym_link *retype = getSpec(operandType(right));
7596 sym_link *letype = getSpec(operandType(result));
7598 aopOp(result,ic,FALSE, TRUE);
7600 /* if the operand is already in dptr
7601 then we do nothing else we move the value to dptr */
7602 if (AOP_TYPE(result) != AOP_STR) {
7603 _startLazyDPSEvaluation();
7604 /* if this is remateriazable */
7605 if (AOP_TYPE(result) == AOP_IMMD) {
7606 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7607 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE,FALSE));
7609 else { /* we need to get it byte by byte */
7610 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE,TRUE));
7611 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE,TRUE));
7612 emitcode("mov","dpx,%s",aopGet(AOP(result),2,FALSE,FALSE,TRUE));
7613 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE,TRUE));
7615 _endLazyDPSEvaluation();
7617 /* so dptr know contains the address */
7618 freeAsmop(result,NULL,ic,TRUE);
7619 aopOp(right,ic,FALSE, TRUE);
7621 /* if bit then unpack */
7622 if (IS_BITVAR(retype) || IS_BITVAR(letype))
7623 genPackBits((IS_BITVAR(retype)?retype:letype),right,"dptr",GPOINTER);
7625 size = AOP_SIZE(right);
7628 _startLazyDPSEvaluation();
7630 char *l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7636 emitcode("lcall","__gptrput");
7638 emitcode("inc","dptr");
7640 _endLazyDPSEvaluation();
7643 freeAsmop(right,NULL,ic,TRUE);
7646 /*-----------------------------------------------------------------*/
7647 /* genPointerSet - stores the value into a pointer location */
7648 /*-----------------------------------------------------------------*/
7649 static void genPointerSet (iCode *ic)
7651 operand *right, *result ;
7652 sym_link *type, *etype;
7655 D(emitcode(";", "genPointerSet "););
7657 right = IC_RIGHT(ic);
7658 result = IC_RESULT(ic) ;
7660 /* depending on the type of pointer we need to
7661 move it to the correct pointer register */
7662 type = operandType(result);
7663 etype = getSpec(type);
7664 /* if left is of type of pointer then it is simple */
7665 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7666 p_type = DCL_TYPE(type);
7669 /* we have to go by the storage class */
7670 p_type = PTR_TYPE(SPEC_OCLS(etype));
7673 /* now that we have the pointer type we assign
7674 the pointer values */
7679 genNearPointerSet (right,result,ic);
7683 genPagedPointerSet (right,result,ic);
7687 genFarPointerSet (right,result,ic);
7691 genGenPointerSet (right,result,ic);
7697 /*-----------------------------------------------------------------*/
7698 /* genIfx - generate code for Ifx statement */
7699 /*-----------------------------------------------------------------*/
7700 static void genIfx (iCode *ic, iCode *popIc)
7702 operand *cond = IC_COND(ic);
7705 D(emitcode(";", "genIfx "););
7707 aopOp(cond,ic,FALSE, FALSE);
7709 /* get the value into acc */
7710 if (AOP_TYPE(cond) != AOP_CRY)
7714 /* the result is now in the accumulator */
7715 freeAsmop(cond,NULL,ic,TRUE);
7717 /* if there was something to be popped then do it */
7721 /* if the condition is a bit variable */
7722 if (isbit && IS_ITEMP(cond) &&
7724 genIfxJump(ic,SPIL_LOC(cond)->rname);
7726 if (isbit && !IS_ITEMP(cond))
7727 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7734 /*-----------------------------------------------------------------*/
7735 /* genAddrOf - generates code for address of */
7736 /*-----------------------------------------------------------------*/
7737 static void genAddrOf (iCode *ic)
7739 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7742 D(emitcode(";", "genAddrOf "););
7744 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
7746 /* if the operand is on the stack then we
7747 need to get the stack offset of this
7750 /* if it has an offset then we need to compute
7753 emitcode("mov","a,_bp");
7754 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7755 aopPut(AOP(IC_RESULT(ic)),"a",0);
7757 /* we can just move _bp */
7758 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7760 /* fill the result with zero */
7761 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7764 if (options.stack10bit && size < (FPTRSIZE - 1))
7767 "*** warning: pointer to stack var truncated.\n");
7774 if (options.stack10bit && offset == 2)
7776 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7780 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7787 /* object not on stack then we need the name */
7788 size = AOP_SIZE(IC_RESULT(ic));
7792 char s[SDCC_NAME_MAX];
7794 sprintf(s,"#(%s >> %d)",
7798 sprintf(s,"#%s",sym->rname);
7799 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7803 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7807 /*-----------------------------------------------------------------*/
7808 /* genFarFarAssign - assignment when both are in far space */
7809 /*-----------------------------------------------------------------*/
7810 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7812 int size = AOP_SIZE(right);
7818 /* This is a net loss for size == 1, but a big gain
7821 D(emitcode(";", "genFarFarAssign (improved)"););
7823 aopOp(result,ic,TRUE, TRUE);
7825 _startLazyDPSEvaluation();
7829 aopGet(AOP(right),offset,FALSE,FALSE,FALSE), offset);
7832 _endLazyDPSEvaluation();
7833 freeAsmop(result,NULL,ic,FALSE);
7834 freeAsmop(right,NULL,ic,FALSE);
7838 D(emitcode(";", "genFarFarAssign "););
7840 /* first push the right side on to the stack */
7841 _startLazyDPSEvaluation();
7844 l = aopGet(AOP(right),offset++,FALSE,FALSE,TRUE);
7846 emitcode ("push","acc");
7849 freeAsmop(right,NULL,ic,FALSE);
7850 /* now assign DPTR to result */
7851 aopOp(result,ic,FALSE, FALSE);
7852 size = AOP_SIZE(result);
7855 emitcode ("pop","acc");
7856 aopPut(AOP(result),"a",--offset);
7858 freeAsmop(result,NULL,ic,FALSE);
7859 _endLazyDPSEvaluation();
7863 /*-----------------------------------------------------------------*/
7864 /* genAssign - generate code for assignment */
7865 /*-----------------------------------------------------------------*/
7866 static void genAssign (iCode *ic)
7868 operand *result, *right;
7870 unsigned long lit = 0L;
7872 D(emitcode(";", "genAssign "););
7874 result = IC_RESULT(ic);
7875 right = IC_RIGHT(ic) ;
7877 /* if they are the same */
7878 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7881 aopOp(right,ic,FALSE, FALSE);
7883 emitcode(";", "genAssign: resultIsFar = %s",
7884 isOperandInFarSpace(result) ?
7887 /* special case both in far space */
7888 if ((AOP_TYPE(right) == AOP_DPTR ||
7889 AOP_TYPE(right) == AOP_DPTR2) &&
7890 /* IS_TRUE_SYMOP(result) && */
7891 isOperandInFarSpace(result))
7893 genFarFarAssign (result,right,ic);
7897 aopOp(result,ic,TRUE, FALSE);
7899 /* if they are the same registers */
7900 if (sameRegs(AOP(right),AOP(result)))
7903 /* if the result is a bit */
7904 if (AOP_TYPE(result) == AOP_CRY) {
7906 /* if the right size is a literal then
7907 we know what the value is */
7908 if (AOP_TYPE(right) == AOP_LIT) {
7909 if (((int) operandLitValue(right)))
7910 aopPut(AOP(result),one,0);
7912 aopPut(AOP(result),zero,0);
7916 /* the right is also a bit variable */
7917 if (AOP_TYPE(right) == AOP_CRY) {
7918 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7919 aopPut(AOP(result),"c",0);
7925 aopPut(AOP(result),"a",0);
7929 /* bit variables done */
7931 size = AOP_SIZE(result);
7933 if(AOP_TYPE(right) == AOP_LIT)
7934 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7937 (AOP_TYPE(result) != AOP_REG) &&
7938 (AOP_TYPE(right) == AOP_LIT) &&
7939 !IS_FLOAT(operandType(right)))
7941 D(emitcode(";", "Kevin's better literal load code"););
7942 _startLazyDPSEvaluation();
7943 while (size && ((unsigned int)(lit >> (offset*8)) != 0))
7946 aopGet(AOP(right),offset,FALSE,FALSE,TRUE),
7951 /* And now fill the rest with zeros. */
7954 emitcode("clr","a");
7958 aopPut(AOP(result), "a", offset++);
7960 _endLazyDPSEvaluation();
7964 _startLazyDPSEvaluation();
7968 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
7972 _endLazyDPSEvaluation();
7976 freeAsmop (right,NULL,ic,FALSE);
7977 freeAsmop (result,NULL,ic,TRUE);
7980 /*-----------------------------------------------------------------*/
7981 /* genJumpTab - generates code for jump table */
7982 /*-----------------------------------------------------------------*/
7983 static void genJumpTab (iCode *ic)
7988 D(emitcode(";", "genJumpTab "););
7990 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
7991 /* get the condition into accumulator */
7992 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE,TRUE);
7994 /* multiply by four! */
7995 emitcode("add","a,acc");
7996 emitcode("add","a,acc");
7997 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7999 jtab = newiTempLabel(NULL);
8000 emitcode("mov","dptr,#%05d$",jtab->key+100);
8001 emitcode("jmp","@a+dptr");
8002 emitcode("","%05d$:",jtab->key+100);
8003 /* now generate the jump labels */
8004 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8005 jtab = setNextItem(IC_JTLABELS(ic)))
8006 emitcode("ljmp","%05d$",jtab->key+100);
8010 /*-----------------------------------------------------------------*/
8011 /* genCast - gen code for casting */
8012 /*-----------------------------------------------------------------*/
8013 static void genCast (iCode *ic)
8015 operand *result = IC_RESULT(ic);
8016 sym_link *ctype = operandType(IC_LEFT(ic));
8017 sym_link *rtype = operandType(IC_RIGHT(ic));
8018 operand *right = IC_RIGHT(ic);
8021 D(emitcode(";", "genCast "););
8023 /* if they are equivalent then do nothing */
8024 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8027 aopOp(right,ic,FALSE, FALSE) ;
8028 aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
8030 /* if the result is a bit */
8031 if (AOP_TYPE(result) == AOP_CRY) {
8032 /* if the right size is a literal then
8033 we know what the value is */
8034 if (AOP_TYPE(right) == AOP_LIT) {
8035 if (((int) operandLitValue(right)))
8036 aopPut(AOP(result),one,0);
8038 aopPut(AOP(result),zero,0);
8043 /* the right is also a bit variable */
8044 if (AOP_TYPE(right) == AOP_CRY) {
8045 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8046 aopPut(AOP(result),"c",0);
8052 aopPut(AOP(result),"a",0);
8056 /* if they are the same size : or less */
8057 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8059 /* if they are in the same place */
8060 if (sameRegs(AOP(right),AOP(result)))
8063 /* if they in different places then copy */
8064 size = AOP_SIZE(result);
8066 _startLazyDPSEvaluation();
8069 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8073 _endLazyDPSEvaluation();
8078 /* if the result is of type pointer */
8079 if (IS_PTR(ctype)) {
8082 sym_link *type = operandType(right);
8084 /* pointer to generic pointer */
8085 if (IS_GENPTR(ctype)) {
8090 p_type = DCL_TYPE(type);
8094 #if OLD_CAST_BEHAVIOR
8095 /* KV: we are converting a non-pointer type to
8096 * a generic pointer. This (ifdef'd out) code
8097 * says that the resulting generic pointer
8098 * should have the same class as the storage
8099 * location of the non-pointer variable.
8101 * For example, converting an int (which happens
8102 * to be stored in DATA space) to a pointer results
8103 * in a DATA generic pointer; if the original int
8104 * in XDATA space, so will be the resulting pointer.
8106 * I don't like that behavior, and thus this change:
8107 * all such conversions will be forced to XDATA and
8108 * throw a warning. If you want some non-XDATA
8109 * type, or you want to suppress the warning, you
8110 * must go through an intermediate cast, like so:
8112 * char _generic *gp = (char _xdata *)(intVar);
8114 sym_link *etype = getSpec(type);
8116 /* we have to go by the storage class */
8117 if (SPEC_OCLS(etype) != generic)
8119 p_type = PTR_TYPE(SPEC_OCLS(etype));
8124 /* Converting unknown class (i.e. register variable)
8125 * to generic pointer. This is not good, but
8126 * we'll make a guess (and throw a warning).
8129 werror(W_INT_TO_GEN_PTR_CAST);
8133 /* the first two bytes are known */
8134 size = GPTRSIZE - 1;
8136 _startLazyDPSEvaluation();
8139 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8143 _endLazyDPSEvaluation();
8145 /* the last byte depending on type */
8162 /* this should never happen */
8163 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8164 "got unknown pointer type");
8167 aopPut(AOP(result),l, GPTRSIZE - 1);
8171 /* just copy the pointers */
8172 size = AOP_SIZE(result);
8174 _startLazyDPSEvaluation();
8177 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8181 _endLazyDPSEvaluation();
8185 /* so we now know that the size of destination is greater
8186 than the size of the source */
8187 /* we move to result for the size of source */
8188 size = AOP_SIZE(right);
8190 _startLazyDPSEvaluation();
8193 aopGet(AOP(right),offset,FALSE,FALSE,FALSE),
8197 _endLazyDPSEvaluation();
8199 /* now depending on the sign of the source && destination */
8200 size = AOP_SIZE(result) - AOP_SIZE(right);
8201 /* if unsigned or not an integral type */
8202 /* also, if the source is a bit, we don't need to sign extend, because
8203 * it can't possibly have set the sign bit.
8205 if (SPEC_USIGN(rtype) || !IS_SPEC(rtype) || AOP_TYPE(right) == AOP_CRY)
8209 aopPut(AOP(result),zero,offset++);
8214 /* we need to extend the sign :{ */
8215 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
8218 emitcode("rlc","a");
8219 emitcode("subb","a,acc");
8221 aopPut(AOP(result),"a",offset++);
8224 /* we are done hurray !!!! */
8227 freeAsmop(right,NULL,ic,TRUE);
8228 freeAsmop(result,NULL,ic,TRUE);
8232 /*-----------------------------------------------------------------*/
8233 /* genDjnz - generate decrement & jump if not zero instrucion */
8234 /*-----------------------------------------------------------------*/
8235 static int genDjnz (iCode *ic, iCode *ifx)
8241 /* if the if condition has a false label
8242 then we cannot save */
8246 /* if the minus is not of the form
8248 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8249 !IS_OP_LITERAL(IC_RIGHT(ic)))
8252 if (operandLitValue(IC_RIGHT(ic)) != 1)
8255 /* if the size of this greater than one then no
8257 if (getSize(operandType(IC_RESULT(ic))) > 1)
8260 /* otherwise we can save BIG */
8261 lbl = newiTempLabel(NULL);
8262 lbl1= newiTempLabel(NULL);
8264 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8266 if (IS_AOP_PREG(IC_RESULT(ic))) {
8267 emitcode("dec","%s",
8268 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8269 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
8270 emitcode("jnz","%05d$",lbl->key+100);
8272 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE),
8275 emitcode ("sjmp","%05d$",lbl1->key+100);
8276 emitcode ("","%05d$:",lbl->key+100);
8277 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
8278 emitcode ("","%05d$:",lbl1->key+100);
8280 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8285 /*-----------------------------------------------------------------*/
8286 /* genReceive - generate code for a receive iCode */
8287 /*-----------------------------------------------------------------*/
8288 static void genReceive (iCode *ic)
8291 D(emitcode(";", "genReceive "););
8293 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8294 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8295 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8296 int size = getSize(operandType(IC_RESULT(ic)));
8297 int offset = fReturnSize_390 - size;
8299 emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
8300 fReturn[fReturnSize_390 - offset - 1] : "acc"));
8303 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8304 size = AOP_SIZE(IC_RESULT(ic));
8307 emitcode ("pop","acc");
8308 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8313 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
8315 assignResultValue(IC_RESULT(ic));
8318 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8321 /*-----------------------------------------------------------------*/
8322 /* gen390Code - generate code for Dallas 390 based controllers */
8323 /*-----------------------------------------------------------------*/
8324 void gen390Code (iCode *lic)
8329 lineHead = lineCurr = NULL;
8333 /* print the allocation information */
8335 printAllocInfo( currFunc, codeOutFile);
8337 /* if debug information required */
8338 if (options.debug && currFunc) {
8339 //jwk if (currFunc) {
8340 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8342 if (IS_STATIC(currFunc->etype))
8343 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
8345 emitcode("","G$%s$0$0 ==.",currFunc->name);
8348 /* stack pointer name */
8349 if (options.useXstack)
8355 for (ic = lic ; ic ; ic = ic->next ) {
8357 if ( cln != ic->lineno ) {
8358 if ( options.debug ) {
8360 emitcode("","C$%s$%d$%d$%d ==.",
8361 ic->filename,ic->lineno,
8362 ic->level,ic->block);
8365 emitcode(";","%s %d",ic->filename,ic->lineno);
8368 /* if the result is marked as
8369 spilt and rematerializable or code for
8370 this has already been generated then
8372 if (resultRemat(ic) || ic->generated )
8375 /* depending on the operation */
8394 /* IPOP happens only when trying to restore a
8395 spilt live range, if there is an ifx statement
8396 following this pop then the if statement might
8397 be using some of the registers being popped which
8398 would destory the contents of the register so
8399 we need to check for this condition and handle it */
8401 ic->next->op == IFX &&
8402 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8403 genIfx (ic->next,ic);
8421 genEndFunction (ic);
8441 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8458 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8462 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8469 /* note these two are xlated by algebraic equivalence
8470 during parsing SDCC.y */
8471 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8472 "got '>=' or '<=' shouldn't have come here");
8476 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8488 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8492 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8496 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8523 case GET_VALUE_AT_ADDRESS:
8528 if (POINTER_SET(ic))
8555 addSet(&_G.sendSet,ic);
8560 /* piCode(ic,stdout); */
8566 /* now we are ready to call the
8567 peep hole optimizer */
8568 if (!options.nopeep)
8569 peepHole (&lineHead);
8571 /* now do the actual printing */
8572 printLine (lineHead,codeOutFile);