1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
37 #ifdef HAVE_SYS_ISA_DEFS_H
38 #include <sys/isa_defs.h>
44 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
45 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #include "SDCCpeeph.h"
55 char *aopLiteral (value *val, int offset);
58 /* this is the down and dirty file with all kinds of
59 kludgy & hacky stuff. This is what it is all about
60 CODE GENERATION for a specific MCU . some of the
61 routines may be reusable, will have to see */
63 static char *zero = "#0x00";
64 static char *one = "#0x01";
67 char *fReturn8051[] = {"dpl","dph","b","a" };
68 char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
69 unsigned fReturnSize = 4; /* shared with ralloc.c */
70 char **fReturn = fReturn8051;
71 static char *accUse[] = {"a","b"};
73 static short rbank = -1;
85 extern int mcs51_ptrRegReq ;
86 extern int mcs51_nRegs;
87 extern FILE *codeOutFile;
88 static void saverbank (int, iCode *,bool);
89 #define RESULTONSTACK(x) \
90 (IC_RESULT(x) && IC_RESULT(x)->aop && \
91 IC_RESULT(x)->aop->type == AOP_STK )
93 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
94 #define CLRC emitcode("clr","c");
96 static lineNode *lineHead = NULL;
97 static lineNode *lineCurr = NULL;
99 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
100 0xE0, 0xC0, 0x80, 0x00};
101 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
102 0x07, 0x03, 0x01, 0x00};
109 /*-----------------------------------------------------------------*/
110 /* emitcode - writes the code into a file : for now it is simple */
111 /*-----------------------------------------------------------------*/
112 static void emitcode (char *inst,char *fmt, ...)
115 char lb[MAX_INLINEASM];
122 sprintf(lb,"%s\t",inst);
124 sprintf(lb,"%s",inst);
125 vsprintf(lb+(strlen(lb)),fmt,ap);
129 while (isspace(*lbp)) lbp++;
132 lineCurr = (lineCurr ?
133 connectLine(lineCurr,newLineNode(lb)) :
134 (lineHead = newLineNode(lb)));
135 lineCurr->isInline = _G.inLine;
136 lineCurr->isDebug = _G.debugLine;
140 /*-----------------------------------------------------------------*/
141 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
142 /*-----------------------------------------------------------------*/
143 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
145 bool r0iu = FALSE , r1iu = FALSE;
146 bool r0ou = FALSE , r1ou = FALSE;
148 /* the logic: if r0 & r1 used in the instruction
149 then we are in trouble otherwise */
151 /* first check if r0 & r1 are used by this
152 instruction, in which case we are in trouble */
153 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
154 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
159 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
160 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
162 /* if no usage of r0 then return it */
163 if (!r0iu && !r0ou) {
164 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
165 (*aopp)->type = AOP_R0;
167 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
170 /* if no usage of r1 then return it */
171 if (!r1iu && !r1ou) {
172 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
173 (*aopp)->type = AOP_R1;
175 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
178 /* now we know they both have usage */
179 /* if r0 not used in this instruction */
181 /* push it if not already pushed */
183 emitcode ("push","%s",
184 mcs51_regWithIdx(R0_IDX)->dname);
188 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
189 (*aopp)->type = AOP_R0;
191 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
194 /* if r1 not used then */
197 /* push it if not already pushed */
199 emitcode ("push","%s",
200 mcs51_regWithIdx(R1_IDX)->dname);
204 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
205 (*aopp)->type = AOP_R1;
206 return mcs51_regWithIdx(R1_IDX);
210 /* I said end of world but not quite end of world yet */
211 /* if this is a result then we can push it on the stack*/
213 (*aopp)->type = AOP_STK;
218 /* other wise this is true end of the world */
219 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
220 "getFreePtr should never reach here");
224 /*-----------------------------------------------------------------*/
225 /* newAsmop - creates a new asmOp */
226 /*-----------------------------------------------------------------*/
227 static asmop *newAsmop (short type)
231 ALLOC(aop,sizeof(asmop));
236 static void genSetDPTR(int n)
240 emitcode(";", "Select standard DPTR");
241 emitcode("mov", "dps, #0x00");
245 emitcode(";", "Select alternate DPTR");
246 emitcode("mov", "dps, #0x01");
250 /*-----------------------------------------------------------------*/
251 /* pointerCode - returns the code for a pointer type */
252 /*-----------------------------------------------------------------*/
253 static int pointerCode (link *etype)
256 return PTR_TYPE(SPEC_OCLS(etype));
260 /*-----------------------------------------------------------------*/
261 /* aopForSym - for a true symbol */
262 /*-----------------------------------------------------------------*/
263 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
266 memmap *space= SPEC_OCLS(sym->etype);
268 /* if already has one */
272 /* assign depending on the storage class */
273 /* if it is on the stack or indirectly addressable */
274 /* space we need to assign either r0 or r1 to it */
275 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
276 sym->aop = aop = newAsmop(0);
277 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
278 aop->size = getSize(sym->type);
280 /* now assign the address of the variable to
281 the pointer register */
282 if (aop->type != AOP_STK) {
286 emitcode("push","acc");
288 emitcode("mov","a,_bp");
289 emitcode("add","a,#0x%02x",
291 ((char)(sym->stack - _G.nRegsSaved )) :
292 ((char)sym->stack)) & 0xff);
293 emitcode("mov","%s,a",
294 aop->aopu.aop_ptr->name);
297 emitcode("pop","acc");
299 emitcode("mov","%s,#%s",
300 aop->aopu.aop_ptr->name,
302 aop->paged = space->paged;
304 aop->aopu.aop_stk = sym->stack;
308 if (sym->onStack && options.stack10bit)
310 /* It's on the 10 bit stack, which is located in
315 emitcode("push","acc");
317 emitcode("mov","a,_bp");
318 emitcode("add","a,#0x%02x",
320 ((char)(sym->stack - _G.nRegsSaved )) :
321 ((char)sym->stack)) & 0xff);
324 emitcode ("mov","dpx1,#0x40");
325 emitcode ("mov","dph1,#0x00");
326 emitcode ("mov","dpl1, a");
330 emitcode("pop","acc");
332 sym->aop = aop = newAsmop(AOP_DPTR2);
333 aop->size = getSize(sym->type);
337 /* if in bit space */
338 if (IN_BITSPACE(space)) {
339 sym->aop = aop = newAsmop (AOP_CRY);
340 aop->aopu.aop_dir = sym->rname ;
341 aop->size = getSize(sym->type);
344 /* if it is in direct space */
345 if (IN_DIRSPACE(space)) {
346 sym->aop = aop = newAsmop (AOP_DIR);
347 aop->aopu.aop_dir = sym->rname ;
348 aop->size = getSize(sym->type);
352 /* special case for a function */
353 if (IS_FUNC(sym->type)) {
354 sym->aop = aop = newAsmop(AOP_IMMD);
355 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
356 strcpy(aop->aopu.aop_immd,sym->rname);
357 aop->size = FPTRSIZE;
361 /* only remaining is far space */
362 /* in which case DPTR gets the address */
363 sym->aop = aop = newAsmop(AOP_DPTR);
364 emitcode ("mov","dptr,#%s", sym->rname);
365 aop->size = getSize(sym->type);
367 /* if it is in code space */
368 if (IN_CODESPACE(space))
374 /*-----------------------------------------------------------------*/
375 /* aopForRemat - rematerialzes an object */
376 /*-----------------------------------------------------------------*/
377 static asmop *aopForRemat (symbol *sym)
379 iCode *ic = sym->rematiCode;
380 asmop *aop = newAsmop(AOP_IMMD);
385 val += operandLitValue(IC_RIGHT(ic));
386 else if (ic->op == '-')
387 val -= operandLitValue(IC_RIGHT(ic));
391 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
395 sprintf(buffer,"(%s %c 0x%04x)",
396 OP_SYMBOL(IC_LEFT(ic))->rname,
397 val >= 0 ? '+' : '-',
400 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
402 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
403 strcpy(aop->aopu.aop_immd,buffer);
407 /*-----------------------------------------------------------------*/
408 /* regsInCommon - two operands have some registers in common */
409 /*-----------------------------------------------------------------*/
410 static bool regsInCommon (operand *op1, operand *op2)
415 /* if they have registers in common */
416 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
419 sym1 = OP_SYMBOL(op1);
420 sym2 = OP_SYMBOL(op2);
422 if (sym1->nRegs == 0 || sym2->nRegs == 0)
425 for (i = 0 ; i < sym1->nRegs ; i++) {
430 for (j = 0 ; j < sym2->nRegs ;j++ ) {
434 if (sym2->regs[j] == sym1->regs[i])
442 /*-----------------------------------------------------------------*/
443 /* operandsEqu - equivalent */
444 /*-----------------------------------------------------------------*/
445 static bool operandsEqu ( operand *op1, operand *op2)
449 /* if they not symbols */
450 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
453 sym1 = OP_SYMBOL(op1);
454 sym2 = OP_SYMBOL(op2);
456 /* if both are itemps & one is spilt
457 and the other is not then false */
458 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
459 sym1->isspilt != sym2->isspilt )
462 /* if they are the same */
466 if (strcmp(sym1->rname,sym2->rname) == 0)
470 /* if left is a tmp & right is not */
474 (sym1->usl.spillLoc == sym2))
481 (sym2->usl.spillLoc == sym1))
487 /*-----------------------------------------------------------------*/
488 /* sameRegs - two asmops have the same registers */
489 /*-----------------------------------------------------------------*/
490 static bool sameRegs (asmop *aop1, asmop *aop2 )
497 if (aop1->type != AOP_REG ||
498 aop2->type != AOP_REG )
501 if (aop1->size != aop2->size )
504 for (i = 0 ; i < aop1->size ; i++ )
505 if (aop1->aopu.aop_reg[i] !=
506 aop2->aopu.aop_reg[i] )
512 /*-----------------------------------------------------------------*/
513 /* aopOp - allocates an asmop for an operand : */
514 /*-----------------------------------------------------------------*/
515 static void aopOp (operand *op, iCode *ic, bool result)
524 /* if this a literal */
525 if (IS_OP_LITERAL(op)) {
526 op->aop = aop = newAsmop(AOP_LIT);
527 aop->aopu.aop_lit = op->operand.valOperand;
528 aop->size = getSize(operandType(op));
532 /* if already has a asmop then continue */
536 /* if the underlying symbol has a aop */
537 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
538 op->aop = OP_SYMBOL(op)->aop;
542 /* if this is a true symbol */
543 if (IS_TRUE_SYMOP(op)) {
544 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
548 /* this is a temporary : this has
554 e) can be a return use only */
559 /* if the type is a conditional */
560 if (sym->regType == REG_CND) {
561 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
566 /* if it is spilt then two situations
568 b) has a spill location */
569 if (sym->isspilt || sym->nRegs == 0) {
571 /* rematerialize it NOW */
573 sym->aop = op->aop = aop =
575 aop->size = getSize(sym->type);
581 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
582 aop->size = getSize(sym->type);
583 for ( i = 0 ; i < 2 ; i++ )
584 aop->aopu.aop_str[i] = accUse[i];
590 aop = op->aop = sym->aop = newAsmop(AOP_STR);
591 aop->size = getSize(sym->type);
592 for ( i = 0 ; i < fReturnSize ; i++ )
593 aop->aopu.aop_str[i] = fReturn[i];
597 /* else spill location */
598 sym->aop = op->aop = aop =
599 aopForSym(ic,sym->usl.spillLoc,result);
600 aop->size = getSize(sym->type);
604 /* must be in a register */
605 sym->aop = op->aop = aop = newAsmop(AOP_REG);
606 aop->size = sym->nRegs;
607 for ( i = 0 ; i < sym->nRegs ;i++)
608 aop->aopu.aop_reg[i] = sym->regs[i];
611 /*-----------------------------------------------------------------*/
612 /* freeAsmop - free up the asmop given to an operand */
613 /*----------------------------------------------------------------*/
614 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
631 /* depending on the asmop type only three cases need work AOP_RO
632 , AOP_R1 && AOP_STK */
637 emitcode ("pop","ar0");
641 bitVectUnSetBit(ic->rUsed,R0_IDX);
647 emitcode ("pop","ar1");
651 bitVectUnSetBit(ic->rUsed,R1_IDX);
657 int stk = aop->aopu.aop_stk + aop->size;
658 bitVectUnSetBit(ic->rUsed,R0_IDX);
659 bitVectUnSetBit(ic->rUsed,R1_IDX);
661 getFreePtr(ic,&aop,FALSE);
663 if (options.stack10bit)
665 /* I'm not sure what to do here yet... */
668 "*** Warning: probably generating bad code for "
669 "10 bit stack mode.\n");
673 emitcode ("mov","a,_bp");
674 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
675 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
677 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
681 emitcode("pop","acc");
682 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
684 emitcode("dec","%s",aop->aopu.aop_ptr->name);
687 freeAsmop(op,NULL,ic,TRUE);
689 emitcode("pop","ar0");
694 emitcode("pop","ar1");
701 /* all other cases just dealloc */
705 OP_SYMBOL(op)->aop = NULL;
706 /* if the symbol has a spill */
708 SPIL_LOC(op)->aop = NULL;
713 /*-----------------------------------------------------------------*/
714 /* aopGet - for fetching value of the aop */
715 /*-----------------------------------------------------------------*/
716 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
721 /* offset is greater than
723 if (offset > (aop->size - 1) &&
724 aop->type != AOP_LIT)
727 /* depending on type */
732 /* if we need to increment it */
733 while (offset > aop->coff) {
734 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
738 while (offset < aop->coff) {
739 emitcode("dec","%s",aop->aopu.aop_ptr->name);
745 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
746 return (dname ? "acc" : "a");
748 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
749 ALLOC_ATOMIC(rs,strlen(s)+1);
756 if (aop->type == AOP_DPTR2)
761 while (offset > aop->coff) {
762 emitcode ("inc","dptr");
766 while (offset < aop->coff) {
767 emitcode("lcall","__decdptr");
774 emitcode("movc","a,@a+dptr");
777 emitcode("movx","a,@dptr");
780 if (aop->type == AOP_DPTR2)
785 return (dname ? "acc" : "a");
790 sprintf (s,"#%s",aop->aopu.aop_immd);
793 sprintf(s,"#(%s >> %d)",
799 ALLOC_ATOMIC(rs,strlen(s)+1);
805 sprintf(s,"(%s + %d)",
809 sprintf(s,"%s",aop->aopu.aop_dir);
810 ALLOC_ATOMIC(rs,strlen(s)+1);
816 return aop->aopu.aop_reg[offset]->dname;
818 return aop->aopu.aop_reg[offset]->name;
822 emitcode("mov","c,%s",aop->aopu.aop_dir);
823 emitcode("rlc","a") ;
824 return (dname ? "acc" : "a");
827 if (!offset && dname)
829 return aop->aopu.aop_str[offset];
832 return aopLiteral (aop->aopu.aop_lit,offset);
836 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
840 return aop->aopu.aop_str[offset];
844 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
845 "aopget got unsupported aop->type");
848 /*-----------------------------------------------------------------*/
849 /* aopPut - puts a string for a aop */
850 /*-----------------------------------------------------------------*/
851 static void aopPut (asmop *aop, char *s, int offset)
856 if (aop->size && offset > ( aop->size - 1)) {
857 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
858 "aopPut got offset > aop->size");
862 /* will assign value to value */
863 /* depending on where it is ofcourse */
867 sprintf(d,"(%s + %d)",
868 aop->aopu.aop_dir,offset);
870 sprintf(d,"%s",aop->aopu.aop_dir);
873 emitcode("mov","%s,%s",d,s);
878 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
879 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
881 strcmp(s,"r0") == 0 ||
882 strcmp(s,"r1") == 0 ||
883 strcmp(s,"r2") == 0 ||
884 strcmp(s,"r3") == 0 ||
885 strcmp(s,"r4") == 0 ||
886 strcmp(s,"r5") == 0 ||
887 strcmp(s,"r6") == 0 ||
888 strcmp(s,"r7") == 0 )
889 emitcode("mov","%s,%s",
890 aop->aopu.aop_reg[offset]->dname,s);
892 emitcode("mov","%s,%s",
893 aop->aopu.aop_reg[offset]->name,s);
900 if (aop->type == AOP_DPTR2)
906 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
907 "aopPut writting to code space");
911 while (offset > aop->coff) {
913 emitcode ("inc","dptr");
916 while (offset < aop->coff) {
918 emitcode("lcall","__decdptr");
923 /* if not in accumulater */
926 emitcode ("movx","@dptr,a");
928 if (aop->type == AOP_DPTR2)
936 while (offset > aop->coff) {
938 emitcode("inc","%s",aop->aopu.aop_ptr->name);
940 while (offset < aop->coff) {
942 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
948 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
953 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
955 if (strcmp(s,"r0") == 0 ||
956 strcmp(s,"r1") == 0 ||
957 strcmp(s,"r2") == 0 ||
958 strcmp(s,"r3") == 0 ||
959 strcmp(s,"r4") == 0 ||
960 strcmp(s,"r5") == 0 ||
961 strcmp(s,"r6") == 0 ||
962 strcmp(s,"r7") == 0 ) {
964 sprintf(buffer,"a%s",s);
965 emitcode("mov","@%s,%s",
966 aop->aopu.aop_ptr->name,buffer);
968 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
973 if (strcmp(s,"a") == 0)
974 emitcode("push","acc");
976 emitcode("push","%s",s);
981 /* if bit variable */
982 if (!aop->aopu.aop_dir) {
987 emitcode("clr","%s",aop->aopu.aop_dir);
990 emitcode("setb","%s",aop->aopu.aop_dir);
993 emitcode("mov","%s,c",aop->aopu.aop_dir);
995 lbl = newiTempLabel(NULL);
1000 emitcode("clr","c");
1001 emitcode("jz","%05d$",lbl->key+100);
1002 emitcode("cpl","c");
1003 emitcode("","%05d$:",lbl->key+100);
1004 emitcode("mov","%s,c",aop->aopu.aop_dir);
1011 if (strcmp(aop->aopu.aop_str[offset],s))
1012 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1017 if (!offset && (strcmp(s,"acc") == 0))
1020 if (strcmp(aop->aopu.aop_str[offset],s))
1021 emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
1025 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1026 "aopPut got unsupported aop->type");
1034 /*-----------------------------------------------------------------*/
1035 /* pointToEnd :- points to the last byte of the operand */
1036 /*-----------------------------------------------------------------*/
1037 static void pointToEnd (asmop *aop)
1043 aop->coff = count = (aop->size - 1);
1044 switch (aop->type) {
1048 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1052 emitcode("inc","dptr");
1059 /*-----------------------------------------------------------------*/
1060 /* reAdjustPreg - points a register back to where it should */
1061 /*-----------------------------------------------------------------*/
1062 static void reAdjustPreg (asmop *aop)
1067 if ((size = aop->size) <= 1)
1070 switch (aop->type) {
1074 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1078 if (aop->type == AOP_DPTR2)
1084 emitcode("lcall","__decdptr");
1087 if (aop->type == AOP_DPTR2)
1097 #define AOP(op) op->aop
1098 #define AOP_TYPE(op) AOP(op)->type
1099 #define AOP_SIZE(op) AOP(op)->size
1100 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1101 AOP_TYPE(x) == AOP_R0))
1103 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1104 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1107 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1108 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1109 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1111 /*-----------------------------------------------------------------*/
1112 /* genNotFloat - generates not for float operations */
1113 /*-----------------------------------------------------------------*/
1114 static void genNotFloat (operand *op, operand *res)
1120 /* we will put 127 in the first byte of
1122 aopPut(AOP(res),"#127",0);
1123 size = AOP_SIZE(op) - 1;
1126 l = aopGet(op->aop,offset++,FALSE,FALSE);
1130 emitcode("orl","a,%s",
1132 offset++,FALSE,FALSE));
1134 tlbl = newiTempLabel(NULL);
1136 tlbl = newiTempLabel(NULL);
1137 aopPut(res->aop,one,1);
1138 emitcode("jz","%05d$",(tlbl->key+100));
1139 aopPut(res->aop,zero,1);
1140 emitcode("","%05d$:",(tlbl->key+100));
1142 size = res->aop->size - 2;
1144 /* put zeros in the rest */
1146 aopPut(res->aop,zero,offset++);
1149 /*-----------------------------------------------------------------*/
1150 /* opIsGptr: returns non-zero if the passed operand is */
1151 /* a generic pointer type. */
1152 /*-----------------------------------------------------------------*/
1153 static int opIsGptr(operand *op)
1155 link *type = operandType(op);
1157 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1164 /*-----------------------------------------------------------------*/
1165 /* getDataSize - get the operand data size */
1166 /*-----------------------------------------------------------------*/
1167 static int getDataSize(operand *op)
1170 size = AOP_SIZE(op);
1171 if (size == GPTRSIZE)
1173 link *type = operandType(op);
1174 if (IS_GENPTR(type))
1176 /* generic pointer; arithmetic operations
1177 * should ignore the high byte (pointer type).
1185 /*-----------------------------------------------------------------*/
1186 /* outAcc - output Acc */
1187 /*-----------------------------------------------------------------*/
1188 static void outAcc(operand *result)
1191 size = getDataSize(result);
1193 aopPut(AOP(result),"a",0);
1196 /* unsigned or positive */
1198 aopPut(AOP(result),zero,offset++);
1203 /*-----------------------------------------------------------------*/
1204 /* outBitC - output a bit C */
1205 /*-----------------------------------------------------------------*/
1206 static void outBitC(operand *result)
1208 /* if the result is bit */
1209 if (AOP_TYPE(result) == AOP_CRY)
1210 aopPut(AOP(result),"c",0);
1212 emitcode("clr","a");
1213 emitcode("rlc","a");
1218 /*-----------------------------------------------------------------*/
1219 /* toBoolean - emit code for orl a,operator(sizeop) */
1220 /*-----------------------------------------------------------------*/
1221 static void toBoolean(operand *oper)
1223 int size = AOP_SIZE(oper) - 1;
1225 MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
1227 emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
1231 /*-----------------------------------------------------------------*/
1232 /* genNot - generate code for ! operation */
1233 /*-----------------------------------------------------------------*/
1234 static void genNot (iCode *ic)
1237 link *optype = operandType(IC_LEFT(ic));
1239 /* assign asmOps to operand & result */
1240 aopOp (IC_LEFT(ic),ic,FALSE);
1241 aopOp (IC_RESULT(ic),ic,TRUE);
1243 /* if in bit space then a special case */
1244 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1245 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1246 emitcode("cpl","c");
1247 outBitC(IC_RESULT(ic));
1251 /* if type float then do float */
1252 if (IS_FLOAT(optype)) {
1253 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1257 toBoolean(IC_LEFT(ic));
1259 tlbl = newiTempLabel(NULL);
1260 emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
1261 emitcode("","%05d$:",tlbl->key+100);
1262 outBitC(IC_RESULT(ic));
1265 /* release the aops */
1266 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1267 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1271 /*-----------------------------------------------------------------*/
1272 /* genCpl - generate code for complement */
1273 /*-----------------------------------------------------------------*/
1274 static void genCpl (iCode *ic)
1280 /* assign asmOps to operand & result */
1281 aopOp (IC_LEFT(ic),ic,FALSE);
1282 aopOp (IC_RESULT(ic),ic,TRUE);
1284 /* if both are in bit space then
1286 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1287 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1289 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1290 emitcode("cpl","c");
1291 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1295 size = AOP_SIZE(IC_RESULT(ic));
1297 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1299 emitcode("cpl","a");
1300 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1305 /* release the aops */
1306 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1307 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1310 /*-----------------------------------------------------------------*/
1311 /* genUminusFloat - unary minus for floating points */
1312 /*-----------------------------------------------------------------*/
1313 static void genUminusFloat(operand *op,operand *result)
1315 int size ,offset =0 ;
1317 /* for this we just need to flip the
1318 first it then copy the rest in place */
1319 size = AOP_SIZE(op) - 1;
1320 l = aopGet(AOP(op),3,FALSE,FALSE);
1324 emitcode("cpl","acc.7");
1325 aopPut(AOP(result),"a",3);
1329 aopGet(AOP(op),offset,FALSE,FALSE),
1335 /*-----------------------------------------------------------------*/
1336 /* genUminus - unary minus code generation */
1337 /*-----------------------------------------------------------------*/
1338 static void genUminus (iCode *ic)
1341 link *optype, *rtype;
1345 aopOp(IC_LEFT(ic),ic,FALSE);
1346 aopOp(IC_RESULT(ic),ic,TRUE);
1348 /* if both in bit space then special
1350 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1351 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1353 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1354 emitcode("cpl","c");
1355 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1359 optype = operandType(IC_LEFT(ic));
1360 rtype = operandType(IC_RESULT(ic));
1362 /* if float then do float stuff */
1363 if (IS_FLOAT(optype)) {
1364 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1368 /* otherwise subtract from zero */
1369 size = AOP_SIZE(IC_LEFT(ic));
1373 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1374 if (!strcmp(l,"a")) {
1375 emitcode("cpl","a");
1376 emitcode("inc","a");
1378 emitcode("clr","a");
1379 emitcode("subb","a,%s",l);
1381 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1384 /* if any remaining bytes in the result */
1385 /* we just need to propagate the sign */
1386 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1387 emitcode("rlc","a");
1388 emitcode("subb","a,acc");
1390 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1394 /* release the aops */
1395 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1396 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1399 /*-----------------------------------------------------------------*/
1400 /* saveRegisters - will look for a call and save the registers */
1401 /*-----------------------------------------------------------------*/
1402 static void saveRegisters(iCode *lic)
1410 for (ic = lic ; ic ; ic = ic->next)
1411 if (ic->op == CALL || ic->op == PCALL)
1415 fprintf(stderr,"found parameter push with no function call\n");
1419 /* if the registers have been saved already then
1421 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1424 /* find the registers in use at this time
1425 and push them away to safety */
1426 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1430 if (options.useXstack) {
1431 if (bitVectBitValue(rsave,R0_IDX))
1432 emitcode("mov","b,r0");
1433 emitcode("mov","r0,%s",spname);
1434 for (i = 0 ; i < mcs51_nRegs ; i++) {
1435 if (bitVectBitValue(rsave,i)) {
1437 emitcode("mov","a,b");
1439 emitcode("mov","a,%s",mcs51_regWithIdx(i)->name);
1440 emitcode("movx","@r0,a");
1441 emitcode("inc","r0");
1444 emitcode("mov","%s,r0",spname);
1445 if (bitVectBitValue(rsave,R0_IDX))
1446 emitcode("mov","r0,b");
1448 for (i = 0 ; i < mcs51_nRegs ; i++) {
1449 if (bitVectBitValue(rsave,i))
1450 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
1453 detype = getSpec(operandType(IC_LEFT(ic)));
1455 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1456 IS_ISR(currFunc->etype) &&
1459 saverbank(SPEC_BANK(detype),ic,TRUE);
1462 /*-----------------------------------------------------------------*/
1463 /* unsaveRegisters - pop the pushed registers */
1464 /*-----------------------------------------------------------------*/
1465 static void unsaveRegisters (iCode *ic)
1469 /* find the registers in use at this time
1470 and push them away to safety */
1471 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1474 if (options.useXstack) {
1475 emitcode("mov","r0,%s",spname);
1476 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1477 if (bitVectBitValue(rsave,i)) {
1478 emitcode("dec","r0");
1479 emitcode("movx","a,@r0");
1481 emitcode("mov","b,a");
1483 emitcode("mov","%s,a",mcs51_regWithIdx(i)->name);
1487 emitcode("mov","%s,r0",spname);
1488 if (bitVectBitValue(rsave,R0_IDX))
1489 emitcode("mov","r0,b");
1491 for (i = mcs51_nRegs ; i >= 0 ; i--) {
1492 if (bitVectBitValue(rsave,i))
1493 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
1499 /*-----------------------------------------------------------------*/
1501 /*-----------------------------------------------------------------*/
1502 static void pushSide(operand * oper, int size)
1506 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1507 if (AOP_TYPE(oper) != AOP_REG &&
1508 AOP_TYPE(oper) != AOP_DIR &&
1510 emitcode("mov","a,%s",l);
1511 emitcode("push","acc");
1513 emitcode("push","%s",l);
1517 /*-----------------------------------------------------------------*/
1518 /* assignResultValue - */
1519 /*-----------------------------------------------------------------*/
1520 static void assignResultValue(operand * oper)
1523 int size = AOP_SIZE(oper);
1525 aopPut(AOP(oper),fReturn[offset],offset);
1531 /*-----------------------------------------------------------------*/
1532 /* genXpush - pushes onto the external stack */
1533 /*-----------------------------------------------------------------*/
1534 static void genXpush (iCode *ic)
1536 asmop *aop = newAsmop(0);
1538 int size,offset = 0;
1540 aopOp(IC_LEFT(ic),ic,FALSE);
1541 r = getFreePtr(ic,&aop,FALSE);
1544 emitcode("mov","%s,_spx",r->name);
1546 size = AOP_SIZE(IC_LEFT(ic));
1549 char *l = aopGet(AOP(IC_LEFT(ic)),
1550 offset++,FALSE,FALSE);
1552 emitcode("movx","@%s,a",r->name);
1553 emitcode("inc","%s",r->name);
1558 emitcode("mov","_spx,%s",r->name);
1560 freeAsmop(NULL,aop,ic,TRUE);
1561 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1564 /*-----------------------------------------------------------------*/
1565 /* genIpush - genrate code for pushing this gets a little complex */
1566 /*-----------------------------------------------------------------*/
1567 static void genIpush (iCode *ic)
1569 int size, offset = 0 ;
1573 /* if this is not a parm push : ie. it is spill push
1574 and spill push is always done on the local stack */
1575 if (!ic->parmPush) {
1577 /* and the item is spilt then do nothing */
1578 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1581 aopOp(IC_LEFT(ic),ic,FALSE);
1582 size = AOP_SIZE(IC_LEFT(ic));
1583 /* push it on the stack */
1585 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1590 emitcode("push","%s",l);
1595 /* this is a paramter push: in this case we call
1596 the routine to find the call and save those
1597 registers that need to be saved */
1600 /* if use external stack then call the external
1601 stack pushing routine */
1602 if (options.useXstack) {
1607 /* then do the push */
1608 aopOp(IC_LEFT(ic),ic,FALSE);
1611 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1612 size = AOP_SIZE(IC_LEFT(ic));
1615 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1616 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1617 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1619 emitcode("mov","a,%s",l);
1620 emitcode("push","acc");
1622 emitcode("push","%s",l);
1625 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1628 /*-----------------------------------------------------------------*/
1629 /* genIpop - recover the registers: can happen only for spilling */
1630 /*-----------------------------------------------------------------*/
1631 static void genIpop (iCode *ic)
1636 /* if the temp was not pushed then */
1637 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1640 aopOp(IC_LEFT(ic),ic,FALSE);
1641 size = AOP_SIZE(IC_LEFT(ic));
1644 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1647 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1650 /*-----------------------------------------------------------------*/
1651 /* unsaverbank - restores the resgister bank from stack */
1652 /*-----------------------------------------------------------------*/
1653 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1660 if (options.useXstack) {
1662 r = getFreePtr(ic,&aop,FALSE);
1665 emitcode("mov","%s,_spx",r->name);
1666 emitcode("movx","a,@%s",r->name);
1667 emitcode("mov","psw,a");
1668 emitcode("dec","%s",r->name);
1671 emitcode ("pop","psw");
1674 for (i = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
1675 if (options.useXstack) {
1676 emitcode("movx","a,@%s",r->name);
1677 emitcode("mov","(%s+%d),a",
1678 regs8051[i].base,8*bank+regs8051[i].offset);
1679 emitcode("dec","%s",r->name);
1682 emitcode("pop","(%s+%d)",
1683 regs8051[i].base,8*bank+regs8051[i].offset);
1686 if (options.useXstack) {
1688 emitcode("mov","_spx,%s",r->name);
1689 freeAsmop(NULL,aop,ic,TRUE);
1694 /*-----------------------------------------------------------------*/
1695 /* saverbank - saves an entire register bank on the stack */
1696 /*-----------------------------------------------------------------*/
1697 static void saverbank (int bank, iCode *ic, bool pushPsw)
1703 if (options.useXstack) {
1706 r = getFreePtr(ic,&aop,FALSE);
1707 emitcode("mov","%s,_spx",r->name);
1711 for (i = 0 ; i < mcs51_nRegs ;i++) {
1712 if (options.useXstack) {
1713 emitcode("inc","%s",r->name);
1714 emitcode("mov","a,(%s+%d)",
1715 regs8051[i].base,8*bank+regs8051[i].offset);
1716 emitcode("movx","@%s,a",r->name);
1718 emitcode("push","(%s+%d)",
1719 regs8051[i].base,8*bank+regs8051[i].offset);
1723 if (options.useXstack) {
1724 emitcode("mov","a,psw");
1725 emitcode("movx","@%s,a",r->name);
1726 emitcode("inc","%s",r->name);
1727 emitcode("mov","_spx,%s",r->name);
1728 freeAsmop (NULL,aop,ic,TRUE);
1731 emitcode("push","psw");
1733 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1739 /*-----------------------------------------------------------------*/
1740 /* genCall - generates a call statement */
1741 /*-----------------------------------------------------------------*/
1742 static void genCall (iCode *ic)
1746 /* if caller saves & we have not saved then */
1750 /* if we are calling a function that is not using
1751 the same register bank then we need to save the
1752 destination registers on the stack */
1753 detype = getSpec(operandType(IC_LEFT(ic)));
1755 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1756 IS_ISR(currFunc->etype) &&
1759 saverbank(SPEC_BANK(detype),ic,TRUE);
1761 /* if send set is not empty the assign */
1765 for (sic = setFirstItem(_G.sendSet) ; sic ;
1766 sic = setNextItem(_G.sendSet)) {
1767 int size, offset = 0;
1768 aopOp(IC_LEFT(sic),sic,FALSE);
1769 size = AOP_SIZE(IC_LEFT(sic));
1771 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1773 if (strcmp(l,fReturn[offset]))
1774 emitcode("mov","%s,%s",
1779 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1784 emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1785 OP_SYMBOL(IC_LEFT(ic))->rname :
1786 OP_SYMBOL(IC_LEFT(ic))->name));
1788 /* if we need assign a result value */
1789 if ((IS_ITEMP(IC_RESULT(ic)) &&
1790 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1791 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1792 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1795 aopOp(IC_RESULT(ic),ic,FALSE);
1798 assignResultValue(IC_RESULT(ic));
1800 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1803 /* adjust the stack for parameters if
1805 if (IC_LEFT(ic)->parmBytes) {
1807 if (IC_LEFT(ic)->parmBytes > 3) {
1808 emitcode("mov","a,%s",spname);
1809 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1810 emitcode("mov","%s,a",spname);
1812 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1813 emitcode("dec","%s",spname);
1817 /* if register bank was saved then pop them */
1819 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1821 /* if we hade saved some registers then unsave them */
1822 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1823 unsaveRegisters (ic);
1828 /*-----------------------------------------------------------------*/
1829 /* genPcall - generates a call by pointer statement */
1830 /*-----------------------------------------------------------------*/
1831 static void genPcall (iCode *ic)
1834 symbol *rlbl = newiTempLabel(NULL);
1837 /* if caller saves & we have not saved then */
1841 /* if we are calling a function that is not using
1842 the same register bank then we need to save the
1843 destination registers on the stack */
1844 detype = getSpec(operandType(IC_LEFT(ic)));
1846 IS_ISR(currFunc->etype) &&
1847 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
1848 saverbank(SPEC_BANK(detype),ic,TRUE);
1851 /* push the return address on to the stack */
1852 emitcode("mov","a,#%05d$",(rlbl->key+100));
1853 emitcode("push","acc");
1854 emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
1855 emitcode("push","acc");
1857 if (options.model == MODEL_FLAT24)
1859 emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
1860 emitcode("push","acc");
1863 /* now push the calling address */
1864 aopOp(IC_LEFT(ic),ic,FALSE);
1866 pushSide(IC_LEFT(ic), FPTRSIZE);
1868 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1870 /* if send set is not empty the assign */
1874 for (sic = setFirstItem(_G.sendSet) ; sic ;
1875 sic = setNextItem(_G.sendSet)) {
1876 int size, offset = 0;
1877 aopOp(IC_LEFT(sic),sic,FALSE);
1878 size = AOP_SIZE(IC_LEFT(sic));
1880 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1882 if (strcmp(l,fReturn[offset]))
1883 emitcode("mov","%s,%s",
1888 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1894 emitcode("","%05d$:",(rlbl->key+100));
1897 /* if we need assign a result value */
1898 if ((IS_ITEMP(IC_RESULT(ic)) &&
1899 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1900 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
1901 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1904 aopOp(IC_RESULT(ic),ic,FALSE);
1907 assignResultValue(IC_RESULT(ic));
1909 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1912 /* adjust the stack for parameters if
1914 if (IC_LEFT(ic)->parmBytes) {
1916 if (IC_LEFT(ic)->parmBytes > 3) {
1917 emitcode("mov","a,%s",spname);
1918 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1919 emitcode("mov","%s,a",spname);
1921 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1922 emitcode("dec","%s",spname);
1926 /* if register bank was saved then unsave them */
1928 (SPEC_BANK(currFunc->etype) !=
1930 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1932 /* if we hade saved some registers then
1935 unsaveRegisters (ic);
1939 /*-----------------------------------------------------------------*/
1940 /* resultRemat - result is rematerializable */
1941 /*-----------------------------------------------------------------*/
1942 static int resultRemat (iCode *ic)
1944 if (SKIP_IC(ic) || ic->op == IFX)
1947 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1948 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1949 if (sym->remat && !POINTER_SET(ic))
1957 #define STRCASECMP stricmp
1959 #define STRCASECMP strcasecmp
1962 /*-----------------------------------------------------------------*/
1963 /* inExcludeList - return 1 if the string is in exclude Reg list */
1964 /*-----------------------------------------------------------------*/
1965 static bool inExcludeList(char *s)
1969 if (options.excludeRegs[i] &&
1970 STRCASECMP(options.excludeRegs[i],"none") == 0)
1973 for ( i = 0 ; options.excludeRegs[i]; i++) {
1974 if (options.excludeRegs[i] &&
1975 STRCASECMP(s,options.excludeRegs[i]) == 0)
1981 /*-----------------------------------------------------------------*/
1982 /* genFunction - generated code for function entry */
1983 /*-----------------------------------------------------------------*/
1984 static void genFunction (iCode *ic)
1990 /* create the function header */
1991 emitcode(";","-----------------------------------------");
1992 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1993 emitcode(";","-----------------------------------------");
1995 emitcode("","%s:",sym->rname);
1996 fetype = getSpec(operandType(IC_LEFT(ic)));
1998 /* if critical function then turn interrupts off */
1999 if (SPEC_CRTCL(fetype))
2000 emitcode("clr","ea");
2002 /* here we need to generate the equates for the
2003 register bank if required */
2004 if (SPEC_BANK(fetype) != rbank) {
2007 rbank = SPEC_BANK(fetype);
2008 for ( i = 0 ; i < mcs51_nRegs ; i++ ) {
2009 if (strcmp(regs8051[i].base,"0") == 0)
2010 emitcode("","%s = 0x%02x",
2012 8*rbank+regs8051[i].offset);
2014 emitcode ("","%s = %s + 0x%02x",
2017 8*rbank+regs8051[i].offset);
2021 /* if this is an interrupt service routine then
2022 save acc, b, dpl, dph */
2023 if (IS_ISR(sym->etype)) {
2025 if (!inExcludeList("acc"))
2026 emitcode ("push","acc");
2027 if (!inExcludeList("b"))
2028 emitcode ("push","b");
2029 if (!inExcludeList("dpl"))
2030 emitcode ("push","dpl");
2031 if (!inExcludeList("dph"))
2032 emitcode ("push","dph");
2033 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2035 emitcode ("push", "dpx");
2036 /* Make sure we're using standard DPTR */
2037 emitcode ("push", "dps");
2038 emitcode ("mov", "dps, #0x00");
2039 if (options.stack10bit)
2041 /* This ISR could conceivably use DPTR2. Better save it. */
2042 emitcode ("push", "dpl1");
2043 emitcode ("push", "dph1");
2044 emitcode ("push", "dpx1");
2047 /* if this isr has no bank i.e. is going to
2048 run with bank 0 , then we need to save more
2050 if (!SPEC_BANK(sym->etype)) {
2052 /* if this function does not call any other
2053 function then we can be economical and
2054 save only those registers that are used */
2055 if (! sym->hasFcall) {
2058 /* if any registers used */
2059 if (sym->regsUsed) {
2060 /* save the registers used */
2061 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2062 if (bitVectBitValue(sym->regsUsed,i) ||
2063 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2064 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2069 /* this function has a function call cannot
2070 determines register usage so we will have the
2072 saverbank(0,ic,FALSE);
2076 /* if callee-save to be used for this function
2077 then save the registers being used in this function */
2078 if (sym->calleeSave) {
2081 /* if any registers used */
2082 if (sym->regsUsed) {
2083 /* save the registers used */
2084 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2085 if (bitVectBitValue(sym->regsUsed,i) ||
2086 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2087 emitcode("push","%s",mcs51_regWithIdx(i)->dname);
2095 /* set the register bank to the desired value */
2096 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2097 emitcode("push","psw");
2098 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2101 if (IS_RENT(sym->etype) || options.stackAuto) {
2103 if (options.useXstack) {
2104 emitcode("mov","r0,%s",spname);
2105 emitcode("mov","a,_bp");
2106 emitcode("movx","@r0,a");
2107 emitcode("inc","%s",spname);
2111 /* set up the stack */
2112 emitcode ("push","_bp"); /* save the callers stack */
2114 emitcode ("mov","_bp,%s",spname);
2117 /* adjust the stack for the function */
2122 werror(W_STACK_OVERFLOW,sym->name);
2124 if (i > 3 && sym->recvSize < 4) {
2126 emitcode ("mov","a,sp");
2127 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2128 emitcode ("mov","sp,a");
2133 emitcode("inc","sp");
2138 emitcode ("mov","a,_spx");
2139 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2140 emitcode ("mov","_spx,a");
2145 /*-----------------------------------------------------------------*/
2146 /* genEndFunction - generates epilogue for functions */
2147 /*-----------------------------------------------------------------*/
2148 static void genEndFunction (iCode *ic)
2150 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2152 if (IS_RENT(sym->etype) || options.stackAuto)
2154 emitcode ("mov","%s,_bp",spname);
2157 /* if use external stack but some variables were
2158 added to the local stack then decrement the
2160 if (options.useXstack && sym->stack) {
2161 emitcode("mov","a,sp");
2162 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2163 emitcode("mov","sp,a");
2167 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2168 if (options.useXstack) {
2169 emitcode("mov","r0,%s",spname);
2170 emitcode("movx","a,@r0");
2171 emitcode("mov","_bp,a");
2172 emitcode("dec","%s",spname);
2176 emitcode ("pop","_bp");
2180 /* restore the register bank */
2181 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2182 emitcode ("pop","psw");
2184 if (IS_ISR(sym->etype)) {
2186 /* now we need to restore the registers */
2187 /* if this isr has no bank i.e. is going to
2188 run with bank 0 , then we need to save more
2190 if (!SPEC_BANK(sym->etype)) {
2192 /* if this function does not call any other
2193 function then we can be economical and
2194 save only those registers that are used */
2195 if (! sym->hasFcall) {
2198 /* if any registers used */
2199 if (sym->regsUsed) {
2200 /* save the registers used */
2201 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2202 if (bitVectBitValue(sym->regsUsed,i) ||
2203 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2204 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2209 /* this function has a function call cannot
2210 determines register usage so we will have the
2212 unsaverbank(0,ic,FALSE);
2216 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2218 if (options.stack10bit)
2220 emitcode ("pop", "dpx1");
2221 emitcode ("pop", "dph1");
2222 emitcode ("pop", "dpl1");
2224 emitcode ("pop", "dps");
2225 emitcode ("pop", "dpx");
2227 if (!inExcludeList("dph"))
2228 emitcode ("pop","dph");
2229 if (!inExcludeList("dpl"))
2230 emitcode ("pop","dpl");
2231 if (!inExcludeList("b"))
2232 emitcode ("pop","b");
2233 if (!inExcludeList("acc"))
2234 emitcode ("pop","acc");
2236 if (SPEC_CRTCL(sym->etype))
2237 emitcode("setb","ea");
2239 /* if debug then send end of function */
2240 /* if (options.debug && currFunc) { */
2243 emitcode("","C$%s$%d$%d$%d ==.",
2244 ic->filename,currFunc->lastLine,
2245 ic->level,ic->block);
2246 if (IS_STATIC(currFunc->etype))
2247 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2249 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2253 emitcode ("reti","");
2256 if (SPEC_CRTCL(sym->etype))
2257 emitcode("setb","ea");
2259 if (sym->calleeSave) {
2262 /* if any registers used */
2263 if (sym->regsUsed) {
2264 /* save the registers used */
2265 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2266 if (bitVectBitValue(sym->regsUsed,i) ||
2267 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2268 emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
2274 /* if debug then send end of function */
2277 emitcode("","C$%s$%d$%d$%d ==.",
2278 ic->filename,currFunc->lastLine,
2279 ic->level,ic->block);
2280 if (IS_STATIC(currFunc->etype))
2281 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2283 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2287 emitcode ("ret","");
2292 /*-----------------------------------------------------------------*/
2293 /* genRet - generate code for return statement */
2294 /*-----------------------------------------------------------------*/
2295 static void genRet (iCode *ic)
2297 int size,offset = 0 , pushed = 0;
2299 /* if we have no return value then
2300 just generate the "ret" */
2304 /* we have something to return then
2305 move the return value into place */
2306 aopOp(IC_LEFT(ic),ic,FALSE);
2307 size = AOP_SIZE(IC_LEFT(ic));
2311 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2313 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2315 emitcode("push","%s",l);
2318 l = aopGet(AOP(IC_LEFT(ic)),offset,
2320 if (strcmp(fReturn[offset],l))
2321 emitcode("mov","%s,%s",fReturn[offset++],l);
2328 if (strcmp(fReturn[pushed],"a"))
2329 emitcode("pop",fReturn[pushed]);
2331 emitcode("pop","acc");
2334 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2337 /* generate a jump to the return label
2338 if the next is not the return statement */
2339 if (!(ic->next && ic->next->op == LABEL &&
2340 IC_LABEL(ic->next) == returnLabel))
2342 emitcode("ljmp","%05d$",(returnLabel->key+100));
2346 /*-----------------------------------------------------------------*/
2347 /* genLabel - generates a label */
2348 /*-----------------------------------------------------------------*/
2349 static void genLabel (iCode *ic)
2351 /* special case never generate */
2352 if (IC_LABEL(ic) == entryLabel)
2355 emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
2358 /*-----------------------------------------------------------------*/
2359 /* genGoto - generates a ljmp */
2360 /*-----------------------------------------------------------------*/
2361 static void genGoto (iCode *ic)
2363 emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
2366 /*-----------------------------------------------------------------*/
2367 /* findLabelBackwards: walks back through the iCode chain looking */
2368 /* for the given label. Returns number of iCode instructions */
2369 /* between that label and given ic. */
2370 /* Returns zero if label not found. */
2371 /*-----------------------------------------------------------------*/
2372 static int findLabelBackwards(iCode *ic, int key)
2381 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2383 /* printf("findLabelBackwards = %d\n", count); */
2391 /*-----------------------------------------------------------------*/
2392 /* genPlusIncr :- does addition with increment if possible */
2393 /*-----------------------------------------------------------------*/
2394 static bool genPlusIncr (iCode *ic)
2396 unsigned int icount ;
2397 unsigned int size = getDataSize(IC_RESULT(ic));
2399 /* will try to generate an increment */
2400 /* if the right side is not a literal
2402 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2405 /* if the literal value of the right hand side
2406 is greater than 4 then it is not worth it */
2407 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2410 /* if increment 16 bits in register */
2411 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2418 /* If the next instruction is a goto and the goto target
2419 * is < 10 instructions previous to this, we can generate
2420 * jumps straight to that target.
2422 if (ic->next && ic->next->op == GOTO
2423 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2424 && labelRange <= 10 )
2426 emitcode(";", "tail increment optimized");
2427 tlbl = IC_LABEL(ic->next);
2432 tlbl = newiTempLabel(NULL);
2435 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2436 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2437 IS_AOP_PREG(IC_RESULT(ic)))
2438 emitcode("cjne","%s,#0x00,%05d$"
2439 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2442 emitcode("clr","a");
2443 emitcode("cjne","a,%s,%05d$"
2444 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2448 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2451 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2452 IS_AOP_PREG(IC_RESULT(ic)))
2453 emitcode("cjne","%s,#0x00,%05d$"
2454 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2457 emitcode("cjne","a,%s,%05d$"
2458 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2461 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2465 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2466 IS_AOP_PREG(IC_RESULT(ic)))
2467 emitcode("cjne","%s,#0x00,%05d$"
2468 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2471 emitcode("cjne","a,%s,%05d$"
2472 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2475 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2480 emitcode("","%05d$:",tlbl->key+100);
2485 /* if the sizes are greater than 1 then we cannot */
2486 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2487 AOP_SIZE(IC_LEFT(ic)) > 1 )
2490 /* we can if the aops of the left & result match or
2491 if they are in registers and the registers are the
2493 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2496 MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2497 emitcode("add","a,#0x%02x",((char) icount) & 0xff);
2498 aopPut(AOP(IC_RESULT(ic)),"a",0);
2502 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2511 /*-----------------------------------------------------------------*/
2512 /* outBitAcc - output a bit in acc */
2513 /*-----------------------------------------------------------------*/
2514 static void outBitAcc(operand *result)
2516 symbol *tlbl = newiTempLabel(NULL);
2517 /* if the result is a bit */
2518 if (AOP_TYPE(result) == AOP_CRY){
2519 aopPut(AOP(result),"a",0);
2522 emitcode("jz","%05d$",tlbl->key+100);
2523 emitcode("mov","a,%s",one);
2524 emitcode("","%05d$:",tlbl->key+100);
2529 /*-----------------------------------------------------------------*/
2530 /* genPlusBits - generates code for addition of two bits */
2531 /*-----------------------------------------------------------------*/
2532 static void genPlusBits (iCode *ic)
2534 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2535 symbol *lbl = newiTempLabel(NULL);
2536 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2537 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2538 emitcode("cpl","c");
2539 emitcode("","%05d$:",(lbl->key+100));
2540 outBitC(IC_RESULT(ic));
2543 emitcode("clr","a");
2544 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2545 emitcode("rlc","a");
2546 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2547 emitcode("addc","a,#0x00");
2548 outAcc(IC_RESULT(ic));
2553 /* This is the original version of this code.
2555 * This is being kept around for reference,
2556 * because I am not entirely sure I got it right...
2558 static void adjustArithmeticResult(iCode *ic)
2560 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2561 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2562 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2563 aopPut(AOP(IC_RESULT(ic)),
2564 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2567 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2568 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2569 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2570 aopPut(AOP(IC_RESULT(ic)),
2571 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2574 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2575 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2576 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2577 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2578 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2580 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2581 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2585 /* This is the pure and virtuous version of this code.
2586 * I'm pretty certain it's right, but not enough to toss the old
2589 static void adjustArithmeticResult(iCode *ic)
2591 if (opIsGptr(IC_RESULT(ic)) &&
2592 opIsGptr(IC_LEFT(ic)) &&
2593 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2595 aopPut(AOP(IC_RESULT(ic)),
2596 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2600 if (opIsGptr(IC_RESULT(ic)) &&
2601 opIsGptr(IC_RIGHT(ic)) &&
2602 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2604 aopPut(AOP(IC_RESULT(ic)),
2605 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2609 if (opIsGptr(IC_RESULT(ic)) &&
2610 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2611 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2612 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2613 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2615 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2616 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2621 /*-----------------------------------------------------------------*/
2622 /* genPlus - generates code for addition */
2623 /*-----------------------------------------------------------------*/
2624 static void genPlus (iCode *ic)
2626 int size, offset = 0;
2628 /* special cases :- */
2630 aopOp (IC_LEFT(ic),ic,FALSE);
2631 aopOp (IC_RIGHT(ic),ic,FALSE);
2632 aopOp (IC_RESULT(ic),ic,TRUE);
2634 /* if literal, literal on the right or
2635 if left requires ACC or right is already
2637 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2638 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2639 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2640 operand *t = IC_RIGHT(ic);
2641 IC_RIGHT(ic) = IC_LEFT(ic);
2645 /* if both left & right are in bit
2647 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2648 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2653 /* if left in bit space & right literal */
2654 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2655 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2656 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2657 /* if result in bit space */
2658 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2659 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
2660 emitcode("cpl","c");
2661 outBitC(IC_RESULT(ic));
2663 size = getDataSize(IC_RESULT(ic));
2665 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2666 emitcode("addc","a,#00");
2667 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2673 /* if I can do an increment instead
2674 of add then GOOD for ME */
2675 if (genPlusIncr (ic) == TRUE)
2678 size = getDataSize(IC_RESULT(ic));
2681 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2682 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2684 emitcode("add","a,%s",
2685 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2687 emitcode("addc","a,%s",
2688 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2690 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2692 emitcode("add","a,%s",
2693 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2695 emitcode("addc","a,%s",
2696 aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2698 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2701 adjustArithmeticResult(ic);
2704 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2705 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2706 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2709 /*-----------------------------------------------------------------*/
2710 /* genMinusDec :- does subtraction with deccrement if possible */
2711 /*-----------------------------------------------------------------*/
2712 static bool genMinusDec (iCode *ic)
2714 unsigned int icount ;
2715 unsigned int size = getDataSize(IC_RESULT(ic));
2717 /* will try to generate an increment */
2718 /* if the right side is not a literal
2720 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2723 /* if the literal value of the right hand side
2724 is greater than 4 then it is not worth it */
2725 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
2728 /* if decrement 16 bits in register */
2729 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2736 /* If the next instruction is a goto and the goto target
2737 * is <= 10 instructions previous to this, we can generate
2738 * jumps straight to that target.
2740 if (ic->next && ic->next->op == GOTO
2741 && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
2742 && labelRange <= 10 )
2744 emitcode(";", "tail decrement optimized");
2745 tlbl = IC_LABEL(ic->next);
2750 tlbl = newiTempLabel(NULL);
2754 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2755 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2756 IS_AOP_PREG(IC_RESULT(ic)))
2757 emitcode("cjne","%s,#0xff,%05d$"
2758 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2761 emitcode("mov","a,#0xff");
2762 emitcode("cjne","a,%s,%05d$"
2763 ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
2766 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
2769 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2770 IS_AOP_PREG(IC_RESULT(ic)))
2771 emitcode("cjne","%s,#0xff,%05d$"
2772 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2775 emitcode("cjne","a,%s,%05d$"
2776 ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
2779 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
2783 if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
2784 IS_AOP_PREG(IC_RESULT(ic)))
2785 emitcode("cjne","%s,#0xff,%05d$"
2786 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2789 emitcode("cjne","a,%s,%05d$"
2790 ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
2793 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
2797 emitcode("","%05d$:",tlbl->key+100);
2802 /* if the sizes are greater than 1 then we cannot */
2803 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2804 AOP_SIZE(IC_LEFT(ic)) > 1 )
2807 /* we can if the aops of the left & result match or
2808 if they are in registers and the registers are the
2810 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2813 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2821 /*-----------------------------------------------------------------*/
2822 /* addSign - complete with sign */
2823 /*-----------------------------------------------------------------*/
2824 static void addSign(operand *result, int offset, int sign)
2826 int size = (getDataSize(result) - offset);
2829 emitcode("rlc","a");
2830 emitcode("subb","a,acc");
2832 aopPut(AOP(result),"a",offset++);
2835 aopPut(AOP(result),zero,offset++);
2839 /*-----------------------------------------------------------------*/
2840 /* genMinusBits - generates code for subtraction of two bits */
2841 /*-----------------------------------------------------------------*/
2842 static void genMinusBits (iCode *ic)
2844 symbol *lbl = newiTempLabel(NULL);
2845 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2846 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
2847 emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
2848 emitcode("cpl","c");
2849 emitcode("","%05d$:",(lbl->key+100));
2850 outBitC(IC_RESULT(ic));
2853 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
2854 emitcode("subb","a,acc");
2855 emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
2856 emitcode("inc","a");
2857 emitcode("","%05d$:",(lbl->key+100));
2858 aopPut(AOP(IC_RESULT(ic)),"a",0);
2859 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
2863 /*-----------------------------------------------------------------*/
2864 /* genMinus - generates code for subtraction */
2865 /*-----------------------------------------------------------------*/
2866 static void genMinus (iCode *ic)
2868 int size, offset = 0;
2869 unsigned long lit = 0L;
2871 aopOp (IC_LEFT(ic),ic,FALSE);
2872 aopOp (IC_RIGHT(ic),ic,FALSE);
2873 aopOp (IC_RESULT(ic),ic,TRUE);
2875 /* special cases :- */
2876 /* if both left & right are in bit space */
2877 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2878 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2883 /* if I can do an decrement instead
2884 of subtract then GOOD for ME */
2885 if (genMinusDec (ic) == TRUE)
2888 size = getDataSize(IC_RESULT(ic));
2890 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2894 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2898 /* if literal, add a,#-lit, else normal subb */
2900 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2901 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2902 emitcode("subb","a,%s",
2903 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2905 /* first add without previous c */
2907 emitcode("add","a,#0x%02x",
2908 (unsigned int)(lit & 0x0FFL));
2910 emitcode("addc","a,#0x%02x",
2911 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2913 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2916 adjustArithmeticResult(ic);
2919 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2920 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
2921 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2925 /*-----------------------------------------------------------------*/
2926 /* genMultbits :- multiplication of bits */
2927 /*-----------------------------------------------------------------*/
2928 static void genMultbits (operand *left,
2932 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
2933 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
2938 /*-----------------------------------------------------------------*/
2939 /* genMultOneByte : 8 bit multiplication & division */
2940 /*-----------------------------------------------------------------*/
2941 static void genMultOneByte (operand *left,
2945 link *opetype = operandType(result);
2950 /* (if two literals, the value is computed before) */
2951 /* if one literal, literal on the right */
2952 if (AOP_TYPE(left) == AOP_LIT){
2958 size = AOP_SIZE(result);
2959 /* signed or unsigned */
2960 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
2961 l = aopGet(AOP(left),0,FALSE,FALSE);
2963 emitcode("mul","ab");
2964 /* if result size = 1, mul signed = mul unsigned */
2965 aopPut(AOP(result),"a",0);
2967 if (SPEC_USIGN(opetype)){
2968 aopPut(AOP(result),"b",1);
2970 /* for filling the MSBs */
2971 emitcode("clr","a");
2974 emitcode("mov","a,b");
2976 /* adjust the MSB if left or right neg */
2978 /* if one literal */
2979 if (AOP_TYPE(right) == AOP_LIT){
2980 /* AND literal negative */
2981 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
2982 /* adjust MSB (c==0 after mul) */
2983 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2987 lbl = newiTempLabel(NULL);
2988 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2989 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
2990 emitcode("","%05d$:",(lbl->key+100));
2991 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
2992 lbl = newiTempLabel(NULL);
2993 emitcode("jc","%05d$",(lbl->key+100));
2994 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
2995 emitcode("","%05d$:",(lbl->key+100));
2998 lbl = newiTempLabel(NULL);
2999 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3000 emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
3001 emitcode("","%05d$:",(lbl->key+100));
3002 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3003 lbl = newiTempLabel(NULL);
3004 emitcode("jc","%05d$",(lbl->key+100));
3005 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3006 emitcode("","%05d$:",(lbl->key+100));
3008 aopPut(AOP(result),"a",1);
3011 emitcode("rlc","a");
3012 emitcode("subb","a,acc");
3019 aopPut(AOP(result),"a",offset++);
3023 /*-----------------------------------------------------------------*/
3024 /* genMult - generates code for multiplication */
3025 /*-----------------------------------------------------------------*/
3026 static void genMult (iCode *ic)
3028 operand *left = IC_LEFT(ic);
3029 operand *right = IC_RIGHT(ic);
3030 operand *result= IC_RESULT(ic);
3032 /* assign the amsops */
3033 aopOp (left,ic,FALSE);
3034 aopOp (right,ic,FALSE);
3035 aopOp (result,ic,TRUE);
3037 /* special cases first */
3039 if (AOP_TYPE(left) == AOP_CRY &&
3040 AOP_TYPE(right)== AOP_CRY) {
3041 genMultbits(left,right,result);
3045 /* if both are of size == 1 */
3046 if (AOP_SIZE(left) == 1 &&
3047 AOP_SIZE(right) == 1 ) {
3048 genMultOneByte(left,right,result);
3052 /* should have been converted to function call */
3056 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3057 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3058 freeAsmop(result,NULL,ic,TRUE);
3061 /*-----------------------------------------------------------------*/
3062 /* genDivbits :- division of bits */
3063 /*-----------------------------------------------------------------*/
3064 static void genDivbits (operand *left,
3071 /* the result must be bit */
3072 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3073 l = aopGet(AOP(left),0,FALSE,FALSE);
3077 emitcode("div","ab");
3078 emitcode("rrc","a");
3079 aopPut(AOP(result),"c",0);
3082 /*-----------------------------------------------------------------*/
3083 /* genDivOneByte : 8 bit division */
3084 /*-----------------------------------------------------------------*/
3085 static void genDivOneByte (operand *left,
3089 link *opetype = operandType(result);
3094 size = AOP_SIZE(result) - 1;
3096 /* signed or unsigned */
3097 if (SPEC_USIGN(opetype)) {
3098 /* unsigned is easy */
3099 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3100 l = aopGet(AOP(left),0,FALSE,FALSE);
3102 emitcode("div","ab");
3103 aopPut(AOP(result),"a",0);
3105 aopPut(AOP(result),zero,offset++);
3109 /* signed is a little bit more difficult */
3111 /* save the signs of the operands */
3112 l = aopGet(AOP(left),0,FALSE,FALSE);
3114 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3115 emitcode("push","acc"); /* save it on the stack */
3117 /* now sign adjust for both left & right */
3118 l = aopGet(AOP(right),0,FALSE,FALSE);
3120 lbl = newiTempLabel(NULL);
3121 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3122 emitcode("cpl","a");
3123 emitcode("inc","a");
3124 emitcode("","%05d$:",(lbl->key+100));
3125 emitcode("mov","b,a");
3127 /* sign adjust left side */
3128 l = aopGet(AOP(left),0,FALSE,FALSE);
3131 lbl = newiTempLabel(NULL);
3132 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3133 emitcode("cpl","a");
3134 emitcode("inc","a");
3135 emitcode("","%05d$:",(lbl->key+100));
3137 /* now the division */
3138 emitcode("div","ab");
3139 /* we are interested in the lower order
3141 emitcode("mov","b,a");
3142 lbl = newiTempLabel(NULL);
3143 emitcode("pop","acc");
3144 /* if there was an over flow we don't
3145 adjust the sign of the result */
3146 emitcode("jb","ov,%05d$",(lbl->key+100));
3147 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3149 emitcode("clr","a");
3150 emitcode("subb","a,b");
3151 emitcode("mov","b,a");
3152 emitcode("","%05d$:",(lbl->key+100));
3154 /* now we are done */
3155 aopPut(AOP(result),"b",0);
3157 emitcode("mov","c,b.7");
3158 emitcode("subb","a,acc");
3161 aopPut(AOP(result),"a",offset++);
3165 /*-----------------------------------------------------------------*/
3166 /* genDiv - generates code for division */
3167 /*-----------------------------------------------------------------*/
3168 static void genDiv (iCode *ic)
3170 operand *left = IC_LEFT(ic);
3171 operand *right = IC_RIGHT(ic);
3172 operand *result= IC_RESULT(ic);
3174 /* assign the amsops */
3175 aopOp (left,ic,FALSE);
3176 aopOp (right,ic,FALSE);
3177 aopOp (result,ic,TRUE);
3179 /* special cases first */
3181 if (AOP_TYPE(left) == AOP_CRY &&
3182 AOP_TYPE(right)== AOP_CRY) {
3183 genDivbits(left,right,result);
3187 /* if both are of size == 1 */
3188 if (AOP_SIZE(left) == 1 &&
3189 AOP_SIZE(right) == 1 ) {
3190 genDivOneByte(left,right,result);
3194 /* should have been converted to function call */
3197 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3198 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3199 freeAsmop(result,NULL,ic,TRUE);
3202 /*-----------------------------------------------------------------*/
3203 /* genModbits :- modulus of bits */
3204 /*-----------------------------------------------------------------*/
3205 static void genModbits (operand *left,
3212 /* the result must be bit */
3213 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3214 l = aopGet(AOP(left),0,FALSE,FALSE);
3218 emitcode("div","ab");
3219 emitcode("mov","a,b");
3220 emitcode("rrc","a");
3221 aopPut(AOP(result),"c",0);
3224 /*-----------------------------------------------------------------*/
3225 /* genModOneByte : 8 bit modulus */
3226 /*-----------------------------------------------------------------*/
3227 static void genModOneByte (operand *left,
3231 link *opetype = operandType(result);
3235 /* signed or unsigned */
3236 if (SPEC_USIGN(opetype)) {
3237 /* unsigned is easy */
3238 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3239 l = aopGet(AOP(left),0,FALSE,FALSE);
3241 emitcode("div","ab");
3242 aopPut(AOP(result),"b",0);
3246 /* signed is a little bit more difficult */
3248 /* save the signs of the operands */
3249 l = aopGet(AOP(left),0,FALSE,FALSE);
3252 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3253 emitcode("push","acc"); /* save it on the stack */
3255 /* now sign adjust for both left & right */
3256 l = aopGet(AOP(right),0,FALSE,FALSE);
3259 lbl = newiTempLabel(NULL);
3260 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3261 emitcode("cpl","a");
3262 emitcode("inc","a");
3263 emitcode("","%05d$:",(lbl->key+100));
3264 emitcode("mov","b,a");
3266 /* sign adjust left side */
3267 l = aopGet(AOP(left),0,FALSE,FALSE);
3270 lbl = newiTempLabel(NULL);
3271 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3272 emitcode("cpl","a");
3273 emitcode("inc","a");
3274 emitcode("","%05d$:",(lbl->key+100));
3276 /* now the multiplication */
3277 emitcode("div","ab");
3278 /* we are interested in the lower order
3280 lbl = newiTempLabel(NULL);
3281 emitcode("pop","acc");
3282 /* if there was an over flow we don't
3283 adjust the sign of the result */
3284 emitcode("jb","ov,%05d$",(lbl->key+100));
3285 emitcode("jnb","acc.7,%05d$",(lbl->key+100));
3287 emitcode("clr","a");
3288 emitcode("subb","a,b");
3289 emitcode("mov","b,a");
3290 emitcode("","%05d$:",(lbl->key+100));
3292 /* now we are done */
3293 aopPut(AOP(result),"b",0);
3297 /*-----------------------------------------------------------------*/
3298 /* genMod - generates code for division */
3299 /*-----------------------------------------------------------------*/
3300 static void genMod (iCode *ic)
3302 operand *left = IC_LEFT(ic);
3303 operand *right = IC_RIGHT(ic);
3304 operand *result= IC_RESULT(ic);
3306 /* assign the amsops */
3307 aopOp (left,ic,FALSE);
3308 aopOp (right,ic,FALSE);
3309 aopOp (result,ic,TRUE);
3311 /* special cases first */
3313 if (AOP_TYPE(left) == AOP_CRY &&
3314 AOP_TYPE(right)== AOP_CRY) {
3315 genModbits(left,right,result);
3319 /* if both are of size == 1 */
3320 if (AOP_SIZE(left) == 1 &&
3321 AOP_SIZE(right) == 1 ) {
3322 genModOneByte(left,right,result);
3326 /* should have been converted to function call */
3330 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3331 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3332 freeAsmop(result,NULL,ic,TRUE);
3335 /*-----------------------------------------------------------------*/
3336 /* genIfxJump :- will create a jump depending on the ifx */
3337 /*-----------------------------------------------------------------*/
3338 static void genIfxJump (iCode *ic, char *jval)
3341 symbol *tlbl = newiTempLabel(NULL);
3344 /* if true label then we jump if condition
3346 if ( IC_TRUE(ic) ) {
3348 inst = ((strcmp(jval,"a") == 0 ? "jz" :
3349 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
3352 /* false label is present */
3353 jlbl = IC_FALSE(ic) ;
3354 inst = ((strcmp(jval,"a") == 0 ? "jnz" :
3355 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));
3357 if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0)
3358 emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
3360 emitcode(inst,"%05d$",tlbl->key+100);
3361 emitcode("ljmp","%05d$",jlbl->key+100);
3362 emitcode("","%05d$:",tlbl->key+100);
3364 /* mark the icode as generated */
3368 /*-----------------------------------------------------------------*/
3369 /* genCmp :- greater or less than comparison */
3370 /*-----------------------------------------------------------------*/
3371 static void genCmp (operand *left,operand *right,
3372 operand *result, iCode *ifx, int sign)
3374 int size, offset = 0 ;
3375 unsigned long lit = 0L;
3377 /* if left & right are bit variables */
3378 if (AOP_TYPE(left) == AOP_CRY &&
3379 AOP_TYPE(right) == AOP_CRY ) {
3380 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3381 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3383 /* subtract right from left if at the
3384 end the carry flag is set then we know that
3385 left is greater than right */
3386 size = max(AOP_SIZE(left),AOP_SIZE(right));
3388 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3389 if((size == 1) && !sign &&
3390 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3391 symbol *lbl = newiTempLabel(NULL);
3392 emitcode("cjne","%s,%s,%05d$",
3393 aopGet(AOP(left),offset,FALSE,FALSE),
3394 aopGet(AOP(right),offset,FALSE,FALSE),
3396 emitcode("","%05d$:",lbl->key+100);
3398 if(AOP_TYPE(right) == AOP_LIT){
3399 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3400 /* optimize if(x < 0) or if(x >= 0) */
3406 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
3407 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
3408 genIfxJump (ifx,"acc.7");
3412 emitcode("rlc","a");
3419 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3420 if (sign && size == 0) {
3421 emitcode("xrl","a,#0x80");
3422 if (AOP_TYPE(right) == AOP_LIT){
3423 unsigned long lit = (unsigned long)
3424 floatFromVal(AOP(right)->aopu.aop_lit);
3425 emitcode("subb","a,#0x%02x",
3426 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3428 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3429 emitcode("xrl","b,#0x80");
3430 emitcode("subb","a,b");
3433 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3439 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3442 /* if the result is used in the next
3443 ifx conditional branch then generate
3444 code a little differently */
3446 genIfxJump (ifx,"c");
3449 /* leave the result in acc */
3453 /*-----------------------------------------------------------------*/
3454 /* genCmpGt :- greater than comparison */
3455 /*-----------------------------------------------------------------*/
3456 static void genCmpGt (iCode *ic, iCode *ifx)
3458 operand *left, *right, *result;
3459 link *letype , *retype;
3463 right= IC_RIGHT(ic);
3464 result = IC_RESULT(ic);
3466 letype = getSpec(operandType(left));
3467 retype =getSpec(operandType(right));
3468 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3469 /* assign the amsops */
3470 aopOp (left,ic,FALSE);
3471 aopOp (right,ic,FALSE);
3472 aopOp (result,ic,TRUE);
3474 genCmp(right, left, result, ifx, sign);
3476 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3477 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3478 freeAsmop(result,NULL,ic,TRUE);
3481 /*-----------------------------------------------------------------*/
3482 /* genCmpLt - less than comparisons */
3483 /*-----------------------------------------------------------------*/
3484 static void genCmpLt (iCode *ic, iCode *ifx)
3486 operand *left, *right, *result;
3487 link *letype , *retype;
3491 right= IC_RIGHT(ic);
3492 result = IC_RESULT(ic);
3494 letype = getSpec(operandType(left));
3495 retype =getSpec(operandType(right));
3496 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3498 /* assign the amsops */
3499 aopOp (left,ic,FALSE);
3500 aopOp (right,ic,FALSE);
3501 aopOp (result,ic,TRUE);
3503 genCmp(left, right, result, ifx, sign);
3505 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3506 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3507 freeAsmop(result,NULL,ic,TRUE);
3510 /*-----------------------------------------------------------------*/
3511 /* gencjneshort - compare and jump if not equal */
3512 /*-----------------------------------------------------------------*/
3513 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3515 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3517 unsigned long lit = 0L;
3519 /* if the left side is a literal or
3520 if the right is in a pointer register and left
3522 if ((AOP_TYPE(left) == AOP_LIT) ||
3523 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3528 if(AOP_TYPE(right) == AOP_LIT)
3529 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3531 /* if the right side is a literal then anything goes */
3532 if (AOP_TYPE(right) == AOP_LIT &&
3533 AOP_TYPE(left) != AOP_DIR ) {
3535 emitcode("cjne","%s,%s,%05d$",
3536 aopGet(AOP(left),offset,FALSE,FALSE),
3537 aopGet(AOP(right),offset,FALSE,FALSE),
3543 /* if the right side is in a register or in direct space or
3544 if the left is a pointer register & right is not */
3545 else if (AOP_TYPE(right) == AOP_REG ||
3546 AOP_TYPE(right) == AOP_DIR ||
3547 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
3548 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
3550 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
3551 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
3552 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
3553 emitcode("jnz","%05d$",lbl->key+100);
3555 emitcode("cjne","a,%s,%05d$",
3556 aopGet(AOP(right),offset,FALSE,TRUE),
3561 /* right is a pointer reg need both a & b */
3563 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
3565 emitcode("mov","b,%s",l);
3566 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
3567 emitcode("cjne","a,b,%05d$",lbl->key+100);
3573 /*-----------------------------------------------------------------*/
3574 /* gencjne - compare and jump if not equal */
3575 /*-----------------------------------------------------------------*/
3576 static void gencjne(operand *left, operand *right, symbol *lbl)
3578 symbol *tlbl = newiTempLabel(NULL);
3580 gencjneshort(left, right, lbl);
3582 emitcode("mov","a,%s",one);
3583 emitcode("sjmp","%05d$",tlbl->key+100);
3584 emitcode("","%05d$:",lbl->key+100);
3585 emitcode("clr","a");
3586 emitcode("","%05d$:",tlbl->key+100);
3589 /*-----------------------------------------------------------------*/
3590 /* genCmpEq - generates code for equal to */
3591 /*-----------------------------------------------------------------*/
3592 static void genCmpEq (iCode *ic, iCode *ifx)
3594 operand *left, *right, *result;
3596 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3597 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3598 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3600 /* if literal, literal on the right or
3601 if the right is in a pointer register and left
3603 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
3604 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3605 operand *t = IC_RIGHT(ic);
3606 IC_RIGHT(ic) = IC_LEFT(ic);
3610 if(ifx && !AOP_SIZE(result)){
3612 /* if they are both bit variables */
3613 if (AOP_TYPE(left) == AOP_CRY &&
3614 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3615 if(AOP_TYPE(right) == AOP_LIT){
3616 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3618 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3619 emitcode("cpl","c");
3620 } else if(lit == 1L) {
3621 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3623 emitcode("clr","c");
3625 /* AOP_TYPE(right) == AOP_CRY */
3627 symbol *lbl = newiTempLabel(NULL);
3628 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3629 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3630 emitcode("cpl","c");
3631 emitcode("","%05d$:",(lbl->key+100));
3633 /* if true label then we jump if condition
3635 tlbl = newiTempLabel(NULL);
3636 if ( IC_TRUE(ifx) ) {
3637 emitcode("jnc","%05d$",tlbl->key+100);
3638 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3640 emitcode("jc","%05d$",tlbl->key+100);
3641 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3643 emitcode("","%05d$:",tlbl->key+100);
3645 tlbl = newiTempLabel(NULL);
3646 gencjneshort(left, right, tlbl);
3647 if ( IC_TRUE(ifx) ) {
3648 emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
3649 emitcode("","%05d$:",tlbl->key+100);
3651 symbol *lbl = newiTempLabel(NULL);
3652 emitcode("sjmp","%05d$",lbl->key+100);
3653 emitcode("","%05d$:",tlbl->key+100);
3654 emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
3655 emitcode("","%05d$:",lbl->key+100);
3658 /* mark the icode as generated */
3663 /* if they are both bit variables */
3664 if (AOP_TYPE(left) == AOP_CRY &&
3665 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
3666 if(AOP_TYPE(right) == AOP_LIT){
3667 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3669 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3670 emitcode("cpl","c");
3671 } else if(lit == 1L) {
3672 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3674 emitcode("clr","c");
3676 /* AOP_TYPE(right) == AOP_CRY */
3678 symbol *lbl = newiTempLabel(NULL);
3679 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3680 emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
3681 emitcode("cpl","c");
3682 emitcode("","%05d$:",(lbl->key+100));
3685 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
3690 genIfxJump (ifx,"c");
3693 /* if the result is used in an arithmetic operation
3694 then put the result in place */
3697 gencjne(left,right,newiTempLabel(NULL));
3698 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3699 aopPut(AOP(result),"a",0);
3703 genIfxJump (ifx,"a");
3706 /* if the result is used in an arithmetic operation
3707 then put the result in place */
3708 if (AOP_TYPE(result) != AOP_CRY)
3710 /* leave the result in acc */
3714 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3715 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3716 freeAsmop(result,NULL,ic,TRUE);
3719 /*-----------------------------------------------------------------*/
3720 /* ifxForOp - returns the icode containing the ifx for operand */
3721 /*-----------------------------------------------------------------*/
3722 static iCode *ifxForOp ( operand *op, iCode *ic )
3724 /* if true symbol then needs to be assigned */
3725 if (IS_TRUE_SYMOP(op))
3728 /* if this has register type condition and
3729 the next instruction is ifx with the same operand
3730 and live to of the operand is upto the ifx only then */
3732 ic->next->op == IFX &&
3733 IC_COND(ic->next)->key == op->key &&
3734 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3739 /*-----------------------------------------------------------------*/
3740 /* genAndOp - for && operation */
3741 /*-----------------------------------------------------------------*/
3742 static void genAndOp (iCode *ic)
3744 operand *left,*right, *result;
3747 /* note here that && operations that are in an
3748 if statement are taken away by backPatchLabels
3749 only those used in arthmetic operations remain */
3750 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3751 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3752 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3754 /* if both are bit variables */
3755 if (AOP_TYPE(left) == AOP_CRY &&
3756 AOP_TYPE(right) == AOP_CRY ) {
3757 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3758 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3761 tlbl = newiTempLabel(NULL);
3763 emitcode("jz","%05d$",tlbl->key+100);
3765 emitcode("","%05d$:",tlbl->key+100);
3769 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3770 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3771 freeAsmop(result,NULL,ic,TRUE);
3775 /*-----------------------------------------------------------------*/
3776 /* genOrOp - for || operation */
3777 /*-----------------------------------------------------------------*/
3778 static void genOrOp (iCode *ic)
3780 operand *left,*right, *result;
3783 /* note here that || operations that are in an
3784 if statement are taken away by backPatchLabels
3785 only those used in arthmetic operations remain */
3786 aopOp((left=IC_LEFT(ic)),ic,FALSE);
3787 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
3788 aopOp((result=IC_RESULT(ic)),ic,FALSE);
3790 /* if both are bit variables */
3791 if (AOP_TYPE(left) == AOP_CRY &&
3792 AOP_TYPE(right) == AOP_CRY ) {
3793 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3794 emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
3797 tlbl = newiTempLabel(NULL);
3799 emitcode("jnz","%05d$",tlbl->key+100);
3801 emitcode("","%05d$:",tlbl->key+100);
3805 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3806 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3807 freeAsmop(result,NULL,ic,TRUE);
3810 /*-----------------------------------------------------------------*/
3811 /* isLiteralBit - test if lit == 2^n */
3812 /*-----------------------------------------------------------------*/
3813 static int isLiteralBit(unsigned long lit)
3815 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3816 0x100L,0x200L,0x400L,0x800L,
3817 0x1000L,0x2000L,0x4000L,0x8000L,
3818 0x10000L,0x20000L,0x40000L,0x80000L,
3819 0x100000L,0x200000L,0x400000L,0x800000L,
3820 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3821 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3824 for(idx = 0; idx < 32; idx++)
3830 /*-----------------------------------------------------------------*/
3831 /* continueIfTrue - */
3832 /*-----------------------------------------------------------------*/
3833 static void continueIfTrue (iCode *ic)
3836 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3840 /*-----------------------------------------------------------------*/
3842 /*-----------------------------------------------------------------*/
3843 static void jumpIfTrue (iCode *ic)
3846 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3850 /*-----------------------------------------------------------------*/
3851 /* jmpTrueOrFalse - */
3852 /*-----------------------------------------------------------------*/
3853 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3855 // ugly but optimized by peephole
3857 symbol *nlbl = newiTempLabel(NULL);
3858 emitcode("sjmp","%05d$",nlbl->key+100);
3859 emitcode("","%05d$:",tlbl->key+100);
3860 emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
3861 emitcode("","%05d$:",nlbl->key+100);
3864 emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
3865 emitcode("","%05d$:",tlbl->key+100);
3870 /*-----------------------------------------------------------------*/
3871 /* genAnd - code for and */
3872 /*-----------------------------------------------------------------*/
3873 static void genAnd (iCode *ic, iCode *ifx)
3875 operand *left, *right, *result;
3877 unsigned long lit = 0L;
3881 aopOp((left = IC_LEFT(ic)),ic,FALSE);
3882 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
3883 aopOp((result=IC_RESULT(ic)),ic,TRUE);
3886 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3888 AOP_TYPE(left), AOP_TYPE(right));
3889 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3891 AOP_SIZE(left), AOP_SIZE(right));
3894 /* if left is a literal & right is not then exchange them */
3895 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3896 AOP_NEEDSACC(left)) {
3897 operand *tmp = right ;
3902 /* if result = right then exchange them */
3903 if(sameRegs(AOP(result),AOP(right))){
3904 operand *tmp = right ;
3909 /* if right is bit then exchange them */
3910 if (AOP_TYPE(right) == AOP_CRY &&
3911 AOP_TYPE(left) != AOP_CRY){
3912 operand *tmp = right ;
3916 if(AOP_TYPE(right) == AOP_LIT)
3917 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3919 size = AOP_SIZE(result);
3922 // result = bit & yy;
3923 if (AOP_TYPE(left) == AOP_CRY){
3924 // c = bit & literal;
3925 if(AOP_TYPE(right) == AOP_LIT){
3927 if(size && sameRegs(AOP(result),AOP(left)))
3930 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3933 if(size && (AOP_TYPE(result) == AOP_CRY)){
3934 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
3937 if((AOP_TYPE(result) == AOP_CRY) && ifx){
3941 emitcode("clr","c");
3944 if (AOP_TYPE(right) == AOP_CRY){
3946 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3947 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3950 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
3952 emitcode("rrc","a");
3953 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
3961 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
3962 genIfxJump(ifx, "c");
3966 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3967 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3968 if((AOP_TYPE(right) == AOP_LIT) &&
3969 (AOP_TYPE(result) == AOP_CRY) &&
3970 (AOP_TYPE(left) != AOP_CRY)){
3971 int posbit = isLiteralBit(lit);
3975 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
3978 emitcode("mov","c,acc.%d",posbit&0x07);
3982 sprintf(buffer,"acc.%d",posbit&0x07);
3983 genIfxJump(ifx, buffer);
3988 symbol *tlbl = newiTempLabel(NULL);
3989 int sizel = AOP_SIZE(left);
3991 emitcode("setb","c");
3993 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3994 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
3996 if((posbit = isLiteralBit(bytelit)) != 0)
3997 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3999 if(bytelit != 0x0FFL)
4000 emitcode("anl","a,%s",
4001 aopGet(AOP(right),offset,FALSE,TRUE));
4002 emitcode("jnz","%05d$",tlbl->key+100);
4007 // bit = left & literal
4009 emitcode("clr","c");
4010 emitcode("","%05d$:",tlbl->key+100);
4012 // if(left & literal)
4015 jmpTrueOrFalse(ifx, tlbl);
4023 /* if left is same as result */
4024 if(sameRegs(AOP(result),AOP(left))){
4025 for(;size--; offset++) {
4026 if(AOP_TYPE(right) == AOP_LIT){
4027 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
4031 aopPut(AOP(result),zero,offset);
4033 if (IS_AOP_PREG(result)) {
4034 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4035 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4036 aopPut(AOP(result),"a",offset);
4038 emitcode("anl","%s,%s",
4039 aopGet(AOP(left),offset,FALSE,TRUE),
4040 aopGet(AOP(right),offset,FALSE,FALSE));
4042 if (AOP_TYPE(left) == AOP_ACC)
4043 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4045 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4046 if (IS_AOP_PREG(result)) {
4047 emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4048 aopPut(AOP(result),"a",offset);
4051 emitcode("anl","%s,a",
4052 aopGet(AOP(left),offset,FALSE,TRUE));
4057 // left & result in different registers
4058 if(AOP_TYPE(result) == AOP_CRY){
4060 // if(size), result in bit
4061 // if(!size && ifx), conditional oper: if(left & right)
4062 symbol *tlbl = newiTempLabel(NULL);
4063 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4065 emitcode("setb","c");
4067 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4068 emitcode("anl","a,%s",
4069 aopGet(AOP(left),offset,FALSE,FALSE));
4070 emitcode("jnz","%05d$",tlbl->key+100);
4075 emitcode("","%05d$:",tlbl->key+100);
4078 jmpTrueOrFalse(ifx, tlbl);
4080 for(;(size--);offset++) {
4082 // result = left & right
4083 if(AOP_TYPE(right) == AOP_LIT){
4084 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
4086 aopGet(AOP(left),offset,FALSE,FALSE),
4089 } else if(bytelit == 0){
4090 aopPut(AOP(result),zero,offset);
4094 // faster than result <- left, anl result,right
4095 // and better if result is SFR
4096 if (AOP_TYPE(left) == AOP_ACC)
4097 emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4099 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4100 emitcode("anl","a,%s",
4101 aopGet(AOP(left),offset,FALSE,FALSE));
4103 aopPut(AOP(result),"a",offset);
4109 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4110 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4111 freeAsmop(result,NULL,ic,TRUE);
4114 /*-----------------------------------------------------------------*/
4115 /* genOr - code for or */
4116 /*-----------------------------------------------------------------*/
4117 static void genOr (iCode *ic, iCode *ifx)
4119 operand *left, *right, *result;
4121 unsigned long lit = 0L;
4123 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4124 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4125 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4128 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4130 AOP_TYPE(left), AOP_TYPE(right));
4131 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4133 AOP_SIZE(left), AOP_SIZE(right));
4136 /* if left is a literal & right is not then exchange them */
4137 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4138 AOP_NEEDSACC(left)) {
4139 operand *tmp = right ;
4144 /* if result = right then exchange them */
4145 if(sameRegs(AOP(result),AOP(right))){
4146 operand *tmp = right ;
4151 /* if right is bit then exchange them */
4152 if (AOP_TYPE(right) == AOP_CRY &&
4153 AOP_TYPE(left) != AOP_CRY){
4154 operand *tmp = right ;
4158 if(AOP_TYPE(right) == AOP_LIT)
4159 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4161 size = AOP_SIZE(result);
4165 if (AOP_TYPE(left) == AOP_CRY){
4166 if(AOP_TYPE(right) == AOP_LIT){
4167 // c = bit & literal;
4169 // lit != 0 => result = 1
4170 if(AOP_TYPE(result) == AOP_CRY){
4172 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4174 continueIfTrue(ifx);
4177 emitcode("setb","c");
4179 // lit == 0 => result = left
4180 if(size && sameRegs(AOP(result),AOP(left)))
4182 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4185 if (AOP_TYPE(right) == AOP_CRY){
4187 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4188 emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
4192 symbol *tlbl = newiTempLabel(NULL);
4193 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4194 emitcode("setb","c");
4195 emitcode("jb","%s,%05d$",
4196 AOP(left)->aopu.aop_dir,tlbl->key+100);
4198 emitcode("jnz","%05d$",tlbl->key+100);
4199 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4200 jmpTrueOrFalse(ifx, tlbl);
4204 emitcode("","%05d$:",tlbl->key+100);
4213 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4214 genIfxJump(ifx, "c");
4218 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4219 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4220 if((AOP_TYPE(right) == AOP_LIT) &&
4221 (AOP_TYPE(result) == AOP_CRY) &&
4222 (AOP_TYPE(left) != AOP_CRY)){
4226 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4228 continueIfTrue(ifx);
4231 // lit = 0, result = boolean(left)
4233 emitcode("setb","c");
4236 symbol *tlbl = newiTempLabel(NULL);
4237 emitcode("jnz","%05d$",tlbl->key+100);
4239 emitcode("","%05d$:",tlbl->key+100);
4241 genIfxJump (ifx,"a");
4249 /* if left is same as result */
4250 if(sameRegs(AOP(result),AOP(left))){
4251 for(;size--; offset++) {
4252 if(AOP_TYPE(right) == AOP_LIT){
4253 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4256 if (IS_AOP_PREG(left)) {
4257 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4258 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4259 aopPut(AOP(result),"a",offset);
4261 emitcode("orl","%s,%s",
4262 aopGet(AOP(left),offset,FALSE,TRUE),
4263 aopGet(AOP(right),offset,FALSE,FALSE));
4265 if (AOP_TYPE(left) == AOP_ACC)
4266 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4268 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4269 if (IS_AOP_PREG(left)) {
4270 emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4271 aopPut(AOP(result),"a",offset);
4273 emitcode("orl","%s,a",
4274 aopGet(AOP(left),offset,FALSE,TRUE));
4279 // left & result in different registers
4280 if(AOP_TYPE(result) == AOP_CRY){
4282 // if(size), result in bit
4283 // if(!size && ifx), conditional oper: if(left | right)
4284 symbol *tlbl = newiTempLabel(NULL);
4285 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4287 emitcode("setb","c");
4289 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4290 emitcode("orl","a,%s",
4291 aopGet(AOP(left),offset,FALSE,FALSE));
4292 emitcode("jnz","%05d$",tlbl->key+100);
4297 emitcode("","%05d$:",tlbl->key+100);
4300 jmpTrueOrFalse(ifx, tlbl);
4301 } else for(;(size--);offset++){
4303 // result = left & right
4304 if(AOP_TYPE(right) == AOP_LIT){
4305 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4307 aopGet(AOP(left),offset,FALSE,FALSE),
4312 // faster than result <- left, anl result,right
4313 // and better if result is SFR
4314 if (AOP_TYPE(left) == AOP_ACC)
4315 emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4317 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4318 emitcode("orl","a,%s",
4319 aopGet(AOP(left),offset,FALSE,FALSE));
4321 aopPut(AOP(result),"a",offset);
4326 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4327 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4328 freeAsmop(result,NULL,ic,TRUE);
4331 /*-----------------------------------------------------------------*/
4332 /* genXor - code for xclusive or */
4333 /*-----------------------------------------------------------------*/
4334 static void genXor (iCode *ic, iCode *ifx)
4336 operand *left, *right, *result;
4338 unsigned long lit = 0L;
4340 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4341 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4342 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4345 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4347 AOP_TYPE(left), AOP_TYPE(right));
4348 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4350 AOP_SIZE(left), AOP_SIZE(right));
4353 /* if left is a literal & right is not ||
4354 if left needs acc & right does not */
4355 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4356 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
4357 operand *tmp = right ;
4362 /* if result = right then exchange them */
4363 if(sameRegs(AOP(result),AOP(right))){
4364 operand *tmp = right ;
4369 /* if right is bit then exchange them */
4370 if (AOP_TYPE(right) == AOP_CRY &&
4371 AOP_TYPE(left) != AOP_CRY){
4372 operand *tmp = right ;
4376 if(AOP_TYPE(right) == AOP_LIT)
4377 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4379 size = AOP_SIZE(result);
4383 if (AOP_TYPE(left) == AOP_CRY){
4384 if(AOP_TYPE(right) == AOP_LIT){
4385 // c = bit & literal;
4387 // lit>>1 != 0 => result = 1
4388 if(AOP_TYPE(result) == AOP_CRY){
4390 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
4392 continueIfTrue(ifx);
4395 emitcode("setb","c");
4399 // lit == 0, result = left
4400 if(size && sameRegs(AOP(result),AOP(left)))
4402 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4404 // lit == 1, result = not(left)
4405 if(size && sameRegs(AOP(result),AOP(left))){
4406 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
4409 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4410 emitcode("cpl","c");
4417 symbol *tlbl = newiTempLabel(NULL);
4418 if (AOP_TYPE(right) == AOP_CRY){
4420 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4423 int sizer = AOP_SIZE(right);
4425 // if val>>1 != 0, result = 1
4426 emitcode("setb","c");
4428 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
4430 // test the msb of the lsb
4431 emitcode("anl","a,#0xfe");
4432 emitcode("jnz","%05d$",tlbl->key+100);
4436 emitcode("rrc","a");
4438 emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
4439 emitcode("cpl","c");
4440 emitcode("","%05d$:",(tlbl->key+100));
4447 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4448 genIfxJump(ifx, "c");
4452 if(sameRegs(AOP(result),AOP(left))){
4453 /* if left is same as result */
4454 for(;size--; offset++) {
4455 if(AOP_TYPE(right) == AOP_LIT){
4456 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
4459 if (IS_AOP_PREG(left)) {
4460 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4461 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4462 aopPut(AOP(result),"a",offset);
4464 emitcode("xrl","%s,%s",
4465 aopGet(AOP(left),offset,FALSE,TRUE),
4466 aopGet(AOP(right),offset,FALSE,FALSE));
4468 if (AOP_TYPE(left) == AOP_ACC)
4469 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4471 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4472 if (IS_AOP_PREG(left)) {
4473 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
4474 aopPut(AOP(result),"a",offset);
4476 emitcode("xrl","%s,a",
4477 aopGet(AOP(left),offset,FALSE,TRUE));
4482 // left & result in different registers
4483 if(AOP_TYPE(result) == AOP_CRY){
4485 // if(size), result in bit
4486 // if(!size && ifx), conditional oper: if(left ^ right)
4487 symbol *tlbl = newiTempLabel(NULL);
4488 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
4490 emitcode("setb","c");
4492 if((AOP_TYPE(right) == AOP_LIT) &&
4493 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
4494 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4496 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4497 emitcode("xrl","a,%s",
4498 aopGet(AOP(left),offset,FALSE,FALSE));
4500 emitcode("jnz","%05d$",tlbl->key+100);
4505 emitcode("","%05d$:",tlbl->key+100);
4508 jmpTrueOrFalse(ifx, tlbl);
4509 } else for(;(size--);offset++){
4511 // result = left & right
4512 if(AOP_TYPE(right) == AOP_LIT){
4513 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
4515 aopGet(AOP(left),offset,FALSE,FALSE),
4520 // faster than result <- left, anl result,right
4521 // and better if result is SFR
4522 if (AOP_TYPE(left) == AOP_ACC)
4523 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
4525 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4526 emitcode("xrl","a,%s",
4527 aopGet(AOP(left),offset,FALSE,TRUE));
4529 aopPut(AOP(result),"a",offset);
4534 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4535 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4536 freeAsmop(result,NULL,ic,TRUE);
4539 /*-----------------------------------------------------------------*/
4540 /* genInline - write the inline code out */
4541 /*-----------------------------------------------------------------*/
4542 static void genInline (iCode *ic)
4544 char buffer[MAX_INLINEASM];
4548 _G.inLine += (!options.asmpeep);
4549 strcpy(buffer,IC_INLINE(ic));
4551 /* emit each line as a code */
4570 /* emitcode("",buffer); */
4571 _G.inLine -= (!options.asmpeep);
4574 /*-----------------------------------------------------------------*/
4575 /* genRRC - rotate right with carry */
4576 /*-----------------------------------------------------------------*/
4577 static void genRRC (iCode *ic)
4579 operand *left , *result ;
4580 int size, offset = 0;
4583 /* rotate right with carry */
4585 result=IC_RESULT(ic);
4586 aopOp (left,ic,FALSE);
4587 aopOp (result,ic,FALSE);
4589 /* move it to the result */
4590 size = AOP_SIZE(result);
4594 l = aopGet(AOP(left),offset,FALSE,FALSE);
4596 emitcode("rrc","a");
4597 if (AOP_SIZE(result) > 1)
4598 aopPut(AOP(result),"a",offset--);
4600 /* now we need to put the carry into the
4601 highest order byte of the result */
4602 if (AOP_SIZE(result) > 1) {
4603 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
4606 emitcode("mov","acc.7,c");
4607 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
4608 freeAsmop(left,NULL,ic,TRUE);
4609 freeAsmop(result,NULL,ic,TRUE);
4612 /*-----------------------------------------------------------------*/
4613 /* genRLC - generate code for rotate left with carry */
4614 /*-----------------------------------------------------------------*/
4615 static void genRLC (iCode *ic)
4617 operand *left , *result ;
4618 int size, offset = 0;
4621 /* rotate right with carry */
4623 result=IC_RESULT(ic);
4624 aopOp (left,ic,FALSE);
4625 aopOp (result,ic,FALSE);
4627 /* move it to the result */
4628 size = AOP_SIZE(result);
4631 l = aopGet(AOP(left),offset,FALSE,FALSE);
4633 emitcode("add","a,acc");
4634 if (AOP_SIZE(result) > 1)
4635 aopPut(AOP(result),"a",offset++);
4637 l = aopGet(AOP(left),offset,FALSE,FALSE);
4639 emitcode("rlc","a");
4640 if (AOP_SIZE(result) > 1)
4641 aopPut(AOP(result),"a",offset++);
4644 /* now we need to put the carry into the
4645 highest order byte of the result */
4646 if (AOP_SIZE(result) > 1) {
4647 l = aopGet(AOP(result),0,FALSE,FALSE);
4650 emitcode("mov","acc.0,c");
4651 aopPut(AOP(result),"a",0);
4652 freeAsmop(left,NULL,ic,TRUE);
4653 freeAsmop(result,NULL,ic,TRUE);
4656 /*-----------------------------------------------------------------*/
4657 /* genGetHbit - generates code get highest order bit */
4658 /*-----------------------------------------------------------------*/
4659 static void genGetHbit (iCode *ic)
4661 operand *left, *result;
4663 result=IC_RESULT(ic);
4664 aopOp (left,ic,FALSE);
4665 aopOp (result,ic,FALSE);
4667 /* get the highest order byte into a */
4668 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
4669 if(AOP_TYPE(result) == AOP_CRY){
4670 emitcode("rlc","a");
4675 emitcode("anl","a,#0x01");
4680 freeAsmop(left,NULL,ic,TRUE);
4681 freeAsmop(result,NULL,ic,TRUE);
4684 /*-----------------------------------------------------------------*/
4685 /* AccRol - rotate left accumulator by known count */
4686 /*-----------------------------------------------------------------*/
4687 static void AccRol (int shCount)
4689 shCount &= 0x0007; // shCount : 0..7
4701 emitcode("swap","a");
4705 emitcode("swap","a");
4708 emitcode("swap","a");
4721 /*-----------------------------------------------------------------*/
4722 /* AccLsh - left shift accumulator by known count */
4723 /*-----------------------------------------------------------------*/
4724 static void AccLsh (int shCount)
4728 emitcode("add","a,acc");
4731 emitcode("add","a,acc");
4732 emitcode("add","a,acc");
4734 /* rotate left accumulator */
4736 /* and kill the lower order bits */
4737 emitcode("anl","a,#0x%02x", SLMask[shCount]);
4742 /*-----------------------------------------------------------------*/
4743 /* AccRsh - right shift accumulator by known count */
4744 /*-----------------------------------------------------------------*/
4745 static void AccRsh (int shCount)
4750 emitcode("rrc","a");
4752 /* rotate right accumulator */
4753 AccRol(8 - shCount);
4754 /* and kill the higher order bits */
4755 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4760 /*-----------------------------------------------------------------*/
4761 /* AccSRsh - signed right shift accumulator by known count */
4762 /*-----------------------------------------------------------------*/
4763 static void AccSRsh (int shCount)
4768 emitcode("mov","c,acc.7");
4769 emitcode("rrc","a");
4770 } else if(shCount == 2){
4771 emitcode("mov","c,acc.7");
4772 emitcode("rrc","a");
4773 emitcode("mov","c,acc.7");
4774 emitcode("rrc","a");
4776 tlbl = newiTempLabel(NULL);
4777 /* rotate right accumulator */
4778 AccRol(8 - shCount);
4779 /* and kill the higher order bits */
4780 emitcode("anl","a,#0x%02x", SRMask[shCount]);
4781 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
4782 emitcode("orl","a,#0x%02x",
4783 (unsigned char)~SRMask[shCount]);
4784 emitcode("","%05d$:",tlbl->key+100);
4789 /*-----------------------------------------------------------------*/
4790 /* shiftR1Left2Result - shift right one byte from left to result */
4791 /*-----------------------------------------------------------------*/
4792 static void shiftR1Left2Result (operand *left, int offl,
4793 operand *result, int offr,
4794 int shCount, int sign)
4796 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
4797 /* shift right accumulator */
4802 aopPut(AOP(result),"a",offr);
4805 /*-----------------------------------------------------------------*/
4806 /* shiftL1Left2Result - shift left one byte from left to result */
4807 /*-----------------------------------------------------------------*/
4808 static void shiftL1Left2Result (operand *left, int offl,
4809 operand *result, int offr, int shCount)
4812 l = aopGet(AOP(left),offl,FALSE,FALSE);
4814 /* shift left accumulator */
4816 aopPut(AOP(result),"a",offr);
4819 /*-----------------------------------------------------------------*/
4820 /* movLeft2Result - move byte from left to result */
4821 /*-----------------------------------------------------------------*/
4822 static void movLeft2Result (operand *left, int offl,
4823 operand *result, int offr, int sign)
4826 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
4827 l = aopGet(AOP(left),offl,FALSE,FALSE);
4829 if (*l == '@' && (IS_AOP_PREG(result))) {
4830 emitcode("mov","a,%s",l);
4831 aopPut(AOP(result),"a",offr);
4834 aopPut(AOP(result),l,offr);
4836 /* MSB sign in acc.7 ! */
4837 if(getDataSize(left) == offl+1){
4838 emitcode("mov","a,%s",l);
4839 aopPut(AOP(result),"a",offr);
4846 /*-----------------------------------------------------------------*/
4847 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
4848 /*-----------------------------------------------------------------*/
4849 static void AccAXRrl1 (char *x)
4851 emitcode("rrc","a");
4852 emitcode("xch","a,%s", x);
4853 emitcode("rrc","a");
4854 emitcode("xch","a,%s", x);
4857 /*-----------------------------------------------------------------*/
4858 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
4859 /*-----------------------------------------------------------------*/
4860 static void AccAXLrl1 (char *x)
4862 emitcode("xch","a,%s",x);
4863 emitcode("rlc","a");
4864 emitcode("xch","a,%s",x);
4865 emitcode("rlc","a");
4868 /*-----------------------------------------------------------------*/
4869 /* AccAXLsh1 - left shift a:x<-0 by 1 */
4870 /*-----------------------------------------------------------------*/
4871 static void AccAXLsh1 (char *x)
4873 emitcode("xch","a,%s",x);
4874 emitcode("add","a,acc");
4875 emitcode("xch","a,%s",x);
4876 emitcode("rlc","a");
4879 /*-----------------------------------------------------------------*/
4880 /* AccAXLsh - left shift a:x by known count (0..7) */
4881 /*-----------------------------------------------------------------*/
4882 static void AccAXLsh (char *x, int shCount)
4896 case 5 : // AAAAABBB:CCCCCDDD
4897 AccRol(shCount); // BBBAAAAA:CCCCCDDD
4898 emitcode("anl","a,#0x%02x",
4899 SLMask[shCount]); // BBB00000:CCCCCDDD
4900 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
4901 AccRol(shCount); // DDDCCCCC:BBB00000
4902 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
4903 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
4904 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
4905 emitcode("anl","a,#0x%02x",
4906 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
4907 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
4908 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
4910 case 6 : // AAAAAABB:CCCCCCDD
4911 emitcode("anl","a,#0x%02x",
4912 SRMask[shCount]); // 000000BB:CCCCCCDD
4913 emitcode("mov","c,acc.0"); // c = B
4914 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
4915 AccAXRrl1(x); // BCCCCCCD:D000000B
4916 AccAXRrl1(x); // BBCCCCCC:DD000000
4918 case 7 : // a:x <<= 7
4919 emitcode("anl","a,#0x%02x",
4920 SRMask[shCount]); // 0000000B:CCCCCCCD
4921 emitcode("mov","c,acc.0"); // c = B
4922 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
4923 AccAXRrl1(x); // BCCCCCCC:D0000000
4930 /*-----------------------------------------------------------------*/
4931 /* AccAXRsh - right shift a:x known count (0..7) */
4932 /*-----------------------------------------------------------------*/
4933 static void AccAXRsh (char *x, int shCount)
4940 AccAXRrl1(x); // 0->a:x
4944 AccAXRrl1(x); // 0->a:x
4946 AccAXRrl1(x); // 0->a:x
4950 case 5 : // AAAAABBB:CCCCCDDD = a:x
4951 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
4952 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
4953 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
4954 emitcode("anl","a,#0x%02x",
4955 SRMask[shCount]); // 000CCCCC:BBBAAAAA
4956 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
4957 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
4958 emitcode("anl","a,#0x%02x",
4959 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
4960 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
4961 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
4962 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
4964 case 6 : // AABBBBBB:CCDDDDDD
4965 emitcode("mov","c,acc.7");
4966 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
4967 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
4968 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
4969 emitcode("anl","a,#0x%02x",
4970 SRMask[shCount]); // 000000AA:BBBBBBCC
4972 case 7 : // ABBBBBBB:CDDDDDDD
4973 emitcode("mov","c,acc.7"); // c = A
4974 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
4975 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
4976 emitcode("anl","a,#0x%02x",
4977 SRMask[shCount]); // 0000000A:BBBBBBBC
4984 /*-----------------------------------------------------------------*/
4985 /* AccAXRshS - right shift signed a:x known count (0..7) */
4986 /*-----------------------------------------------------------------*/
4987 static void AccAXRshS (char *x, int shCount)
4994 emitcode("mov","c,acc.7");
4995 AccAXRrl1(x); // s->a:x
4998 emitcode("mov","c,acc.7");
4999 AccAXRrl1(x); // s->a:x
5000 emitcode("mov","c,acc.7");
5001 AccAXRrl1(x); // s->a:x
5005 case 5 : // AAAAABBB:CCCCCDDD = a:x
5006 tlbl = newiTempLabel(NULL);
5007 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5008 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5009 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5010 emitcode("anl","a,#0x%02x",
5011 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5012 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5013 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5014 emitcode("anl","a,#0x%02x",
5015 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5016 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5017 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5018 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5019 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5020 emitcode("orl","a,#0x%02x",
5021 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5022 emitcode("","%05d$:",tlbl->key+100);
5023 break; // SSSSAAAA:BBBCCCCC
5024 case 6 : // AABBBBBB:CCDDDDDD
5025 tlbl = newiTempLabel(NULL);
5026 emitcode("mov","c,acc.7");
5027 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5028 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5029 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5030 emitcode("anl","a,#0x%02x",
5031 SRMask[shCount]); // 000000AA:BBBBBBCC
5032 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5033 emitcode("orl","a,#0x%02x",
5034 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5035 emitcode("","%05d$:",tlbl->key+100);
5037 case 7 : // ABBBBBBB:CDDDDDDD
5038 tlbl = newiTempLabel(NULL);
5039 emitcode("mov","c,acc.7"); // c = A
5040 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5041 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5042 emitcode("anl","a,#0x%02x",
5043 SRMask[shCount]); // 0000000A:BBBBBBBC
5044 emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
5045 emitcode("orl","a,#0x%02x",
5046 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5047 emitcode("","%05d$:",tlbl->key+100);
5054 /*-----------------------------------------------------------------*/
5055 /* shiftL2Left2Result - shift left two bytes from left to result */
5056 /*-----------------------------------------------------------------*/
5057 static void shiftL2Left2Result (operand *left, int offl,
5058 operand *result, int offr, int shCount)
5060 if(sameRegs(AOP(result), AOP(left)) &&
5061 ((offl + MSB16) == offr)){
5062 /* don't crash result[offr] */
5063 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5064 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5066 movLeft2Result(left,offl, result, offr, 0);
5067 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5069 /* ax << shCount (x = lsb(result))*/
5070 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5071 aopPut(AOP(result),"a",offr+MSB16);
5075 /*-----------------------------------------------------------------*/
5076 /* shiftR2Left2Result - shift right two bytes from left to result */
5077 /*-----------------------------------------------------------------*/
5078 static void shiftR2Left2Result (operand *left, int offl,
5079 operand *result, int offr,
5080 int shCount, int sign)
5082 if(sameRegs(AOP(result), AOP(left)) &&
5083 ((offl + MSB16) == offr)){
5084 /* don't crash result[offr] */
5085 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5086 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5088 movLeft2Result(left,offl, result, offr, 0);
5089 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5091 /* a:x >> shCount (x = lsb(result))*/
5093 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5095 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5096 if(getDataSize(result) > 1)
5097 aopPut(AOP(result),"a",offr+MSB16);
5100 /*-----------------------------------------------------------------*/
5101 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5102 /*-----------------------------------------------------------------*/
5103 static void shiftLLeftOrResult (operand *left, int offl,
5104 operand *result, int offr, int shCount)
5106 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5107 /* shift left accumulator */
5109 /* or with result */
5110 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5111 /* back to result */
5112 aopPut(AOP(result),"a",offr);
5115 /*-----------------------------------------------------------------*/
5116 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5117 /*-----------------------------------------------------------------*/
5118 static void shiftRLeftOrResult (operand *left, int offl,
5119 operand *result, int offr, int shCount)
5121 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5122 /* shift right accumulator */
5124 /* or with result */
5125 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5126 /* back to result */
5127 aopPut(AOP(result),"a",offr);
5130 /*-----------------------------------------------------------------*/
5131 /* genlshOne - left shift a one byte quantity by known count */
5132 /*-----------------------------------------------------------------*/
5133 static void genlshOne (operand *result, operand *left, int shCount)
5135 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5138 /*-----------------------------------------------------------------*/
5139 /* genlshTwo - left shift two bytes by known amount != 0 */
5140 /*-----------------------------------------------------------------*/
5141 static void genlshTwo (operand *result,operand *left, int shCount)
5145 size = getDataSize(result);
5147 /* if shCount >= 8 */
5153 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5155 movLeft2Result(left, LSB, result, MSB16, 0);
5157 aopPut(AOP(result),zero,LSB);
5160 /* 1 <= shCount <= 7 */
5163 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5165 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5169 /*-----------------------------------------------------------------*/
5170 /* shiftLLong - shift left one long from left to result */
5171 /* offl = LSB or MSB16 */
5172 /*-----------------------------------------------------------------*/
5173 static void shiftLLong (operand *left, operand *result, int offr )
5176 int size = AOP_SIZE(result);
5178 if(size >= LSB+offr){
5179 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5181 emitcode("add","a,acc");
5182 if (sameRegs(AOP(left),AOP(result)) &&
5183 size >= MSB16+offr && offr != LSB )
5184 emitcode("xch","a,%s",
5185 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5187 aopPut(AOP(result),"a",LSB+offr);
5190 if(size >= MSB16+offr){
5191 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5192 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5195 emitcode("rlc","a");
5196 if (sameRegs(AOP(left),AOP(result)) &&
5197 size >= MSB24+offr && offr != LSB)
5198 emitcode("xch","a,%s",
5199 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5201 aopPut(AOP(result),"a",MSB16+offr);
5204 if(size >= MSB24+offr){
5205 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5206 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5209 emitcode("rlc","a");
5210 if (sameRegs(AOP(left),AOP(result)) &&
5211 size >= MSB32+offr && offr != LSB )
5212 emitcode("xch","a,%s",
5213 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5215 aopPut(AOP(result),"a",MSB24+offr);
5218 if(size > MSB32+offr){
5219 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5220 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5223 emitcode("rlc","a");
5224 aopPut(AOP(result),"a",MSB32+offr);
5227 aopPut(AOP(result),zero,LSB);
5230 /*-----------------------------------------------------------------*/
5231 /* genlshFour - shift four byte by a known amount != 0 */
5232 /*-----------------------------------------------------------------*/
5233 static void genlshFour (operand *result, operand *left, int shCount)
5237 size = AOP_SIZE(result);
5239 /* if shifting more that 3 bytes */
5240 if (shCount >= 24 ) {
5243 /* lowest order of left goes to the highest
5244 order of the destination */
5245 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
5247 movLeft2Result(left, LSB, result, MSB32, 0);
5248 aopPut(AOP(result),zero,LSB);
5249 aopPut(AOP(result),zero,MSB16);
5250 aopPut(AOP(result),zero,MSB32);
5254 /* more than two bytes */
5255 else if ( shCount >= 16 ) {
5256 /* lower order two bytes goes to higher order two bytes */
5258 /* if some more remaining */
5260 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
5262 movLeft2Result(left, MSB16, result, MSB32, 0);
5263 movLeft2Result(left, LSB, result, MSB24, 0);
5265 aopPut(AOP(result),zero,MSB16);
5266 aopPut(AOP(result),zero,LSB);
5270 /* if more than 1 byte */
5271 else if ( shCount >= 8 ) {
5272 /* lower order three bytes goes to higher order three bytes */
5276 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5278 movLeft2Result(left, LSB, result, MSB16, 0);
5280 else{ /* size = 4 */
5282 movLeft2Result(left, MSB24, result, MSB32, 0);
5283 movLeft2Result(left, MSB16, result, MSB24, 0);
5284 movLeft2Result(left, LSB, result, MSB16, 0);
5285 aopPut(AOP(result),zero,LSB);
5287 else if(shCount == 1)
5288 shiftLLong(left, result, MSB16);
5290 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
5291 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5292 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
5293 aopPut(AOP(result),zero,LSB);
5298 /* 1 <= shCount <= 7 */
5299 else if(shCount <= 2){
5300 shiftLLong(left, result, LSB);
5302 shiftLLong(result, result, LSB);
5304 /* 3 <= shCount <= 7, optimize */
5306 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
5307 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
5308 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5312 /*-----------------------------------------------------------------*/
5313 /* genLeftShiftLiteral - left shifting by known count */
5314 /*-----------------------------------------------------------------*/
5315 static void genLeftShiftLiteral (operand *left,
5320 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5323 freeAsmop(right,NULL,ic,TRUE);
5325 aopOp(left,ic,FALSE);
5326 aopOp(result,ic,FALSE);
5328 size = getSize(operandType(result));
5331 emitcode("; shift left ","result %d, left %d",size,
5335 /* I suppose that the left size >= result size */
5338 movLeft2Result(left, size, result, size, 0);
5342 else if(shCount >= (size * 8))
5344 aopPut(AOP(result),zero,size);
5348 genlshOne (result,left,shCount);
5353 genlshTwo (result,left,shCount);
5357 genlshFour (result,left,shCount);
5361 freeAsmop(left,NULL,ic,TRUE);
5362 freeAsmop(result,NULL,ic,TRUE);
5365 /*-----------------------------------------------------------------*/
5366 /* genLeftShift - generates code for left shifting */
5367 /*-----------------------------------------------------------------*/
5368 static void genLeftShift (iCode *ic)
5370 operand *left,*right, *result;
5373 symbol *tlbl , *tlbl1;
5375 right = IC_RIGHT(ic);
5377 result = IC_RESULT(ic);
5379 aopOp(right,ic,FALSE);
5381 /* if the shift count is known then do it
5382 as efficiently as possible */
5383 if (AOP_TYPE(right) == AOP_LIT) {
5384 genLeftShiftLiteral (left,right,result,ic);
5388 /* shift count is unknown then we have to form
5389 a loop get the loop count in B : Note: we take
5390 only the lower order byte since shifting
5391 more that 32 bits make no sense anyway, ( the
5392 largest size of an object can be only 32 bits ) */
5394 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5395 emitcode("inc","b");
5396 freeAsmop (right,NULL,ic,TRUE);
5397 aopOp(left,ic,FALSE);
5398 aopOp(result,ic,FALSE);
5400 /* now move the left to the result if they are not the
5402 if (!sameRegs(AOP(left),AOP(result)) &&
5403 AOP_SIZE(result) > 1) {
5405 size = AOP_SIZE(result);
5408 l = aopGet(AOP(left),offset,FALSE,TRUE);
5409 if (*l == '@' && (IS_AOP_PREG(result))) {
5411 emitcode("mov","a,%s",l);
5412 aopPut(AOP(result),"a",offset);
5414 aopPut(AOP(result),l,offset);
5419 tlbl = newiTempLabel(NULL);
5420 size = AOP_SIZE(result);
5422 tlbl1 = newiTempLabel(NULL);
5424 /* if it is only one byte then */
5426 symbol *tlbl1 = newiTempLabel(NULL);
5428 l = aopGet(AOP(left),0,FALSE,FALSE);
5430 emitcode("sjmp","%05d$",tlbl1->key+100);
5431 emitcode("","%05d$:",tlbl->key+100);
5432 emitcode("add","a,acc");
5433 emitcode("","%05d$:",tlbl1->key+100);
5434 emitcode("djnz","b,%05d$",tlbl->key+100);
5435 aopPut(AOP(result),"a",0);
5439 reAdjustPreg(AOP(result));
5441 emitcode("sjmp","%05d$",tlbl1->key+100);
5442 emitcode("","%05d$:",tlbl->key+100);
5443 l = aopGet(AOP(result),offset,FALSE,FALSE);
5445 emitcode("add","a,acc");
5446 aopPut(AOP(result),"a",offset++);
5448 l = aopGet(AOP(result),offset,FALSE,FALSE);
5450 emitcode("rlc","a");
5451 aopPut(AOP(result),"a",offset++);
5453 reAdjustPreg(AOP(result));
5455 emitcode("","%05d$:",tlbl1->key+100);
5456 emitcode("djnz","b,%05d$",tlbl->key+100);
5458 freeAsmop(left,NULL,ic,TRUE);
5459 freeAsmop(result,NULL,ic,TRUE);
5462 /*-----------------------------------------------------------------*/
5463 /* genrshOne - right shift a one byte quantity by known count */
5464 /*-----------------------------------------------------------------*/
5465 static void genrshOne (operand *result, operand *left,
5466 int shCount, int sign)
5468 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
5471 /*-----------------------------------------------------------------*/
5472 /* genrshTwo - right shift two bytes by known amount != 0 */
5473 /*-----------------------------------------------------------------*/
5474 static void genrshTwo (operand *result,operand *left,
5475 int shCount, int sign)
5477 /* if shCount >= 8 */
5481 shiftR1Left2Result(left, MSB16, result, LSB,
5484 movLeft2Result(left, MSB16, result, LSB, sign);
5485 addSign(result, MSB16, sign);
5488 /* 1 <= shCount <= 7 */
5490 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
5493 /*-----------------------------------------------------------------*/
5494 /* shiftRLong - shift right one long from left to result */
5495 /* offl = LSB or MSB16 */
5496 /*-----------------------------------------------------------------*/
5497 static void shiftRLong (operand *left, int offl,
5498 operand *result, int sign)
5501 emitcode("clr","c");
5502 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
5504 emitcode("mov","c,acc.7");
5505 emitcode("rrc","a");
5506 aopPut(AOP(result),"a",MSB32-offl);
5508 /* add sign of "a" */
5509 addSign(result, MSB32, sign);
5511 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
5512 emitcode("rrc","a");
5513 aopPut(AOP(result),"a",MSB24-offl);
5515 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
5516 emitcode("rrc","a");
5517 aopPut(AOP(result),"a",MSB16-offl);
5520 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
5521 emitcode("rrc","a");
5522 aopPut(AOP(result),"a",LSB);
5526 /*-----------------------------------------------------------------*/
5527 /* genrshFour - shift four byte by a known amount != 0 */
5528 /*-----------------------------------------------------------------*/
5529 static void genrshFour (operand *result, operand *left,
5530 int shCount, int sign)
5532 /* if shifting more that 3 bytes */
5533 if(shCount >= 24 ) {
5536 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
5538 movLeft2Result(left, MSB32, result, LSB, sign);
5539 addSign(result, MSB16, sign);
5541 else if(shCount >= 16){
5544 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
5546 movLeft2Result(left, MSB24, result, LSB, 0);
5547 movLeft2Result(left, MSB32, result, MSB16, sign);
5549 addSign(result, MSB24, sign);
5551 else if(shCount >= 8){
5554 shiftRLong(left, MSB16, result, sign);
5555 else if(shCount == 0){
5556 movLeft2Result(left, MSB16, result, LSB, 0);
5557 movLeft2Result(left, MSB24, result, MSB16, 0);
5558 movLeft2Result(left, MSB32, result, MSB24, sign);
5559 addSign(result, MSB32, sign);
5562 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
5563 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
5564 /* the last shift is signed */
5565 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
5566 addSign(result, MSB32, sign);
5569 else{ /* 1 <= shCount <= 7 */
5571 shiftRLong(left, LSB, result, sign);
5573 shiftRLong(result, LSB, result, sign);
5576 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
5577 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
5578 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
5583 /*-----------------------------------------------------------------*/
5584 /* genRightShiftLiteral - right shifting by known count */
5585 /*-----------------------------------------------------------------*/
5586 static void genRightShiftLiteral (operand *left,
5592 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
5595 freeAsmop(right,NULL,ic,TRUE);
5597 aopOp(left,ic,FALSE);
5598 aopOp(result,ic,FALSE);
5601 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
5605 size = getDataSize(left);
5606 /* test the LEFT size !!! */
5608 /* I suppose that the left size >= result size */
5610 size = getDataSize(result);
5612 movLeft2Result(left, size, result, size, 0);
5615 else if(shCount >= (size * 8)){
5617 /* get sign in acc.7 */
5618 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
5619 addSign(result, LSB, sign);
5623 genrshOne (result,left,shCount,sign);
5627 genrshTwo (result,left,shCount,sign);
5631 genrshFour (result,left,shCount,sign);
5637 freeAsmop(left,NULL,ic,TRUE);
5638 freeAsmop(result,NULL,ic,TRUE);
5642 /*-----------------------------------------------------------------*/
5643 /* genSignedRightShift - right shift of signed number */
5644 /*-----------------------------------------------------------------*/
5645 static void genSignedRightShift (iCode *ic)
5647 operand *right, *left, *result;
5650 symbol *tlbl, *tlbl1 ;
5652 /* we do it the hard way put the shift count in b
5653 and loop thru preserving the sign */
5655 right = IC_RIGHT(ic);
5657 result = IC_RESULT(ic);
5659 aopOp(right,ic,FALSE);
5662 if ( AOP_TYPE(right) == AOP_LIT) {
5663 genRightShiftLiteral (left,right,result,ic,1);
5666 /* shift count is unknown then we have to form
5667 a loop get the loop count in B : Note: we take
5668 only the lower order byte since shifting
5669 more that 32 bits make no sense anyway, ( the
5670 largest size of an object can be only 32 bits ) */
5672 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5673 emitcode("inc","b");
5674 freeAsmop (right,NULL,ic,TRUE);
5675 aopOp(left,ic,FALSE);
5676 aopOp(result,ic,FALSE);
5678 /* now move the left to the result if they are not the
5680 if (!sameRegs(AOP(left),AOP(result)) &&
5681 AOP_SIZE(result) > 1) {
5683 size = AOP_SIZE(result);
5686 l = aopGet(AOP(left),offset,FALSE,TRUE);
5687 if (*l == '@' && IS_AOP_PREG(result)) {
5689 emitcode("mov","a,%s",l);
5690 aopPut(AOP(result),"a",offset);
5692 aopPut(AOP(result),l,offset);
5697 /* mov the highest order bit to OVR */
5698 tlbl = newiTempLabel(NULL);
5699 tlbl1= newiTempLabel(NULL);
5701 size = AOP_SIZE(result);
5703 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
5704 emitcode("rlc","a");
5705 emitcode("mov","ov,c");
5706 /* if it is only one byte then */
5708 l = aopGet(AOP(left),0,FALSE,FALSE);
5710 emitcode("sjmp","%05d$",tlbl1->key+100);
5711 emitcode("","%05d$:",tlbl->key+100);
5712 emitcode("mov","c,ov");
5713 emitcode("rrc","a");
5714 emitcode("","%05d$:",tlbl1->key+100);
5715 emitcode("djnz","b,%05d$",tlbl->key+100);
5716 aopPut(AOP(result),"a",0);
5720 reAdjustPreg(AOP(result));
5721 emitcode("sjmp","%05d$",tlbl1->key+100);
5722 emitcode("","%05d$:",tlbl->key+100);
5723 emitcode("mov","c,ov");
5725 l = aopGet(AOP(result),offset,FALSE,FALSE);
5727 emitcode("rrc","a");
5728 aopPut(AOP(result),"a",offset--);
5730 reAdjustPreg(AOP(result));
5731 emitcode("","%05d$:",tlbl1->key+100);
5732 emitcode("djnz","b,%05d$",tlbl->key+100);
5735 freeAsmop(left,NULL,ic,TRUE);
5736 freeAsmop(result,NULL,ic,TRUE);
5739 /*-----------------------------------------------------------------*/
5740 /* genRightShift - generate code for right shifting */
5741 /*-----------------------------------------------------------------*/
5742 static void genRightShift (iCode *ic)
5744 operand *right, *left, *result;
5748 symbol *tlbl, *tlbl1 ;
5750 /* if signed then we do it the hard way preserve the
5751 sign bit moving it inwards */
5752 retype = getSpec(operandType(IC_RESULT(ic)));
5754 if (!SPEC_USIGN(retype)) {
5755 genSignedRightShift (ic);
5759 /* signed & unsigned types are treated the same : i.e. the
5760 signed is NOT propagated inwards : quoting from the
5761 ANSI - standard : "for E1 >> E2, is equivalent to division
5762 by 2**E2 if unsigned or if it has a non-negative value,
5763 otherwise the result is implementation defined ", MY definition
5764 is that the sign does not get propagated */
5766 right = IC_RIGHT(ic);
5768 result = IC_RESULT(ic);
5770 aopOp(right,ic,FALSE);
5772 /* if the shift count is known then do it
5773 as efficiently as possible */
5774 if (AOP_TYPE(right) == AOP_LIT) {
5775 genRightShiftLiteral (left,right,result,ic, 0);
5779 /* shift count is unknown then we have to form
5780 a loop get the loop count in B : Note: we take
5781 only the lower order byte since shifting
5782 more that 32 bits make no sense anyway, ( the
5783 largest size of an object can be only 32 bits ) */
5785 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
5786 emitcode("inc","b");
5787 freeAsmop (right,NULL,ic,TRUE);
5788 aopOp(left,ic,FALSE);
5789 aopOp(result,ic,FALSE);
5791 /* now move the left to the result if they are not the
5793 if (!sameRegs(AOP(left),AOP(result)) &&
5794 AOP_SIZE(result) > 1) {
5796 size = AOP_SIZE(result);
5799 l = aopGet(AOP(left),offset,FALSE,TRUE);
5800 if (*l == '@' && IS_AOP_PREG(result)) {
5802 emitcode("mov","a,%s",l);
5803 aopPut(AOP(result),"a",offset);
5805 aopPut(AOP(result),l,offset);
5810 tlbl = newiTempLabel(NULL);
5811 tlbl1= newiTempLabel(NULL);
5812 size = AOP_SIZE(result);
5815 /* if it is only one byte then */
5817 l = aopGet(AOP(left),0,FALSE,FALSE);
5819 emitcode("sjmp","%05d$",tlbl1->key+100);
5820 emitcode("","%05d$:",tlbl->key+100);
5822 emitcode("rrc","a");
5823 emitcode("","%05d$:",tlbl1->key+100);
5824 emitcode("djnz","b,%05d$",tlbl->key+100);
5825 aopPut(AOP(result),"a",0);
5829 reAdjustPreg(AOP(result));
5830 emitcode("sjmp","%05d$",tlbl1->key+100);
5831 emitcode("","%05d$:",tlbl->key+100);
5834 l = aopGet(AOP(result),offset,FALSE,FALSE);
5836 emitcode("rrc","a");
5837 aopPut(AOP(result),"a",offset--);
5839 reAdjustPreg(AOP(result));
5841 emitcode("","%05d$:",tlbl1->key+100);
5842 emitcode("djnz","b,%05d$",tlbl->key+100);
5845 freeAsmop(left,NULL,ic,TRUE);
5846 freeAsmop(result,NULL,ic,TRUE);
5849 /*-----------------------------------------------------------------*/
5850 /* genUnpackBits - generates code for unpacking bits */
5851 /*-----------------------------------------------------------------*/
5852 static void genUnpackBits (operand *result, char *rname, int ptype)
5859 etype = getSpec(operandType(result));
5861 /* read the first byte */
5866 emitcode("mov","a,@%s",rname);
5870 emitcode("movx","a,@%s",rname);
5874 emitcode("movx","a,@dptr");
5878 emitcode("clr","a");
5879 emitcode("movc","a","@a+dptr");
5883 emitcode("lcall","__gptrget");
5887 /* if we have bitdisplacement then it fits */
5888 /* into this byte completely or if length is */
5889 /* less than a byte */
5890 if ((shCnt = SPEC_BSTR(etype)) ||
5891 (SPEC_BLEN(etype) <= 8)) {
5893 /* shift right acc */
5896 emitcode("anl","a,#0x%02x",
5897 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
5898 aopPut(AOP(result),"a",offset);
5902 /* bit field did not fit in a byte */
5903 rlen = SPEC_BLEN(etype) - 8;
5904 aopPut(AOP(result),"a",offset++);
5911 emitcode("inc","%s",rname);
5912 emitcode("mov","a,@%s",rname);
5916 emitcode("inc","%s",rname);
5917 emitcode("movx","a,@%s",rname);
5921 emitcode("inc","dptr");
5922 emitcode("movx","a,@dptr");
5926 emitcode("clr","a");
5927 emitcode("inc","dptr");
5928 emitcode("movc","a","@a+dptr");
5932 emitcode("inc","dptr");
5933 emitcode("lcall","__gptrget");
5938 /* if we are done */
5942 aopPut(AOP(result),"a",offset++);
5947 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
5948 aopPut(AOP(result),"a",offset);
5955 /*-----------------------------------------------------------------*/
5956 /* genDataPointerGet - generates code when ptr offset is known */
5957 /*-----------------------------------------------------------------*/
5958 static void genDataPointerGet (operand *left,
5964 int size , offset = 0;
5965 aopOp(result,ic,TRUE);
5967 /* get the string representation of the name */
5968 l = aopGet(AOP(left),0,FALSE,TRUE);
5969 size = AOP_SIZE(result);
5972 sprintf(buffer,"(%s + %d)",l+1,offset);
5974 sprintf(buffer,"%s",l+1);
5975 aopPut(AOP(result),buffer,offset++);
5978 freeAsmop(left,NULL,ic,TRUE);
5979 freeAsmop(result,NULL,ic,TRUE);
5982 /*-----------------------------------------------------------------*/
5983 /* genNearPointerGet - emitcode for near pointer fetch */
5984 /*-----------------------------------------------------------------*/
5985 static void genNearPointerGet (operand *left,
5992 link *rtype, *retype;
5993 link *ltype = operandType(left);
5996 rtype = operandType(result);
5997 retype= getSpec(rtype);
5999 aopOp(left,ic,FALSE);
6001 /* if left is rematerialisable and
6002 result is not bit variable type and
6003 the left is pointer to data space i.e
6004 lower 128 bytes of space */
6005 if (AOP_TYPE(left) == AOP_IMMD &&
6006 !IS_BITVAR(retype) &&
6007 DCL_TYPE(ltype) == POINTER) {
6008 genDataPointerGet (left,result,ic);
6012 /* if the value is already in a pointer register
6013 then don't need anything more */
6014 if (!AOP_INPREG(AOP(left))) {
6015 /* otherwise get a free pointer register */
6017 preg = getFreePtr(ic,&aop,FALSE);
6018 emitcode("mov","%s,%s",
6020 aopGet(AOP(left),0,FALSE,TRUE));
6021 rname = preg->name ;
6023 rname = aopGet(AOP(left),0,FALSE,FALSE);
6025 freeAsmop(left,NULL,ic,TRUE);
6026 aopOp (result,ic,FALSE);
6028 /* if bitfield then unpack the bits */
6029 if (IS_BITVAR(retype))
6030 genUnpackBits (result,rname,POINTER);
6032 /* we have can just get the values */
6033 int size = AOP_SIZE(result);
6037 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6039 emitcode("mov","a,@%s",rname);
6040 aopPut(AOP(result),"a",offset);
6042 sprintf(buffer,"@%s",rname);
6043 aopPut(AOP(result),buffer,offset);
6047 emitcode("inc","%s",rname);
6051 /* now some housekeeping stuff */
6053 /* we had to allocate for this iCode */
6054 freeAsmop(NULL,aop,ic,TRUE);
6056 /* we did not allocate which means left
6057 already in a pointer register, then
6058 if size > 0 && this could be used again
6059 we have to point it back to where it
6061 if (AOP_SIZE(result) > 1 &&
6062 !OP_SYMBOL(left)->remat &&
6063 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6065 int size = AOP_SIZE(result) - 1;
6067 emitcode("dec","%s",rname);
6072 freeAsmop(result,NULL,ic,TRUE);
6076 /*-----------------------------------------------------------------*/
6077 /* genPagedPointerGet - emitcode for paged pointer fetch */
6078 /*-----------------------------------------------------------------*/
6079 static void genPagedPointerGet (operand *left,
6086 link *rtype, *retype;
6088 rtype = operandType(result);
6089 retype= getSpec(rtype);
6091 aopOp(left,ic,FALSE);
6093 /* if the value is already in a pointer register
6094 then don't need anything more */
6095 if (!AOP_INPREG(AOP(left))) {
6096 /* otherwise get a free pointer register */
6098 preg = getFreePtr(ic,&aop,FALSE);
6099 emitcode("mov","%s,%s",
6101 aopGet(AOP(left),0,FALSE,TRUE));
6102 rname = preg->name ;
6104 rname = aopGet(AOP(left),0,FALSE,FALSE);
6106 freeAsmop(left,NULL,ic,TRUE);
6107 aopOp (result,ic,FALSE);
6109 /* if bitfield then unpack the bits */
6110 if (IS_BITVAR(retype))
6111 genUnpackBits (result,rname,PPOINTER);
6113 /* we have can just get the values */
6114 int size = AOP_SIZE(result);
6119 emitcode("movx","a,@%s",rname);
6120 aopPut(AOP(result),"a",offset);
6125 emitcode("inc","%s",rname);
6129 /* now some housekeeping stuff */
6131 /* we had to allocate for this iCode */
6132 freeAsmop(NULL,aop,ic,TRUE);
6134 /* we did not allocate which means left
6135 already in a pointer register, then
6136 if size > 0 && this could be used again
6137 we have to point it back to where it
6139 if (AOP_SIZE(result) > 1 &&
6140 !OP_SYMBOL(left)->remat &&
6141 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6143 int size = AOP_SIZE(result) - 1;
6145 emitcode("dec","%s",rname);
6150 freeAsmop(result,NULL,ic,TRUE);
6155 /*-----------------------------------------------------------------*/
6156 /* genFarPointerGet - gget value from far space */
6157 /*-----------------------------------------------------------------*/
6158 static void genFarPointerGet (operand *left,
6159 operand *result, iCode *ic)
6162 link *retype = getSpec(operandType(result));
6164 aopOp(left,ic,FALSE);
6166 /* if the operand is already in dptr
6167 then we do nothing else we move the value to dptr */
6168 if (AOP_TYPE(left) != AOP_STR) {
6169 /* if this is remateriazable */
6170 if (AOP_TYPE(left) == AOP_IMMD)
6171 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6172 else { /* we need to get it byte by byte */
6173 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6174 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6175 if (options.model == MODEL_FLAT24)
6177 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6181 /* so dptr know contains the address */
6182 freeAsmop(left,NULL,ic,TRUE);
6183 aopOp(result,ic,FALSE);
6185 /* if bit then unpack */
6186 if (IS_BITVAR(retype))
6187 genUnpackBits(result,"dptr",FPOINTER);
6189 size = AOP_SIZE(result);
6193 emitcode("movx","a,@dptr");
6194 aopPut(AOP(result),"a",offset++);
6196 emitcode("inc","dptr");
6200 freeAsmop(result,NULL,ic,TRUE);
6203 /*-----------------------------------------------------------------*/
6204 /* emitcodePointerGet - gget value from code space */
6205 /*-----------------------------------------------------------------*/
6206 static void emitcodePointerGet (operand *left,
6207 operand *result, iCode *ic)
6210 link *retype = getSpec(operandType(result));
6212 aopOp(left,ic,FALSE);
6214 /* if the operand is already in dptr
6215 then we do nothing else we move the value to dptr */
6216 if (AOP_TYPE(left) != AOP_STR) {
6217 /* if this is remateriazable */
6218 if (AOP_TYPE(left) == AOP_IMMD)
6219 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6220 else { /* we need to get it byte by byte */
6221 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6222 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6223 if (options.model == MODEL_FLAT24)
6225 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6229 /* so dptr know contains the address */
6230 freeAsmop(left,NULL,ic,TRUE);
6231 aopOp(result,ic,FALSE);
6233 /* if bit then unpack */
6234 if (IS_BITVAR(retype))
6235 genUnpackBits(result,"dptr",CPOINTER);
6237 size = AOP_SIZE(result);
6241 emitcode("clr","a");
6242 emitcode("movc","a,@a+dptr");
6243 aopPut(AOP(result),"a",offset++);
6245 emitcode("inc","dptr");
6249 freeAsmop(result,NULL,ic,TRUE);
6252 /*-----------------------------------------------------------------*/
6253 /* genGenPointerGet - gget value from generic pointer space */
6254 /*-----------------------------------------------------------------*/
6255 static void genGenPointerGet (operand *left,
6256 operand *result, iCode *ic)
6259 link *retype = getSpec(operandType(result));
6261 aopOp(left,ic,FALSE);
6263 /* if the operand is already in dptr
6264 then we do nothing else we move the value to dptr */
6265 if (AOP_TYPE(left) != AOP_STR) {
6266 /* if this is remateriazable */
6267 if (AOP_TYPE(left) == AOP_IMMD) {
6268 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6269 emitcode("mov","b,#%d",pointerCode(retype));
6271 else { /* we need to get it byte by byte */
6272 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6273 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6274 if (options.model == MODEL_FLAT24)
6276 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6277 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
6281 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
6285 /* so dptr know contains the address */
6286 freeAsmop(left,NULL,ic,TRUE);
6287 aopOp(result,ic,FALSE);
6289 /* if bit then unpack */
6290 if (IS_BITVAR(retype))
6291 genUnpackBits(result,"dptr",GPOINTER);
6293 size = AOP_SIZE(result);
6297 emitcode("lcall","__gptrget");
6298 aopPut(AOP(result),"a",offset++);
6300 emitcode("inc","dptr");
6304 freeAsmop(result,NULL,ic,TRUE);
6307 /*-----------------------------------------------------------------*/
6308 /* genPointerGet - generate code for pointer get */
6309 /*-----------------------------------------------------------------*/
6310 static void genPointerGet (iCode *ic)
6312 operand *left, *result ;
6317 result = IC_RESULT(ic) ;
6319 /* depending on the type of pointer we need to
6320 move it to the correct pointer register */
6321 type = operandType(left);
6322 etype = getSpec(type);
6323 /* if left is of type of pointer then it is simple */
6324 if (IS_PTR(type) && !IS_FUNC(type->next))
6325 p_type = DCL_TYPE(type);
6327 /* we have to go by the storage class */
6328 p_type = PTR_TYPE(SPEC_OCLS(etype));
6330 /* if (SPEC_OCLS(etype)->codesp ) { */
6331 /* p_type = CPOINTER ; */
6334 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6335 /* p_type = FPOINTER ; */
6337 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6338 /* p_type = PPOINTER; */
6340 /* if (SPEC_OCLS(etype) == idata ) */
6341 /* p_type = IPOINTER; */
6343 /* p_type = POINTER ; */
6346 /* now that we have the pointer type we assign
6347 the pointer values */
6352 genNearPointerGet (left,result,ic);
6356 genPagedPointerGet(left,result,ic);
6360 genFarPointerGet (left,result,ic);
6364 emitcodePointerGet (left,result,ic);
6368 genGenPointerGet (left,result,ic);
6374 /*-----------------------------------------------------------------*/
6375 /* genPackBits - generates code for packed bit storage */
6376 /*-----------------------------------------------------------------*/
6377 static void genPackBits (link *etype ,
6379 char *rname, int p_type)
6387 blen = SPEC_BLEN(etype);
6388 bstr = SPEC_BSTR(etype);
6390 l = aopGet(AOP(right),offset++,FALSE,FALSE);
6393 /* if the bit lenth is less than or */
6394 /* it exactly fits a byte then */
6395 if (SPEC_BLEN(etype) <= 8 ) {
6396 shCount = SPEC_BSTR(etype) ;
6398 /* shift left acc */
6401 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
6406 emitcode ("mov","b,a");
6407 emitcode("mov","a,@%s",rname);
6411 emitcode ("mov","b,a");
6412 emitcode("movx","a,@dptr");
6416 emitcode ("push","b");
6417 emitcode ("push","acc");
6418 emitcode ("lcall","__gptrget");
6419 emitcode ("pop","b");
6423 emitcode ("anl","a,#0x%02x",(unsigned char)
6424 ((unsigned char)(0xFF << (blen+bstr)) |
6425 (unsigned char)(0xFF >> (8-bstr)) ) );
6426 emitcode ("orl","a,b");
6427 if (p_type == GPOINTER)
6428 emitcode("pop","b");
6434 emitcode("mov","@%s,a",rname);
6438 emitcode("movx","@dptr,a");
6442 emitcode("lcall","__gptrput");
6447 if ( SPEC_BLEN(etype) <= 8 )
6450 emitcode("inc","%s",rname);
6451 rLen = SPEC_BLEN(etype) ;
6453 /* now generate for lengths greater than one byte */
6456 l = aopGet(AOP(right),offset++,FALSE,TRUE);
6466 emitcode("mov","@%s,a",rname);
6468 emitcode("mov","@%s,%s",rname,l);
6473 emitcode("movx","@dptr,a");
6478 emitcode("lcall","__gptrput");
6481 emitcode ("inc","%s",rname);
6486 /* last last was not complete */
6488 /* save the byte & read byte */
6491 emitcode ("mov","b,a");
6492 emitcode("mov","a,@%s",rname);
6496 emitcode ("mov","b,a");
6497 emitcode("movx","a,@dptr");
6501 emitcode ("push","b");
6502 emitcode ("push","acc");
6503 emitcode ("lcall","__gptrget");
6504 emitcode ("pop","b");
6508 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
6509 emitcode ("orl","a,b");
6512 if (p_type == GPOINTER)
6513 emitcode("pop","b");
6518 emitcode("mov","@%s,a",rname);
6522 emitcode("movx","@dptr,a");
6526 emitcode("lcall","__gptrput");
6530 /*-----------------------------------------------------------------*/
6531 /* genDataPointerSet - remat pointer to data space */
6532 /*-----------------------------------------------------------------*/
6533 static void genDataPointerSet(operand *right,
6537 int size, offset = 0 ;
6538 char *l, buffer[256];
6540 aopOp(right,ic,FALSE);
6542 l = aopGet(AOP(result),0,FALSE,TRUE);
6543 size = AOP_SIZE(right);
6546 sprintf(buffer,"(%s + %d)",l+1,offset);
6548 sprintf(buffer,"%s",l+1);
6549 emitcode("mov","%s,%s",buffer,
6550 aopGet(AOP(right),offset++,FALSE,FALSE));
6553 freeAsmop(right,NULL,ic,TRUE);
6554 freeAsmop(result,NULL,ic,TRUE);
6557 /*-----------------------------------------------------------------*/
6558 /* genNearPointerSet - emitcode for near pointer put */
6559 /*-----------------------------------------------------------------*/
6560 static void genNearPointerSet (operand *right,
6568 link *ptype = operandType(result);
6570 retype= getSpec(operandType(right));
6572 aopOp(result,ic,FALSE);
6574 /* if the result is rematerializable &
6575 in data space & not a bit variable */
6576 if (AOP_TYPE(result) == AOP_IMMD &&
6577 DCL_TYPE(ptype) == POINTER &&
6578 !IS_BITVAR(retype)) {
6579 genDataPointerSet (right,result,ic);
6583 /* if the value is already in a pointer register
6584 then don't need anything more */
6585 if (!AOP_INPREG(AOP(result))) {
6586 /* otherwise get a free pointer register */
6588 preg = getFreePtr(ic,&aop,FALSE);
6589 emitcode("mov","%s,%s",
6591 aopGet(AOP(result),0,FALSE,TRUE));
6592 rname = preg->name ;
6594 rname = aopGet(AOP(result),0,FALSE,FALSE);
6596 freeAsmop(result,NULL,ic,TRUE);
6597 aopOp (right,ic,FALSE);
6599 /* if bitfield then unpack the bits */
6600 if (IS_BITVAR(retype))
6601 genPackBits (retype,right,rname,POINTER);
6603 /* we have can just get the values */
6604 int size = AOP_SIZE(right);
6608 l = aopGet(AOP(right),offset,FALSE,TRUE);
6611 emitcode("mov","@%s,a",rname);
6613 emitcode("mov","@%s,%s",rname,l);
6615 emitcode("inc","%s",rname);
6620 /* now some housekeeping stuff */
6622 /* we had to allocate for this iCode */
6623 freeAsmop(NULL,aop,ic,TRUE);
6625 /* we did not allocate which means left
6626 already in a pointer register, then
6627 if size > 0 && this could be used again
6628 we have to point it back to where it
6630 if (AOP_SIZE(right) > 1 &&
6631 !OP_SYMBOL(result)->remat &&
6632 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6634 int size = AOP_SIZE(right) - 1;
6636 emitcode("dec","%s",rname);
6641 freeAsmop(right,NULL,ic,TRUE);
6646 /*-----------------------------------------------------------------*/
6647 /* genPagedPointerSet - emitcode for Paged pointer put */
6648 /*-----------------------------------------------------------------*/
6649 static void genPagedPointerSet (operand *right,
6658 retype= getSpec(operandType(right));
6660 aopOp(result,ic,FALSE);
6662 /* if the value is already in a pointer register
6663 then don't need anything more */
6664 if (!AOP_INPREG(AOP(result))) {
6665 /* otherwise get a free pointer register */
6667 preg = getFreePtr(ic,&aop,FALSE);
6668 emitcode("mov","%s,%s",
6670 aopGet(AOP(result),0,FALSE,TRUE));
6671 rname = preg->name ;
6673 rname = aopGet(AOP(result),0,FALSE,FALSE);
6675 freeAsmop(result,NULL,ic,TRUE);
6676 aopOp (right,ic,FALSE);
6678 /* if bitfield then unpack the bits */
6679 if (IS_BITVAR(retype))
6680 genPackBits (retype,right,rname,PPOINTER);
6682 /* we have can just get the values */
6683 int size = AOP_SIZE(right);
6687 l = aopGet(AOP(right),offset,FALSE,TRUE);
6690 emitcode("movx","@%s,a",rname);
6693 emitcode("inc","%s",rname);
6699 /* now some housekeeping stuff */
6701 /* we had to allocate for this iCode */
6702 freeAsmop(NULL,aop,ic,TRUE);
6704 /* we did not allocate which means left
6705 already in a pointer register, then
6706 if size > 0 && this could be used again
6707 we have to point it back to where it
6709 if (AOP_SIZE(right) > 1 &&
6710 !OP_SYMBOL(result)->remat &&
6711 ( OP_SYMBOL(result)->liveTo > ic->seq ||
6713 int size = AOP_SIZE(right) - 1;
6715 emitcode("dec","%s",rname);
6720 freeAsmop(right,NULL,ic,TRUE);
6725 /*-----------------------------------------------------------------*/
6726 /* genFarPointerSet - set value from far space */
6727 /*-----------------------------------------------------------------*/
6728 static void genFarPointerSet (operand *right,
6729 operand *result, iCode *ic)
6732 link *retype = getSpec(operandType(right));
6734 aopOp(result,ic,FALSE);
6736 /* if the operand is already in dptr
6737 then we do nothing else we move the value to dptr */
6738 if (AOP_TYPE(result) != AOP_STR) {
6739 /* if this is remateriazable */
6740 if (AOP_TYPE(result) == AOP_IMMD)
6741 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6742 else { /* we need to get it byte by byte */
6743 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6744 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6745 if (options.model == MODEL_FLAT24)
6747 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6751 /* so dptr know contains the address */
6752 freeAsmop(result,NULL,ic,TRUE);
6753 aopOp(right,ic,FALSE);
6755 /* if bit then unpack */
6756 if (IS_BITVAR(retype))
6757 genPackBits(retype,right,"dptr",FPOINTER);
6759 size = AOP_SIZE(right);
6763 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6765 emitcode("movx","@dptr,a");
6767 emitcode("inc","dptr");
6771 freeAsmop(right,NULL,ic,TRUE);
6774 /*-----------------------------------------------------------------*/
6775 /* genGenPointerSet - set value from generic pointer space */
6776 /*-----------------------------------------------------------------*/
6777 static void genGenPointerSet (operand *right,
6778 operand *result, iCode *ic)
6781 link *retype = getSpec(operandType(right));
6783 aopOp(result,ic,FALSE);
6785 /* if the operand is already in dptr
6786 then we do nothing else we move the value to dptr */
6787 if (AOP_TYPE(result) != AOP_STR) {
6788 /* if this is remateriazable */
6789 if (AOP_TYPE(result) == AOP_IMMD) {
6790 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
6791 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
6793 else { /* we need to get it byte by byte */
6794 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
6795 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
6796 if (options.model == MODEL_FLAT24)
6798 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
6799 emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
6803 emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
6807 /* so dptr know contains the address */
6808 freeAsmop(result,NULL,ic,TRUE);
6809 aopOp(right,ic,FALSE);
6811 /* if bit then unpack */
6812 if (IS_BITVAR(retype))
6813 genPackBits(retype,right,"dptr",GPOINTER);
6815 size = AOP_SIZE(right);
6819 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
6821 emitcode("lcall","__gptrput");
6823 emitcode("inc","dptr");
6827 freeAsmop(right,NULL,ic,TRUE);
6830 /*-----------------------------------------------------------------*/
6831 /* genPointerSet - stores the value into a pointer location */
6832 /*-----------------------------------------------------------------*/
6833 static void genPointerSet (iCode *ic)
6835 operand *right, *result ;
6839 right = IC_RIGHT(ic);
6840 result = IC_RESULT(ic) ;
6842 /* depending on the type of pointer we need to
6843 move it to the correct pointer register */
6844 type = operandType(result);
6845 etype = getSpec(type);
6846 /* if left is of type of pointer then it is simple */
6847 if (IS_PTR(type) && !IS_FUNC(type->next)) {
6848 p_type = DCL_TYPE(type);
6851 /* we have to go by the storage class */
6852 p_type = PTR_TYPE(SPEC_OCLS(etype));
6854 /* if (SPEC_OCLS(etype)->codesp ) { */
6855 /* p_type = CPOINTER ; */
6858 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
6859 /* p_type = FPOINTER ; */
6861 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
6862 /* p_type = PPOINTER ; */
6864 /* if (SPEC_OCLS(etype) == idata ) */
6865 /* p_type = IPOINTER ; */
6867 /* p_type = POINTER ; */
6870 /* now that we have the pointer type we assign
6871 the pointer values */
6876 genNearPointerSet (right,result,ic);
6880 genPagedPointerSet (right,result,ic);
6884 genFarPointerSet (right,result,ic);
6888 genGenPointerSet (right,result,ic);
6894 /*-----------------------------------------------------------------*/
6895 /* genIfx - generate code for Ifx statement */
6896 /*-----------------------------------------------------------------*/
6897 static void genIfx (iCode *ic, iCode *popIc)
6899 operand *cond = IC_COND(ic);
6902 aopOp(cond,ic,FALSE);
6904 /* get the value into acc */
6905 if (AOP_TYPE(cond) != AOP_CRY)
6909 /* the result is now in the accumulator */
6910 freeAsmop(cond,NULL,ic,TRUE);
6912 /* if there was something to be popped then do it */
6916 /* if the condition is a bit variable */
6917 if (isbit && IS_ITEMP(cond) &&
6919 genIfxJump(ic,SPIL_LOC(cond)->rname);
6921 if (isbit && !IS_ITEMP(cond))
6922 genIfxJump(ic,OP_SYMBOL(cond)->rname);
6929 /*-----------------------------------------------------------------*/
6930 /* genAddrOf - generates code for address of */
6931 /*-----------------------------------------------------------------*/
6932 static void genAddrOf (iCode *ic)
6934 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
6937 aopOp(IC_RESULT(ic),ic,FALSE);
6939 /* if the operand is on the stack then we
6940 need to get the stack offset of this
6943 /* if it has an offset then we need to compute
6946 emitcode("mov","a,_bp");
6947 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
6948 aopPut(AOP(IC_RESULT(ic)),"a",0);
6950 /* we can just move _bp */
6951 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
6953 /* fill the result with zero */
6954 size = AOP_SIZE(IC_RESULT(ic)) - 1;
6957 if (options.stack10bit && size < (FPTRSIZE - 1))
6960 "*** warning: pointer to stack var truncated.\n");
6967 if (options.stack10bit && offset == 2)
6969 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
6973 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
6980 /* object not on stack then we need the name */
6981 size = AOP_SIZE(IC_RESULT(ic));
6985 char s[SDCC_NAME_MAX];
6987 sprintf(s,"#(%s >> %d)",
6991 sprintf(s,"#%s",sym->rname);
6992 aopPut(AOP(IC_RESULT(ic)),s,offset++);
6996 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7000 /*-----------------------------------------------------------------*/
7001 /* genFarFarAssign - assignment when both are in far space */
7002 /*-----------------------------------------------------------------*/
7003 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7005 int size = AOP_SIZE(right);
7008 /* first push the right side on to the stack */
7010 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7012 emitcode ("push","acc");
7015 freeAsmop(right,NULL,ic,FALSE);
7016 /* now assign DPTR to result */
7017 aopOp(result,ic,FALSE);
7018 size = AOP_SIZE(result);
7020 emitcode ("pop","acc");
7021 aopPut(AOP(result),"a",--offset);
7023 freeAsmop(result,NULL,ic,FALSE);
7027 /*-----------------------------------------------------------------*/
7028 /* genAssign - generate code for assignment */
7029 /*-----------------------------------------------------------------*/
7030 static void genAssign (iCode *ic)
7032 operand *result, *right;
7034 unsigned long lit = 0L;
7036 result = IC_RESULT(ic);
7037 right = IC_RIGHT(ic) ;
7039 /* if they are the same */
7040 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7043 aopOp(right,ic,FALSE);
7045 /* special case both in far space */
7046 if ((AOP_TYPE(right) == AOP_DPTR ||
7047 AOP_TYPE(right) == AOP_DPTR2) &&
7048 IS_TRUE_SYMOP(result) &&
7049 isOperandInFarSpace(result)) {
7051 genFarFarAssign (result,right,ic);
7055 aopOp(result,ic,TRUE);
7057 /* if they are the same registers */
7058 if (sameRegs(AOP(right),AOP(result)))
7061 /* if the result is a bit */
7062 if (AOP_TYPE(result) == AOP_CRY) {
7064 /* if the right size is a literal then
7065 we know what the value is */
7066 if (AOP_TYPE(right) == AOP_LIT) {
7067 if (((int) operandLitValue(right)))
7068 aopPut(AOP(result),one,0);
7070 aopPut(AOP(result),zero,0);
7074 /* the right is also a bit variable */
7075 if (AOP_TYPE(right) == AOP_CRY) {
7076 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7077 aopPut(AOP(result),"c",0);
7083 aopPut(AOP(result),"a",0);
7087 /* bit variables done */
7089 size = AOP_SIZE(result);
7091 if(AOP_TYPE(right) == AOP_LIT)
7092 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7094 (AOP_TYPE(result) != AOP_REG) &&
7095 (AOP_TYPE(right) == AOP_LIT) &&
7096 !IS_FLOAT(operandType(right)) &&
7098 emitcode("clr","a");
7100 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7101 aopPut(AOP(result),"a",size);
7104 aopGet(AOP(right),size,FALSE,FALSE),
7110 aopGet(AOP(right),offset,FALSE,FALSE),
7117 freeAsmop (right,NULL,ic,FALSE);
7118 freeAsmop (result,NULL,ic,TRUE);
7121 /*-----------------------------------------------------------------*/
7122 /* genJumpTab - genrates code for jump table */
7123 /*-----------------------------------------------------------------*/
7124 static void genJumpTab (iCode *ic)
7129 aopOp(IC_JTCOND(ic),ic,FALSE);
7130 /* get the condition into accumulator */
7131 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
7133 /* multiply by three */
7134 emitcode("add","a,acc");
7135 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
7136 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
7138 jtab = newiTempLabel(NULL);
7139 emitcode("mov","dptr,#%05d$",jtab->key+100);
7140 emitcode("jmp","@a+dptr");
7141 emitcode("","%05d$:",jtab->key+100);
7142 /* now generate the jump labels */
7143 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
7144 jtab = setNextItem(IC_JTLABELS(ic)))
7145 emitcode("ljmp","%05d$",jtab->key+100);
7149 /*-----------------------------------------------------------------*/
7150 /* genCast - gen code for casting */
7151 /*-----------------------------------------------------------------*/
7152 static void genCast (iCode *ic)
7154 operand *result = IC_RESULT(ic);
7155 link *ctype = operandType(IC_LEFT(ic));
7156 operand *right = IC_RIGHT(ic);
7159 /* if they are equivalent then do nothing */
7160 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
7163 aopOp(right,ic,FALSE) ;
7164 aopOp(result,ic,FALSE);
7166 /* if the result is a bit */
7167 if (AOP_TYPE(result) == AOP_CRY) {
7168 /* if the right size is a literal then
7169 we know what the value is */
7170 if (AOP_TYPE(right) == AOP_LIT) {
7171 if (((int) operandLitValue(right)))
7172 aopPut(AOP(result),one,0);
7174 aopPut(AOP(result),zero,0);
7179 /* the right is also a bit variable */
7180 if (AOP_TYPE(right) == AOP_CRY) {
7181 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7182 aopPut(AOP(result),"c",0);
7188 aopPut(AOP(result),"a",0);
7192 /* if they are the same size : or less */
7193 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
7195 /* if they are in the same place */
7196 if (sameRegs(AOP(right),AOP(result)))
7199 /* if they in different places then copy */
7200 size = AOP_SIZE(result);
7204 aopGet(AOP(right),offset,FALSE,FALSE),
7212 /* if the result is of type pointer */
7213 if (IS_PTR(ctype)) {
7216 link *type = operandType(right);
7217 link *etype = getSpec(type);
7219 /* pointer to generic pointer */
7220 if (IS_GENPTR(ctype)) {
7224 p_type = DCL_TYPE(type);
7226 /* we have to go by the storage class */
7227 p_type = PTR_TYPE(SPEC_OCLS(etype));
7229 /* if (SPEC_OCLS(etype)->codesp ) */
7230 /* p_type = CPOINTER ; */
7232 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7233 /* p_type = FPOINTER ; */
7235 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7236 /* p_type = PPOINTER; */
7238 /* if (SPEC_OCLS(etype) == idata ) */
7239 /* p_type = IPOINTER ; */
7241 /* p_type = POINTER ; */
7244 /* the first two bytes are known */
7245 size = GPTRSIZE - 1;
7249 aopGet(AOP(right),offset,FALSE,FALSE),
7253 /* the last byte depending on type */
7270 /* this should never happen */
7271 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7272 "got unknown pointer type");
7275 aopPut(AOP(result),l, GPTRSIZE - 1);
7279 /* just copy the pointers */
7280 size = AOP_SIZE(result);
7284 aopGet(AOP(right),offset,FALSE,FALSE),
7291 /* so we now know that the size of destination is greater
7292 than the size of the source */
7293 /* we move to result for the size of source */
7294 size = AOP_SIZE(right);
7298 aopGet(AOP(right),offset,FALSE,FALSE),
7303 /* now depending on the sign of the destination */
7304 size = AOP_SIZE(result) - AOP_SIZE(right);
7305 /* if unsigned or not an integral type */
7306 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
7308 aopPut(AOP(result),zero,offset++);
7310 /* we need to extend the sign :{ */
7311 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
7314 emitcode("rlc","a");
7315 emitcode("subb","a,acc");
7317 aopPut(AOP(result),"a",offset++);
7320 /* we are done hurray !!!! */
7323 freeAsmop(right,NULL,ic,TRUE);
7324 freeAsmop(result,NULL,ic,TRUE);
7328 /*-----------------------------------------------------------------*/
7329 /* genDjnz - generate decrement & jump if not zero instrucion */
7330 /*-----------------------------------------------------------------*/
7331 static int genDjnz (iCode *ic, iCode *ifx)
7337 /* if the if condition has a false label
7338 then we cannot save */
7342 /* if the minus is not of the form
7344 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
7345 !IS_OP_LITERAL(IC_RIGHT(ic)))
7348 if (operandLitValue(IC_RIGHT(ic)) != 1)
7351 /* if the size of this greater than one then no
7353 if (getSize(operandType(IC_RESULT(ic))) > 1)
7356 /* otherwise we can save BIG */
7357 lbl = newiTempLabel(NULL);
7358 lbl1= newiTempLabel(NULL);
7360 aopOp(IC_RESULT(ic),ic,FALSE);
7362 if (IS_AOP_PREG(IC_RESULT(ic))) {
7363 emitcode("dec","%s",
7364 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7365 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
7366 emitcode("jnz","%05d$",lbl->key+100);
7368 emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
7371 emitcode ("sjmp","%05d$",lbl1->key+100);
7372 emitcode ("","%05d$:",lbl->key+100);
7373 emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
7374 emitcode ("","%05d$:",lbl1->key+100);
7376 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7381 /*-----------------------------------------------------------------*/
7382 /* genReceive - generate code for a receive iCode */
7383 /*-----------------------------------------------------------------*/
7384 static void genReceive (iCode *ic)
7386 if (isOperandInFarSpace(IC_RESULT(ic)) &&
7387 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
7388 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
7390 int size = getSize(operandType(IC_RESULT(ic)));
7391 int offset = fReturnSize - size;
7393 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
7394 fReturn[fReturnSize - offset - 1] : "acc"));
7397 aopOp(IC_RESULT(ic),ic,FALSE);
7398 size = AOP_SIZE(IC_RESULT(ic));
7401 emitcode ("pop","acc");
7402 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
7407 aopOp(IC_RESULT(ic),ic,FALSE);
7409 assignResultValue(IC_RESULT(ic));
7412 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7415 /*-----------------------------------------------------------------*/
7416 /* gen51Code - generate code for 8051 based controllers */
7417 /*-----------------------------------------------------------------*/
7418 void gen51Code (iCode *lic)
7423 lineHead = lineCurr = NULL;
7425 /* print the allocation information */
7427 printAllocInfo( currFunc, codeOutFile);
7428 /* if debug information required */
7429 /* if (options.debug && currFunc) { */
7431 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
7433 if (IS_STATIC(currFunc->etype))
7434 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
7436 emitcode("","G$%s$0$0 ==.",currFunc->name);
7439 /* stack pointer name */
7440 if (options.useXstack)
7446 for (ic = lic ; ic ; ic = ic->next ) {
7448 if ( cln != ic->lineno ) {
7449 if ( options.debug ) {
7451 emitcode("","C$%s$%d$%d$%d ==.",
7452 ic->filename,ic->lineno,
7453 ic->level,ic->block);
7456 emitcode(";","%s %d",ic->filename,ic->lineno);
7459 /* if the result is marked as
7460 spilt and rematerializable or code for
7461 this has already been generated then
7463 if (resultRemat(ic) || ic->generated )
7466 /* depending on the operation */
7485 /* IPOP happens only when trying to restore a
7486 spilt live range, if there is an ifx statement
7487 following this pop then the if statement might
7488 be using some of the registers being popped which
7489 would destory the contents of the register so
7490 we need to check for this condition and handle it */
7492 ic->next->op == IFX &&
7493 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
7494 genIfx (ic->next,ic);
7512 genEndFunction (ic);
7532 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
7549 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
7553 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
7560 /* note these two are xlated by algebraic equivalence
7561 during parsing SDCC.y */
7562 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7563 "got '>=' or '<=' shouldn't have come here");
7567 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
7579 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
7583 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
7587 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
7614 case GET_VALUE_AT_ADDRESS:
7619 if (POINTER_SET(ic))
7646 addSet(&_G.sendSet,ic);
7651 /* piCode(ic,stdout); */
7657 /* now we are ready to call the
7658 peep hole optimizer */
7659 if (!options.nopeep)
7660 peepHole (&lineHead);
7662 /* now do the actual printing */
7663 printLine (lineHead,codeOutFile);