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)
7 PIC port - Scott Dattalo scott@dattalo.com (2000)
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
28 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
29 Made everything static
30 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
40 #define __FUNCTION__ __FILE__
43 #ifdef HAVE_SYS_ISA_DEFS_H
44 #include <sys/isa_defs.h>
49 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
50 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
51 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
57 #include "SDCCpeeph.h"
61 //char *aopLiteral (value *val, int offset);
62 char *pic14aopLiteral (value *val, int offset);
64 /* this is the down and dirty file with all kinds of
65 kludgy & hacky stuff. This is what it is all about
66 CODE GENERATION for a specific MCU . some of the
67 routines may be reusable, will have to see */
69 static char *zero = "#0x00";
70 static char *one = "#0x01";
71 static char *spname = "sp";
73 char *fReturnpic14[] = {"fsr","dph","b","a" };
74 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
75 static unsigned fReturnSize = 4; /* shared with ralloc.c */
76 static char **fReturn = fReturnpic14;
78 static char *accUse[] = {"a","b"};
80 //static short rbank = -1;
92 extern int pic14_ptrRegReq ;
93 extern int pic14_nRegs;
94 extern FILE *codeOutFile;
95 static void saverbank (int, iCode *,bool);
96 #define RESULTONSTACK(x) \
97 (IC_RESULT(x) && IC_RESULT(x)->aop && \
98 IC_RESULT(x)->aop->type == AOP_STK )
100 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode(";XXX mov","a,%s %s,%d",x,__FILE__,__LINE__);
101 #define CLRC emitcode(";XXX clr","c %s,%d",__FILE__,__LINE__);
103 #define BIT_NUMBER(x) (x & 7)
104 #define BIT_REGISTER(x) (x>>3)
106 static lineNode *lineHead = NULL;
107 static lineNode *lineCurr = NULL;
109 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
110 0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
112 0x07, 0x03, 0x01, 0x00};
120 #define FUNCTION_LABEL_INC 20
121 static int labelOffset=0;
122 static int debug_verbose=0;
125 /*-----------------------------------------------------------------*/
126 /* Macros for emitting instructions */
127 /*-----------------------------------------------------------------*/
128 #define emitSKPC emitcode("btfss","status,c")
129 #define emitSKPNC emitcode("btfsc","status,c")
130 #define emitSKPZ emitcode("btfss","status,z")
131 #define emitSKPNZ emitcode("btfsc","status,z")
133 /*-----------------------------------------------------------------*/
134 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
135 /* exponent of 2 is returned, otherwise -1 is */
137 /* note that this is similar to the function `powof2' in SDCCsymt */
141 /*-----------------------------------------------------------------*/
142 static int my_powof2 (unsigned long num)
145 if( (num & (num-1)) == 0) {
159 /*-----------------------------------------------------------------*/
160 /* emitcode - writes the code into a file : for now it is simple */
161 /*-----------------------------------------------------------------*/
162 static void emitcode (char *inst,char *fmt, ...)
165 char lb[MAX_INLINEASM];
172 sprintf(lb,"%s\t",inst);
174 sprintf(lb,"%s",inst);
175 vsprintf(lb+(strlen(lb)),fmt,ap);
179 while (isspace(*lbp)) lbp++;
182 lineCurr = (lineCurr ?
183 connectLine(lineCurr,newLineNode(lb)) :
184 (lineHead = newLineNode(lb)));
185 lineCurr->isInline = _G.inLine;
186 lineCurr->isDebug = _G.debugLine;
190 static void DEBUGemitcode (char *inst,char *fmt, ...)
193 char lb[MAX_INLINEASM];
203 sprintf(lb,"%s\t",inst);
205 sprintf(lb,"%s",inst);
206 vsprintf(lb+(strlen(lb)),fmt,ap);
210 while (isspace(*lbp)) lbp++;
213 lineCurr = (lineCurr ?
214 connectLine(lineCurr,newLineNode(lb)) :
215 (lineHead = newLineNode(lb)));
216 lineCurr->isInline = _G.inLine;
217 lineCurr->isDebug = _G.debugLine;
222 /*-----------------------------------------------------------------*/
223 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
224 /*-----------------------------------------------------------------*/
225 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
227 bool r0iu = FALSE , r1iu = FALSE;
228 bool r0ou = FALSE , r1ou = FALSE;
230 /* the logic: if r0 & r1 used in the instruction
231 then we are in trouble otherwise */
233 /* first check if r0 & r1 are used by this
234 instruction, in which case we are in trouble */
235 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
236 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
241 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
242 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
244 /* if no usage of r0 then return it */
245 if (!r0iu && !r0ou) {
246 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
247 (*aopp)->type = AOP_R0;
249 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
252 /* if no usage of r1 then return it */
253 if (!r1iu && !r1ou) {
254 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
255 (*aopp)->type = AOP_R1;
257 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
260 /* now we know they both have usage */
261 /* if r0 not used in this instruction */
263 /* push it if not already pushed */
265 emitcode ("push","%s",
266 pic14_regWithIdx(R0_IDX)->dname);
270 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
271 (*aopp)->type = AOP_R0;
273 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
276 /* if r1 not used then */
279 /* push it if not already pushed */
281 emitcode ("push","%s",
282 pic14_regWithIdx(R1_IDX)->dname);
286 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
287 (*aopp)->type = AOP_R1;
288 return pic14_regWithIdx(R1_IDX);
292 /* I said end of world but not quite end of world yet */
293 /* if this is a result then we can push it on the stack*/
295 (*aopp)->type = AOP_STK;
300 /* other wise this is true end of the world */
301 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
302 "getFreePtr should never reach here");
306 /*-----------------------------------------------------------------*/
307 /* newAsmop - creates a new asmOp */
308 /*-----------------------------------------------------------------*/
309 static asmop *newAsmop (short type)
313 aop = Safe_calloc(1,sizeof(asmop));
318 static void genSetDPTR(int n)
322 emitcode(";", "Select standard DPTR");
323 emitcode("mov", "dps, #0x00");
327 emitcode(";", "Select alternate DPTR");
328 emitcode("mov", "dps, #0x01");
332 /*-----------------------------------------------------------------*/
333 /* pointerCode - returns the code for a pointer type */
334 /*-----------------------------------------------------------------*/
335 static int pointerCode (sym_link *etype)
338 return PTR_TYPE(SPEC_OCLS(etype));
342 /*-----------------------------------------------------------------*/
343 /* aopForSym - for a true symbol */
344 /*-----------------------------------------------------------------*/
345 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
348 memmap *space= SPEC_OCLS(sym->etype);
350 DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
351 /* if already has one */
355 /* assign depending on the storage class */
356 /* if it is on the stack or indirectly addressable */
357 /* space we need to assign either r0 or r1 to it */
358 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
359 sym->aop = aop = newAsmop(0);
360 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
361 aop->size = getSize(sym->type);
363 /* now assign the address of the variable to
364 the pointer register */
365 if (aop->type != AOP_STK) {
369 emitcode("push","acc");
371 emitcode("mov","a,_bp");
372 emitcode("add","a,#0x%02x",
374 ((char)(sym->stack - _G.nRegsSaved )) :
375 ((char)sym->stack)) & 0xff);
376 emitcode("mov","%s,a",
377 aop->aopu.aop_ptr->name);
380 emitcode("pop","acc");
382 emitcode("mov","%s,#%s",
383 aop->aopu.aop_ptr->name,
385 aop->paged = space->paged;
387 aop->aopu.aop_stk = sym->stack;
391 if (sym->onStack && options.stack10bit)
393 /* It's on the 10 bit stack, which is located in
397 //DEBUGemitcode(";","%d",__LINE__);
400 emitcode("push","acc");
402 emitcode("mov","a,_bp");
403 emitcode("add","a,#0x%02x",
405 ((char)(sym->stack - _G.nRegsSaved )) :
406 ((char)sym->stack)) & 0xff);
409 emitcode ("mov","dpx1,#0x40");
410 emitcode ("mov","dph1,#0x00");
411 emitcode ("mov","dpl1, a");
415 emitcode("pop","acc");
417 sym->aop = aop = newAsmop(AOP_DPTR2);
418 aop->size = getSize(sym->type);
422 //DEBUGemitcode(";","%d",__LINE__);
423 /* if in bit space */
424 if (IN_BITSPACE(space)) {
425 sym->aop = aop = newAsmop (AOP_CRY);
426 aop->aopu.aop_dir = sym->rname ;
427 aop->size = getSize(sym->type);
428 DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
431 /* if it is in direct space */
432 if (IN_DIRSPACE(space)) {
433 sym->aop = aop = newAsmop (AOP_DIR);
434 aop->aopu.aop_dir = sym->rname ;
435 aop->size = getSize(sym->type);
436 DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
440 /* special case for a function */
441 if (IS_FUNC(sym->type)) {
442 sym->aop = aop = newAsmop(AOP_IMMD);
443 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
444 strcpy(aop->aopu.aop_immd,sym->rname);
445 aop->size = FPTRSIZE;
450 /* only remaining is far space */
451 /* in which case DPTR gets the address */
452 sym->aop = aop = newAsmop(AOP_DPTR);
453 emitcode ("mov","dptr,#%s", sym->rname);
454 aop->size = getSize(sym->type);
456 DEBUGemitcode(";","%d size = %d",__LINE__,aop->size);
457 /* if it is in code space */
458 if (IN_CODESPACE(space))
464 /*-----------------------------------------------------------------*/
465 /* aopForRemat - rematerialzes an object */
466 /*-----------------------------------------------------------------*/
467 static asmop *aopForRemat (symbol *sym)
469 iCode *ic = sym->rematiCode;
470 asmop *aop = newAsmop(AOP_IMMD);
472 DEBUGemitcode(";","%s %d",__FUNCTION__,__LINE__);
475 val += operandLitValue(IC_RIGHT(ic));
476 else if (ic->op == '-')
477 val -= operandLitValue(IC_RIGHT(ic));
481 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
485 sprintf(buffer,"(%s %c 0x%04x)",
486 OP_SYMBOL(IC_LEFT(ic))->rname,
487 val >= 0 ? '+' : '-',
490 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
492 //DEBUGemitcode(";","%s",buffer);
493 aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
494 strcpy(aop->aopu.aop_immd,buffer);
498 /*-----------------------------------------------------------------*/
499 /* regsInCommon - two operands have some registers in common */
500 /*-----------------------------------------------------------------*/
501 static bool regsInCommon (operand *op1, operand *op2)
506 /* if they have registers in common */
507 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
510 sym1 = OP_SYMBOL(op1);
511 sym2 = OP_SYMBOL(op2);
513 if (sym1->nRegs == 0 || sym2->nRegs == 0)
516 for (i = 0 ; i < sym1->nRegs ; i++) {
521 for (j = 0 ; j < sym2->nRegs ;j++ ) {
525 if (sym2->regs[j] == sym1->regs[i])
533 /*-----------------------------------------------------------------*/
534 /* operandsEqu - equivalent */
535 /*-----------------------------------------------------------------*/
536 static bool operandsEqu ( operand *op1, operand *op2)
540 /* if they not symbols */
541 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
544 sym1 = OP_SYMBOL(op1);
545 sym2 = OP_SYMBOL(op2);
547 /* if both are itemps & one is spilt
548 and the other is not then false */
549 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
550 sym1->isspilt != sym2->isspilt )
553 /* if they are the same */
557 if (strcmp(sym1->rname,sym2->rname) == 0)
561 /* if left is a tmp & right is not */
565 (sym1->usl.spillLoc == sym2))
572 (sym2->usl.spillLoc == sym1))
578 /*-----------------------------------------------------------------*/
579 /* sameRegs - two asmops have the same registers */
580 /*-----------------------------------------------------------------*/
581 static bool sameRegs (asmop *aop1, asmop *aop2 )
588 if (aop1->type != AOP_REG ||
589 aop2->type != AOP_REG )
592 if (aop1->size != aop2->size )
595 for (i = 0 ; i < aop1->size ; i++ )
596 if (aop1->aopu.aop_reg[i] !=
597 aop2->aopu.aop_reg[i] )
603 /*-----------------------------------------------------------------*/
604 /* aopOp - allocates an asmop for an operand : */
605 /*-----------------------------------------------------------------*/
606 static void aopOp (operand *op, iCode *ic, bool result)
615 DEBUGemitcode(";","%d",__LINE__);
616 /* if this a literal */
617 if (IS_OP_LITERAL(op)) {
618 DEBUGemitcode(";","%d",__LINE__);
619 op->aop = aop = newAsmop(AOP_LIT);
620 aop->aopu.aop_lit = op->operand.valOperand;
621 aop->size = getSize(operandType(op));
625 /* if already has a asmop then continue */
629 /* if the underlying symbol has a aop */
630 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
631 DEBUGemitcode(";","%d",__LINE__);
632 op->aop = OP_SYMBOL(op)->aop;
636 /* if this is a true symbol */
637 if (IS_TRUE_SYMOP(op)) {
638 DEBUGemitcode(";","%d",__LINE__);
639 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
643 /* this is a temporary : this has
649 e) can be a return use only */
654 /* if the type is a conditional */
655 if (sym->regType == REG_CND) {
656 DEBUGemitcode(";","%d",__LINE__);
657 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
662 /* if it is spilt then two situations
664 b) has a spill location */
665 if (sym->isspilt || sym->nRegs == 0) {
667 DEBUGemitcode(";","%d",__LINE__);
668 /* rematerialize it NOW */
670 sym->aop = op->aop = aop =
672 aop->size = getSize(sym->type);
673 DEBUGemitcode(";","%d",__LINE__);
679 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
680 aop->size = getSize(sym->type);
681 for ( i = 0 ; i < 2 ; i++ )
682 aop->aopu.aop_str[i] = accUse[i];
683 DEBUGemitcode(";","%d",__LINE__);
689 aop = op->aop = sym->aop = newAsmop(AOP_STR);
690 aop->size = getSize(sym->type);
691 for ( i = 0 ; i < fReturnSize ; i++ )
692 aop->aopu.aop_str[i] = fReturn[i];
693 DEBUGemitcode(";","%d",__LINE__);
697 /* else spill location */
698 DEBUGemitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
699 sym->aop = op->aop = aop =
700 aopForSym(ic,sym->usl.spillLoc,result);
701 aop->size = getSize(sym->type);
705 /* must be in a register */
706 sym->aop = op->aop = aop = newAsmop(AOP_REG);
707 aop->size = sym->nRegs;
708 for ( i = 0 ; i < sym->nRegs ;i++)
709 aop->aopu.aop_reg[i] = sym->regs[i];
712 /*-----------------------------------------------------------------*/
713 /* freeAsmop - free up the asmop given to an operand */
714 /*----------------------------------------------------------------*/
715 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
732 /* depending on the asmop type only three cases need work AOP_RO
733 , AOP_R1 && AOP_STK */
738 emitcode ("pop","ar0");
742 bitVectUnSetBit(ic->rUsed,R0_IDX);
748 emitcode ("pop","ar1");
752 bitVectUnSetBit(ic->rUsed,R1_IDX);
758 int stk = aop->aopu.aop_stk + aop->size;
759 bitVectUnSetBit(ic->rUsed,R0_IDX);
760 bitVectUnSetBit(ic->rUsed,R1_IDX);
762 getFreePtr(ic,&aop,FALSE);
764 if (options.stack10bit)
766 /* I'm not sure what to do here yet... */
769 "*** Warning: probably generating bad code for "
770 "10 bit stack mode.\n");
774 emitcode ("mov","a,_bp");
775 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
776 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
778 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
782 emitcode("pop","acc");
783 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
785 emitcode("dec","%s",aop->aopu.aop_ptr->name);
788 freeAsmop(op,NULL,ic,TRUE);
790 emitcode("pop","ar0");
795 emitcode("pop","ar1");
802 /* all other cases just dealloc */
806 OP_SYMBOL(op)->aop = NULL;
807 /* if the symbol has a spill */
809 SPIL_LOC(op)->aop = NULL;
814 /*-----------------------------------------------------------------*/
815 /* aopGet - for fetching value of the aop */
816 /*-----------------------------------------------------------------*/
817 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
822 //DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
823 /* offset is greater than
825 if (offset > (aop->size - 1) &&
826 aop->type != AOP_LIT)
829 /* depending on type */
834 DEBUGemitcode(";","%d",__LINE__);
835 /* if we need to increment it */
836 while (offset > aop->coff) {
837 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
841 while (offset < aop->coff) {
842 emitcode("dec","%s",aop->aopu.aop_ptr->name);
848 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
849 return (dname ? "acc" : "a");
851 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
852 rs = Safe_calloc(1,strlen(s)+1);
858 DEBUGemitcode(";","%d",__LINE__);
859 if (aop->type == AOP_DPTR2)
864 while (offset > aop->coff) {
865 emitcode ("inc","dptr");
869 while (offset < aop->coff) {
870 emitcode("lcall","__decdptr");
877 emitcode("movc","a,@a+dptr");
880 emitcode("movx","a,@dptr");
883 if (aop->type == AOP_DPTR2)
888 return (dname ? "acc" : "a");
892 DEBUGemitcode(";","%d",__LINE__);
894 sprintf (s,"%s",aop->aopu.aop_immd);
897 sprintf(s,"(%s >> %d)",
903 rs = Safe_calloc(1,strlen(s)+1);
909 sprintf(s,"(%s + %d)",
913 sprintf(s,"%s",aop->aopu.aop_dir);
914 rs = Safe_calloc(1,strlen(s)+1);
919 DEBUGemitcode(";","%d",__LINE__);
921 return aop->aopu.aop_reg[offset]->dname;
923 return aop->aopu.aop_reg[offset]->name;
926 emitcode(";","%d",__LINE__);
927 //emitcode("clr","a");
928 //emitcode("mov","c,%s",aop->aopu.aop_dir);
929 //emitcode("rlc","a") ;
930 //return (dname ? "acc" : "a");
931 return aop->aopu.aop_dir;
934 DEBUGemitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
935 //if (!offset && dname)
937 //return aop->aopu.aop_str[offset];
938 return "AOP_accumulator_bug";
941 DEBUGemitcode(";","%d",__LINE__);
942 return pic14aopLiteral (aop->aopu.aop_lit,offset);
945 DEBUGemitcode(";","%d",__LINE__);
947 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
951 return aop->aopu.aop_str[offset];
955 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
956 "aopget got unsupported aop->type");
959 /*-----------------------------------------------------------------*/
960 /* aopPut - puts a string for a aop */
961 /*-----------------------------------------------------------------*/
962 static void aopPut (asmop *aop, char *s, int offset)
967 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
969 if (aop->size && offset > ( aop->size - 1)) {
970 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
971 "aopPut got offset > aop->size");
975 /* will assign value to value */
976 /* depending on where it is ofcourse */
980 sprintf(d,"(%s + %d)",
981 aop->aopu.aop_dir,offset);
983 sprintf(d,"%s",aop->aopu.aop_dir);
986 DEBUGemitcode(";","%d",__LINE__);
988 emitcode("movf","%s,w",s);
989 emitcode("movwf","%s",d);
994 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
995 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
998 strcmp(s,"r0") == 0 ||
999 strcmp(s,"r1") == 0 ||
1000 strcmp(s,"r2") == 0 ||
1001 strcmp(s,"r3") == 0 ||
1002 strcmp(s,"r4") == 0 ||
1003 strcmp(s,"r5") == 0 ||
1004 strcmp(s,"r6") == 0 ||
1005 strcmp(s,"r7") == 0 )
1006 emitcode("mov","%s,%s ; %d",
1007 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1012 emitcode("movf","%s,w ; %d",s,__LINE__);
1014 emitcode("movwf","%s",
1015 aop->aopu.aop_reg[offset]->name);
1023 if (aop->type == AOP_DPTR2)
1029 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1030 "aopPut writting to code space");
1034 while (offset > aop->coff) {
1036 emitcode ("inc","dptr");
1039 while (offset < aop->coff) {
1041 emitcode("lcall","__decdptr");
1046 /* if not in accumulater */
1049 emitcode ("movx","@dptr,a");
1051 if (aop->type == AOP_DPTR2)
1059 while (offset > aop->coff) {
1061 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1063 while (offset < aop->coff) {
1065 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1071 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1076 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1078 if (strcmp(s,"r0") == 0 ||
1079 strcmp(s,"r1") == 0 ||
1080 strcmp(s,"r2") == 0 ||
1081 strcmp(s,"r3") == 0 ||
1082 strcmp(s,"r4") == 0 ||
1083 strcmp(s,"r5") == 0 ||
1084 strcmp(s,"r6") == 0 ||
1085 strcmp(s,"r7") == 0 ) {
1087 sprintf(buffer,"a%s",s);
1088 emitcode("mov","@%s,%s",
1089 aop->aopu.aop_ptr->name,buffer);
1091 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1096 if (strcmp(s,"a") == 0)
1097 emitcode("push","acc");
1099 emitcode("push","%s",s);
1104 /* if bit variable */
1105 if (!aop->aopu.aop_dir) {
1106 emitcode("clr","a");
1107 emitcode("rlc","a");
1110 emitcode("clr","%s",aop->aopu.aop_dir);
1113 emitcode("setb","%s",aop->aopu.aop_dir);
1116 emitcode("mov","%s,c",aop->aopu.aop_dir);
1118 lbl = newiTempLabel(NULL);
1120 if (strcmp(s,"a")) {
1123 emitcode("clr","c");
1124 emitcode("jz","%05d_DS_",lbl->key+100);
1125 emitcode("cpl","c");
1126 emitcode("","%05d_DS_:",lbl->key+100);
1127 emitcode("mov","%s,c",aop->aopu.aop_dir);
1134 if (strcmp(aop->aopu.aop_str[offset],s))
1135 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1140 if (!offset && (strcmp(s,"acc") == 0))
1143 if (strcmp(aop->aopu.aop_str[offset],s))
1144 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1148 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1149 "aopPut got unsupported aop->type");
1155 /*-----------------------------------------------------------------*/
1156 /* reAdjustPreg - points a register back to where it should */
1157 /*-----------------------------------------------------------------*/
1158 static void reAdjustPreg (asmop *aop)
1162 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1164 if ((size = aop->size) <= 1)
1167 switch (aop->type) {
1171 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1175 if (aop->type == AOP_DPTR2)
1181 emitcode("lcall","__decdptr");
1184 if (aop->type == AOP_DPTR2)
1194 #define AOP(op) op->aop
1195 #define AOP_TYPE(op) AOP(op)->type
1196 #define AOP_SIZE(op) AOP(op)->size
1197 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1198 AOP_TYPE(x) == AOP_R0))
1200 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1201 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1204 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1205 (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1206 x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1208 /*-----------------------------------------------------------------*/
1209 /* genNotFloat - generates not for float operations */
1210 /*-----------------------------------------------------------------*/
1211 static void genNotFloat (operand *op, operand *res)
1217 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1218 /* we will put 127 in the first byte of
1220 aopPut(AOP(res),"#127",0);
1221 size = AOP_SIZE(op) - 1;
1224 l = aopGet(op->aop,offset++,FALSE,FALSE);
1228 emitcode("orl","a,%s",
1230 offset++,FALSE,FALSE));
1232 tlbl = newiTempLabel(NULL);
1234 tlbl = newiTempLabel(NULL);
1235 aopPut(res->aop,one,1);
1236 emitcode("jz","%05d_DS_",(tlbl->key+100));
1237 aopPut(res->aop,zero,1);
1238 emitcode("","%05d_DS_:",(tlbl->key+100));
1240 size = res->aop->size - 2;
1242 /* put zeros in the rest */
1244 aopPut(res->aop,zero,offset++);
1248 /*-----------------------------------------------------------------*/
1249 /* opIsGptr: returns non-zero if the passed operand is */
1250 /* a generic pointer type. */
1251 /*-----------------------------------------------------------------*/
1252 static int opIsGptr(operand *op)
1254 sym_link *type = operandType(op);
1256 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1257 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1265 /*-----------------------------------------------------------------*/
1266 /* getDataSize - get the operand data size */
1267 /*-----------------------------------------------------------------*/
1268 static int getDataSize(operand *op)
1270 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1273 return AOP_SIZE(op);
1275 // tsd- in the pic port, the genptr size is 1, so this code here
1276 // fails. ( in the 8051 port, the size was 4).
1279 size = AOP_SIZE(op);
1280 if (size == GPTRSIZE)
1282 sym_link *type = operandType(op);
1283 if (IS_GENPTR(type))
1285 /* generic pointer; arithmetic operations
1286 * should ignore the high byte (pointer type).
1289 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1296 /*-----------------------------------------------------------------*/
1297 /* outAcc - output Acc */
1298 /*-----------------------------------------------------------------*/
1299 static void outAcc(operand *result)
1302 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1303 size = getDataSize(result);
1305 aopPut(AOP(result),"a",0);
1308 /* unsigned or positive */
1310 aopPut(AOP(result),zero,offset++);
1315 /*-----------------------------------------------------------------*/
1316 /* outBitC - output a bit C */
1317 /*-----------------------------------------------------------------*/
1318 static void outBitC(operand *result)
1321 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1322 /* if the result is bit */
1323 if (AOP_TYPE(result) == AOP_CRY)
1324 aopPut(AOP(result),"c",0);
1326 emitcode("clr","a ; %d", __LINE__);
1327 emitcode("rlc","a");
1332 /*-----------------------------------------------------------------*/
1333 /* toBoolean - emit code for orl a,operator(sizeop) */
1334 /*-----------------------------------------------------------------*/
1335 static void toBoolean(operand *oper)
1337 int size = AOP_SIZE(oper) - 1;
1340 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1342 if ( AOP_TYPE(oper) != AOP_ACC)
1343 emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1346 emitcode("iorwf","%s,w",aopGet(AOP(oper),offset++,FALSE,FALSE));
1350 /*-----------------------------------------------------------------*/
1351 /* genNot - generate code for ! operation */
1352 /*-----------------------------------------------------------------*/
1353 static void genNot (iCode *ic)
1356 sym_link *optype = operandType(IC_LEFT(ic));
1358 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1359 /* assign asmOps to operand & result */
1360 aopOp (IC_LEFT(ic),ic,FALSE);
1361 aopOp (IC_RESULT(ic),ic,TRUE);
1363 /* if in bit space then a special case */
1364 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1365 emitcode("movlw","1<<%s");
1366 //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1367 //emitcode("cpl","c");
1368 //outBitC(IC_RESULT(ic));
1372 /* if type float then do float */
1373 if (IS_FLOAT(optype)) {
1374 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1378 toBoolean(IC_LEFT(ic));
1380 tlbl = newiTempLabel(NULL);
1381 emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1382 emitcode("","%05d_DS_:",tlbl->key+100);
1383 outBitC(IC_RESULT(ic));
1386 /* release the aops */
1387 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1388 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1392 /*-----------------------------------------------------------------*/
1393 /* genCpl - generate code for complement */
1394 /*-----------------------------------------------------------------*/
1395 static void genCpl (iCode *ic)
1401 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1402 /* assign asmOps to operand & result */
1403 aopOp (IC_LEFT(ic),ic,FALSE);
1404 aopOp (IC_RESULT(ic),ic,TRUE);
1406 /* if both are in bit space then
1408 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1409 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1411 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1412 emitcode("cpl","c");
1413 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1417 size = AOP_SIZE(IC_RESULT(ic));
1419 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1421 emitcode("cpl","a");
1422 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1427 /* release the aops */
1428 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1429 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1432 /*-----------------------------------------------------------------*/
1433 /* genUminusFloat - unary minus for floating points */
1434 /*-----------------------------------------------------------------*/
1435 static void genUminusFloat(operand *op,operand *result)
1437 int size ,offset =0 ;
1440 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1441 /* for this we just need to flip the
1442 first it then copy the rest in place */
1443 size = AOP_SIZE(op) - 1;
1444 l = aopGet(AOP(op),3,FALSE,FALSE);
1448 emitcode("cpl","acc.7");
1449 aopPut(AOP(result),"a",3);
1453 aopGet(AOP(op),offset,FALSE,FALSE),
1459 /*-----------------------------------------------------------------*/
1460 /* genUminus - unary minus code generation */
1461 /*-----------------------------------------------------------------*/
1462 static void genUminus (iCode *ic)
1465 sym_link *optype, *rtype;
1468 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1470 aopOp(IC_LEFT(ic),ic,FALSE);
1471 aopOp(IC_RESULT(ic),ic,TRUE);
1473 /* if both in bit space then special
1475 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1476 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1478 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1479 emitcode("cpl","c");
1480 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1484 optype = operandType(IC_LEFT(ic));
1485 rtype = operandType(IC_RESULT(ic));
1487 /* if float then do float stuff */
1488 if (IS_FLOAT(optype)) {
1489 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1493 /* otherwise subtract from zero */
1494 size = AOP_SIZE(IC_LEFT(ic));
1498 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1499 if (!strcmp(l,"a")) {
1500 emitcode("cpl","a");
1501 emitcode("inc","a");
1503 emitcode("clr","a");
1504 emitcode("subb","a,%s",l);
1506 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1509 /* if any remaining bytes in the result */
1510 /* we just need to propagate the sign */
1511 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1512 emitcode("rlc","a");
1513 emitcode("subb","a,acc");
1515 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1519 /* release the aops */
1520 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1521 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1524 /*-----------------------------------------------------------------*/
1525 /* saveRegisters - will look for a call and save the registers */
1526 /*-----------------------------------------------------------------*/
1527 static void saveRegisters(iCode *lic)
1534 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1536 for (ic = lic ; ic ; ic = ic->next)
1537 if (ic->op == CALL || ic->op == PCALL)
1541 fprintf(stderr,"found parameter push with no function call\n");
1545 /* if the registers have been saved already then
1547 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1550 /* find the registers in use at this time
1551 and push them away to safety */
1552 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1556 if (options.useXstack) {
1557 if (bitVectBitValue(rsave,R0_IDX))
1558 emitcode("mov","b,r0");
1559 emitcode("mov","r0,%s",spname);
1560 for (i = 0 ; i < pic14_nRegs ; i++) {
1561 if (bitVectBitValue(rsave,i)) {
1563 emitcode("mov","a,b");
1565 emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1566 emitcode("movx","@r0,a");
1567 emitcode("inc","r0");
1570 emitcode("mov","%s,r0",spname);
1571 if (bitVectBitValue(rsave,R0_IDX))
1572 emitcode("mov","r0,b");
1574 for (i = 0 ; i < pic14_nRegs ; i++) {
1575 if (bitVectBitValue(rsave,i))
1576 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1579 detype = getSpec(operandType(IC_LEFT(ic)));
1581 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1582 IS_ISR(currFunc->etype) &&
1585 saverbank(SPEC_BANK(detype),ic,TRUE);
1588 /*-----------------------------------------------------------------*/
1589 /* unsaveRegisters - pop the pushed registers */
1590 /*-----------------------------------------------------------------*/
1591 static void unsaveRegisters (iCode *ic)
1596 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1597 /* find the registers in use at this time
1598 and push them away to safety */
1599 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1602 if (options.useXstack) {
1603 emitcode("mov","r0,%s",spname);
1604 for (i = pic14_nRegs ; i >= 0 ; i--) {
1605 if (bitVectBitValue(rsave,i)) {
1606 emitcode("dec","r0");
1607 emitcode("movx","a,@r0");
1609 emitcode("mov","b,a");
1611 emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1615 emitcode("mov","%s,r0",spname);
1616 if (bitVectBitValue(rsave,R0_IDX))
1617 emitcode("mov","r0,b");
1619 for (i = pic14_nRegs ; i >= 0 ; i--) {
1620 if (bitVectBitValue(rsave,i))
1621 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1627 /*-----------------------------------------------------------------*/
1629 /*-----------------------------------------------------------------*/
1630 static void pushSide(operand * oper, int size)
1633 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1635 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1636 if (AOP_TYPE(oper) != AOP_REG &&
1637 AOP_TYPE(oper) != AOP_DIR &&
1639 emitcode("mov","a,%s",l);
1640 emitcode("push","acc");
1642 emitcode("push","%s",l);
1646 /*-----------------------------------------------------------------*/
1647 /* assignResultValue - */
1648 /*-----------------------------------------------------------------*/
1649 static void assignResultValue(operand * oper)
1652 int size = AOP_SIZE(oper);
1654 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1656 // The last byte in the assignment is in W
1657 aopPut(AOP(oper),"W",size-1);
1661 aopPut(AOP(oper),fReturn[offset],offset);
1669 /*-----------------------------------------------------------------*/
1670 /* genXpush - pushes onto the external stack */
1671 /*-----------------------------------------------------------------*/
1672 static void genXpush (iCode *ic)
1674 asmop *aop = newAsmop(0);
1676 int size,offset = 0;
1678 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1679 aopOp(IC_LEFT(ic),ic,FALSE);
1680 r = getFreePtr(ic,&aop,FALSE);
1683 emitcode("mov","%s,_spx",r->name);
1685 size = AOP_SIZE(IC_LEFT(ic));
1688 char *l = aopGet(AOP(IC_LEFT(ic)),
1689 offset++,FALSE,FALSE);
1691 emitcode("movx","@%s,a",r->name);
1692 emitcode("inc","%s",r->name);
1697 emitcode("mov","_spx,%s",r->name);
1699 freeAsmop(NULL,aop,ic,TRUE);
1700 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1703 /*-----------------------------------------------------------------*/
1704 /* genIpush - genrate code for pushing this gets a little complex */
1705 /*-----------------------------------------------------------------*/
1706 static void genIpush (iCode *ic)
1708 int size, offset = 0 ;
1712 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1713 /* if this is not a parm push : ie. it is spill push
1714 and spill push is always done on the local stack */
1715 if (!ic->parmPush) {
1717 /* and the item is spilt then do nothing */
1718 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1721 aopOp(IC_LEFT(ic),ic,FALSE);
1722 size = AOP_SIZE(IC_LEFT(ic));
1723 /* push it on the stack */
1725 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1730 emitcode("push","%s",l);
1735 /* this is a paramter push: in this case we call
1736 the routine to find the call and save those
1737 registers that need to be saved */
1740 /* if use external stack then call the external
1741 stack pushing routine */
1742 if (options.useXstack) {
1747 /* then do the push */
1748 aopOp(IC_LEFT(ic),ic,FALSE);
1751 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1752 size = AOP_SIZE(IC_LEFT(ic));
1755 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1756 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1757 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1759 emitcode("mov","a,%s",l);
1760 emitcode("push","acc");
1762 emitcode("push","%s",l);
1765 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1768 /*-----------------------------------------------------------------*/
1769 /* genIpop - recover the registers: can happen only for spilling */
1770 /*-----------------------------------------------------------------*/
1771 static void genIpop (iCode *ic)
1776 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1777 /* if the temp was not pushed then */
1778 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1781 aopOp(IC_LEFT(ic),ic,FALSE);
1782 size = AOP_SIZE(IC_LEFT(ic));
1785 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
1788 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1791 /*-----------------------------------------------------------------*/
1792 /* unsaverbank - restores the resgister bank from stack */
1793 /*-----------------------------------------------------------------*/
1794 static void unsaverbank (int bank,iCode *ic,bool popPsw)
1800 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1802 if (options.useXstack) {
1804 r = getFreePtr(ic,&aop,FALSE);
1807 emitcode("mov","%s,_spx",r->name);
1808 emitcode("movx","a,@%s",r->name);
1809 emitcode("mov","psw,a");
1810 emitcode("dec","%s",r->name);
1813 emitcode ("pop","psw");
1816 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
1817 if (options.useXstack) {
1818 emitcode("movx","a,@%s",r->name);
1819 //emitcode("mov","(%s+%d),a",
1820 // regspic14[i].base,8*bank+regspic14[i].offset);
1821 emitcode("dec","%s",r->name);
1824 emitcode("pop",""); //"(%s+%d)",
1825 //regspic14[i].base,8*bank); //+regspic14[i].offset);
1828 if (options.useXstack) {
1830 emitcode("mov","_spx,%s",r->name);
1831 freeAsmop(NULL,aop,ic,TRUE);
1836 /*-----------------------------------------------------------------*/
1837 /* saverbank - saves an entire register bank on the stack */
1838 /*-----------------------------------------------------------------*/
1839 static void saverbank (int bank, iCode *ic, bool pushPsw)
1845 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1846 if (options.useXstack) {
1849 r = getFreePtr(ic,&aop,FALSE);
1850 emitcode("mov","%s,_spx",r->name);
1854 for (i = 0 ; i < pic14_nRegs ;i++) {
1855 if (options.useXstack) {
1856 emitcode("inc","%s",r->name);
1857 //emitcode("mov","a,(%s+%d)",
1858 // regspic14[i].base,8*bank+regspic14[i].offset);
1859 emitcode("movx","@%s,a",r->name);
1861 emitcode("push","");// "(%s+%d)",
1862 //regspic14[i].base,8*bank+regspic14[i].offset);
1866 if (options.useXstack) {
1867 emitcode("mov","a,psw");
1868 emitcode("movx","@%s,a",r->name);
1869 emitcode("inc","%s",r->name);
1870 emitcode("mov","_spx,%s",r->name);
1871 freeAsmop (NULL,aop,ic,TRUE);
1874 emitcode("push","psw");
1876 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
1882 /*-----------------------------------------------------------------*/
1883 /* genCall - generates a call statement */
1884 /*-----------------------------------------------------------------*/
1885 static void genCall (iCode *ic)
1889 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1891 /* if caller saves & we have not saved then */
1895 /* if we are calling a function that is not using
1896 the same register bank then we need to save the
1897 destination registers on the stack */
1898 detype = getSpec(operandType(IC_LEFT(ic)));
1900 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1901 IS_ISR(currFunc->etype) &&
1904 saverbank(SPEC_BANK(detype),ic,TRUE);
1906 /* if send set is not empty the assign */
1910 for (sic = setFirstItem(_G.sendSet) ; sic ;
1911 sic = setNextItem(_G.sendSet)) {
1912 int size, offset = 0;
1914 aopOp(IC_LEFT(sic),sic,FALSE);
1915 size = AOP_SIZE(IC_LEFT(sic));
1917 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1919 DEBUGemitcode(";","%d - left type %d",__LINE__,AOP(IC_LEFT(sic))->type);
1921 if (strcmp(l,fReturn[offset])) {
1923 if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
1924 ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
1925 emitcode("movlw","%s",l);
1927 emitcode("movf","%s,w",l);
1928 // The last one is past in W
1930 emitcode("movwf","%s",fReturn[offset]);
1934 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
1939 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1940 OP_SYMBOL(IC_LEFT(ic))->rname :
1941 OP_SYMBOL(IC_LEFT(ic))->name));
1943 /* if we need assign a result value */
1944 if ((IS_ITEMP(IC_RESULT(ic)) &&
1945 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1946 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1947 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1950 aopOp(IC_RESULT(ic),ic,FALSE);
1953 assignResultValue(IC_RESULT(ic));
1955 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
1958 /* adjust the stack for parameters if
1960 if (IC_LEFT(ic)->parmBytes) {
1962 if (IC_LEFT(ic)->parmBytes > 3) {
1963 emitcode("mov","a,%s",spname);
1964 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
1965 emitcode("mov","%s,a",spname);
1967 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
1968 emitcode("dec","%s",spname);
1972 /* if register bank was saved then pop them */
1974 unsaverbank(SPEC_BANK(detype),ic,TRUE);
1976 /* if we hade saved some registers then unsave them */
1977 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1978 unsaveRegisters (ic);
1983 /*-----------------------------------------------------------------*/
1984 /* genPcall - generates a call by pointer statement */
1985 /*-----------------------------------------------------------------*/
1986 static void genPcall (iCode *ic)
1989 symbol *rlbl = newiTempLabel(NULL);
1992 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1993 /* if caller saves & we have not saved then */
1997 /* if we are calling a function that is not using
1998 the same register bank then we need to save the
1999 destination registers on the stack */
2000 detype = getSpec(operandType(IC_LEFT(ic)));
2002 IS_ISR(currFunc->etype) &&
2003 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2004 saverbank(SPEC_BANK(detype),ic,TRUE);
2007 /* push the return address on to the stack */
2008 emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2009 emitcode("push","acc");
2010 emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2011 emitcode("push","acc");
2013 if (options.model == MODEL_FLAT24)
2015 emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2016 emitcode("push","acc");
2019 /* now push the calling address */
2020 aopOp(IC_LEFT(ic),ic,FALSE);
2022 pushSide(IC_LEFT(ic), FPTRSIZE);
2024 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2026 /* if send set is not empty the assign */
2030 for (sic = setFirstItem(_G.sendSet) ; sic ;
2031 sic = setNextItem(_G.sendSet)) {
2032 int size, offset = 0;
2033 aopOp(IC_LEFT(sic),sic,FALSE);
2034 size = AOP_SIZE(IC_LEFT(sic));
2036 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2038 if (strcmp(l,fReturn[offset]))
2039 emitcode("mov","%s,%s",
2044 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2050 emitcode("","%05d_DS_:",(rlbl->key+100));
2053 /* if we need assign a result value */
2054 if ((IS_ITEMP(IC_RESULT(ic)) &&
2055 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2056 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2057 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2060 aopOp(IC_RESULT(ic),ic,FALSE);
2063 assignResultValue(IC_RESULT(ic));
2065 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2068 /* adjust the stack for parameters if
2070 if (IC_LEFT(ic)->parmBytes) {
2072 if (IC_LEFT(ic)->parmBytes > 3) {
2073 emitcode("mov","a,%s",spname);
2074 emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
2075 emitcode("mov","%s,a",spname);
2077 for ( i = 0 ; i < IC_LEFT(ic)->parmBytes ;i++)
2078 emitcode("dec","%s",spname);
2082 /* if register bank was saved then unsave them */
2084 (SPEC_BANK(currFunc->etype) !=
2086 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2088 /* if we hade saved some registers then
2091 unsaveRegisters (ic);
2095 /*-----------------------------------------------------------------*/
2096 /* resultRemat - result is rematerializable */
2097 /*-----------------------------------------------------------------*/
2098 static int resultRemat (iCode *ic)
2100 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2101 if (SKIP_IC(ic) || ic->op == IFX)
2104 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2105 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2106 if (sym->remat && !POINTER_SET(ic))
2113 #if defined(__BORLANDC__) || defined(_MSC_VER)
2114 #define STRCASECMP stricmp
2116 #define STRCASECMP strcasecmp
2119 /*-----------------------------------------------------------------*/
2120 /* inExcludeList - return 1 if the string is in exclude Reg list */
2121 /*-----------------------------------------------------------------*/
2122 static bool inExcludeList(char *s)
2126 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2127 if (options.excludeRegs[i] &&
2128 STRCASECMP(options.excludeRegs[i],"none") == 0)
2131 for ( i = 0 ; options.excludeRegs[i]; i++) {
2132 if (options.excludeRegs[i] &&
2133 STRCASECMP(s,options.excludeRegs[i]) == 0)
2139 /*-----------------------------------------------------------------*/
2140 /* genFunction - generated code for function entry */
2141 /*-----------------------------------------------------------------*/
2142 static void genFunction (iCode *ic)
2147 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2148 labelOffset += FUNCTION_LABEL_INC;
2151 /* create the function header */
2152 emitcode(";","-----------------------------------------");
2153 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2154 emitcode(";","-----------------------------------------");
2156 emitcode("","%s:",sym->rname);
2157 fetype = getSpec(operandType(IC_LEFT(ic)));
2159 /* if critical function then turn interrupts off */
2160 if (SPEC_CRTCL(fetype))
2161 emitcode("clr","ea");
2163 /* here we need to generate the equates for the
2164 register bank if required */
2166 if (SPEC_BANK(fetype) != rbank) {
2169 rbank = SPEC_BANK(fetype);
2170 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2171 if (strcmp(regspic14[i].base,"0") == 0)
2172 emitcode("","%s = 0x%02x",
2174 8*rbank+regspic14[i].offset);
2176 emitcode ("","%s = %s + 0x%02x",
2179 8*rbank+regspic14[i].offset);
2184 /* if this is an interrupt service routine then
2185 save acc, b, dpl, dph */
2186 if (IS_ISR(sym->etype)) {
2188 if (!inExcludeList("acc"))
2189 emitcode ("push","acc");
2190 if (!inExcludeList("b"))
2191 emitcode ("push","b");
2192 if (!inExcludeList("dpl"))
2193 emitcode ("push","dpl");
2194 if (!inExcludeList("dph"))
2195 emitcode ("push","dph");
2196 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2198 emitcode ("push", "dpx");
2199 /* Make sure we're using standard DPTR */
2200 emitcode ("push", "dps");
2201 emitcode ("mov", "dps, #0x00");
2202 if (options.stack10bit)
2204 /* This ISR could conceivably use DPTR2. Better save it. */
2205 emitcode ("push", "dpl1");
2206 emitcode ("push", "dph1");
2207 emitcode ("push", "dpx1");
2210 /* if this isr has no bank i.e. is going to
2211 run with bank 0 , then we need to save more
2213 if (!SPEC_BANK(sym->etype)) {
2215 /* if this function does not call any other
2216 function then we can be economical and
2217 save only those registers that are used */
2218 if (! sym->hasFcall) {
2221 /* if any registers used */
2222 if (sym->regsUsed) {
2223 /* save the registers used */
2224 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2225 if (bitVectBitValue(sym->regsUsed,i) ||
2226 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2227 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2232 /* this function has a function call cannot
2233 determines register usage so we will have the
2235 saverbank(0,ic,FALSE);
2239 /* if callee-save to be used for this function
2240 then save the registers being used in this function */
2241 if (sym->calleeSave) {
2244 /* if any registers used */
2245 if (sym->regsUsed) {
2246 /* save the registers used */
2247 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2248 if (bitVectBitValue(sym->regsUsed,i) ||
2249 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2250 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2258 /* set the register bank to the desired value */
2259 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2260 emitcode("push","psw");
2261 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2264 if (IS_RENT(sym->etype) || options.stackAuto) {
2266 if (options.useXstack) {
2267 emitcode("mov","r0,%s",spname);
2268 emitcode("mov","a,_bp");
2269 emitcode("movx","@r0,a");
2270 emitcode("inc","%s",spname);
2274 /* set up the stack */
2275 emitcode ("push","_bp"); /* save the callers stack */
2277 emitcode ("mov","_bp,%s",spname);
2280 /* adjust the stack for the function */
2285 werror(W_STACK_OVERFLOW,sym->name);
2287 if (i > 3 && sym->recvSize < 4) {
2289 emitcode ("mov","a,sp");
2290 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2291 emitcode ("mov","sp,a");
2296 emitcode("inc","sp");
2301 emitcode ("mov","a,_spx");
2302 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2303 emitcode ("mov","_spx,a");
2308 /*-----------------------------------------------------------------*/
2309 /* genEndFunction - generates epilogue for functions */
2310 /*-----------------------------------------------------------------*/
2311 static void genEndFunction (iCode *ic)
2313 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2315 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2317 if (IS_RENT(sym->etype) || options.stackAuto)
2319 emitcode ("mov","%s,_bp",spname);
2322 /* if use external stack but some variables were
2323 added to the local stack then decrement the
2325 if (options.useXstack && sym->stack) {
2326 emitcode("mov","a,sp");
2327 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2328 emitcode("mov","sp,a");
2332 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2333 if (options.useXstack) {
2334 emitcode("mov","r0,%s",spname);
2335 emitcode("movx","a,@r0");
2336 emitcode("mov","_bp,a");
2337 emitcode("dec","%s",spname);
2341 emitcode ("pop","_bp");
2345 /* restore the register bank */
2346 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2347 emitcode ("pop","psw");
2349 if (IS_ISR(sym->etype)) {
2351 /* now we need to restore the registers */
2352 /* if this isr has no bank i.e. is going to
2353 run with bank 0 , then we need to save more
2355 if (!SPEC_BANK(sym->etype)) {
2357 /* if this function does not call any other
2358 function then we can be economical and
2359 save only those registers that are used */
2360 if (! sym->hasFcall) {
2363 /* if any registers used */
2364 if (sym->regsUsed) {
2365 /* save the registers used */
2366 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2367 if (bitVectBitValue(sym->regsUsed,i) ||
2368 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2369 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2374 /* this function has a function call cannot
2375 determines register usage so we will have the
2377 unsaverbank(0,ic,FALSE);
2381 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2383 if (options.stack10bit)
2385 emitcode ("pop", "dpx1");
2386 emitcode ("pop", "dph1");
2387 emitcode ("pop", "dpl1");
2389 emitcode ("pop", "dps");
2390 emitcode ("pop", "dpx");
2392 if (!inExcludeList("dph"))
2393 emitcode ("pop","dph");
2394 if (!inExcludeList("dpl"))
2395 emitcode ("pop","dpl");
2396 if (!inExcludeList("b"))
2397 emitcode ("pop","b");
2398 if (!inExcludeList("acc"))
2399 emitcode ("pop","acc");
2401 if (SPEC_CRTCL(sym->etype))
2402 emitcode("setb","ea");
2404 /* if debug then send end of function */
2405 /* if (options.debug && currFunc) { */
2408 emitcode(";","C$%s$%d$%d$%d ==.",
2409 FileBaseName(ic->filename),currFunc->lastLine,
2410 ic->level,ic->block);
2411 if (IS_STATIC(currFunc->etype))
2412 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2414 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2418 emitcode ("reti","");
2421 if (SPEC_CRTCL(sym->etype))
2422 emitcode("setb","ea");
2424 if (sym->calleeSave) {
2427 /* if any registers used */
2428 if (sym->regsUsed) {
2429 /* save the registers used */
2430 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2431 if (bitVectBitValue(sym->regsUsed,i) ||
2432 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2433 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2439 /* if debug then send end of function */
2442 emitcode(";","C$%s$%d$%d$%d ==.",
2443 FileBaseName(ic->filename),currFunc->lastLine,
2444 ic->level,ic->block);
2445 if (IS_STATIC(currFunc->etype))
2446 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2448 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2452 emitcode ("return","");
2457 /*-----------------------------------------------------------------*/
2458 /* genRet - generate code for return statement */
2459 /*-----------------------------------------------------------------*/
2460 static void genRet (iCode *ic)
2462 int size,offset = 0 , pushed = 0;
2464 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2465 /* if we have no return value then
2466 just generate the "ret" */
2470 /* we have something to return then
2471 move the return value into place */
2472 aopOp(IC_LEFT(ic),ic,FALSE);
2473 size = AOP_SIZE(IC_LEFT(ic));
2477 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2479 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2481 emitcode("push","%s",l);
2484 l = aopGet(AOP(IC_LEFT(ic)),offset,
2486 if (strcmp(fReturn[offset],l)) {
2487 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2488 ((AOP(IC_LEFT(ic))->type) == AOP_LIT) )
2489 emitcode("movlw","%s",l);
2491 emitcode("movf","%s,w",l);
2493 emitcode("movwf","%s",fReturn[offset]);
2502 if (strcmp(fReturn[pushed],"a"))
2503 emitcode("pop",fReturn[pushed]);
2505 emitcode("pop","acc");
2508 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2511 /* generate a jump to the return label
2512 if the next is not the return statement */
2513 if (!(ic->next && ic->next->op == LABEL &&
2514 IC_LABEL(ic->next) == returnLabel))
2516 emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2520 /*-----------------------------------------------------------------*/
2521 /* genLabel - generates a label */
2522 /*-----------------------------------------------------------------*/
2523 static void genLabel (iCode *ic)
2525 /* special case never generate */
2526 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2527 if (IC_LABEL(ic) == entryLabel)
2530 emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2533 /*-----------------------------------------------------------------*/
2534 /* genGoto - generates a goto */
2535 /*-----------------------------------------------------------------*/
2537 static void genGoto (iCode *ic)
2539 emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2542 /*-----------------------------------------------------------------*/
2543 /* findLabelBackwards: walks back through the iCode chain looking */
2544 /* for the given label. Returns number of iCode instructions */
2545 /* between that label and given ic. */
2546 /* Returns zero if label not found. */
2547 /*-----------------------------------------------------------------*/
2549 static int findLabelBackwards(iCode *ic, int key)
2553 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2559 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2561 /* printf("findLabelBackwards = %d\n", count); */
2569 /*-----------------------------------------------------------------*/
2570 /* genPlusIncr :- does addition with increment if possible */
2571 /*-----------------------------------------------------------------*/
2572 static bool genPlusIncr (iCode *ic)
2574 unsigned int icount ;
2575 unsigned int size = getDataSize(IC_RESULT(ic));
2577 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2578 DEBUGemitcode ("; ","result %d, left %d, right %d",
2579 AOP_TYPE(IC_RESULT(ic)),
2580 AOP_TYPE(IC_LEFT(ic)),
2581 AOP_TYPE(IC_RIGHT(ic)));
2583 /* will try to generate an increment */
2584 /* if the right side is not a literal
2586 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2589 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2590 /* if the literal value of the right hand side
2591 is greater than 1 then it is faster to add */
2592 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2595 /* if increment 16 bits in register */
2596 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2601 emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2605 emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2611 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2612 /* if left is in accumulator - probably a bit operation*/
2613 if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") &&
2614 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
2616 emitcode("bcf","(%s >> 3), (%s & 7)",
2617 AOP(IC_RESULT(ic))->aopu.aop_dir,
2618 AOP(IC_RESULT(ic))->aopu.aop_dir);
2620 emitcode("xorlw","1");
2622 emitcode("andlw","1");
2625 emitcode("bsf","(%s >> 3), (%s & 7)",
2626 AOP(IC_RESULT(ic))->aopu.aop_dir,
2627 AOP(IC_RESULT(ic))->aopu.aop_dir);
2634 /* if the sizes are greater than 1 then we cannot */
2635 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2636 AOP_SIZE(IC_LEFT(ic)) > 1 )
2639 /* If we are incrementing the same register by two: */
2641 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2644 emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2649 DEBUGemitcode ("; ","couldn't increment result-%s left-%s",
2650 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
2651 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2655 /*-----------------------------------------------------------------*/
2656 /* outBitAcc - output a bit in acc */
2657 /*-----------------------------------------------------------------*/
2658 static void outBitAcc(operand *result)
2660 symbol *tlbl = newiTempLabel(NULL);
2661 /* if the result is a bit */
2662 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2664 if (AOP_TYPE(result) == AOP_CRY){
2665 aopPut(AOP(result),"a",0);
2668 emitcode("jz","%05d_DS_",tlbl->key+100);
2669 emitcode("mov","a,%s",one);
2670 emitcode("","%05d_DS_:",tlbl->key+100);
2675 /*-----------------------------------------------------------------*/
2676 /* genPlusBits - generates code for addition of two bits */
2677 /*-----------------------------------------------------------------*/
2678 static void genPlusBits (iCode *ic)
2681 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2683 The following block of code will add two bits.
2684 Note that it'll even work if the destination is
2685 the carry (C in the status register).
2686 It won't work if the 'Z' bit is a source or destination.
2689 /* If the result is stored in the accumulator (w) */
2690 if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2691 emitcode("movlw","(1 << (%s & 7))",
2692 AOP(IC_RESULT(ic))->aopu.aop_dir,
2693 AOP(IC_RESULT(ic))->aopu.aop_dir);
2694 emitcode("bcf","(%s >> 3), (%s & 7)",
2695 AOP(IC_RESULT(ic))->aopu.aop_dir,
2696 AOP(IC_RESULT(ic))->aopu.aop_dir);
2697 emitcode("btfsc","(%s >> 3), (%s & 7)",
2698 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2699 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2700 emitcode("xorwf","(%s >>3),f",
2701 AOP(IC_RESULT(ic))->aopu.aop_dir);
2702 emitcode("btfsc","(%s >> 3), (%s & 7)",
2703 AOP(IC_LEFT(ic))->aopu.aop_dir,
2704 AOP(IC_LEFT(ic))->aopu.aop_dir);
2705 emitcode("xorwf","(%s>>3),f",
2706 AOP(IC_RESULT(ic))->aopu.aop_dir);
2709 emitcode("clrw","");
2710 emitcode("btfsc","(%s >> 3), (%s & 7)",
2711 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2712 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2713 emitcode("xorlw","1");
2714 emitcode("btfsc","(%s >> 3), (%s & 7)",
2715 AOP(IC_LEFT(ic))->aopu.aop_dir,
2716 AOP(IC_LEFT(ic))->aopu.aop_dir);
2717 emitcode("xorlw","1");
2723 /* This is the original version of this code.
2725 * This is being kept around for reference,
2726 * because I am not entirely sure I got it right...
2728 static void adjustArithmeticResult(iCode *ic)
2730 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2731 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2732 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2733 aopPut(AOP(IC_RESULT(ic)),
2734 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
2737 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2738 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
2739 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2740 aopPut(AOP(IC_RESULT(ic)),
2741 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
2744 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2745 AOP_SIZE(IC_LEFT(ic)) < 3 &&
2746 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
2747 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2748 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2750 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2751 aopPut(AOP(IC_RESULT(ic)),buffer,2);
2755 /* This is the pure and virtuous version of this code.
2756 * I'm pretty certain it's right, but not enough to toss the old
2759 static void adjustArithmeticResult(iCode *ic)
2761 if (opIsGptr(IC_RESULT(ic)) &&
2762 opIsGptr(IC_LEFT(ic)) &&
2763 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2765 aopPut(AOP(IC_RESULT(ic)),
2766 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
2770 if (opIsGptr(IC_RESULT(ic)) &&
2771 opIsGptr(IC_RIGHT(ic)) &&
2772 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
2774 aopPut(AOP(IC_RESULT(ic)),
2775 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
2779 if (opIsGptr(IC_RESULT(ic)) &&
2780 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
2781 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
2782 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
2783 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
2785 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
2786 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
2791 /*-----------------------------------------------------------------*/
2792 /* genPlus - generates code for addition */
2793 /*-----------------------------------------------------------------*/
2794 static void genPlus (iCode *ic)
2796 int size, offset = 0;
2798 /* special cases :- */
2799 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2801 aopOp (IC_LEFT(ic),ic,FALSE);
2802 aopOp (IC_RIGHT(ic),ic,FALSE);
2803 aopOp (IC_RESULT(ic),ic,TRUE);
2805 /* if literal, literal on the right or
2806 if left requires ACC or right is already
2809 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2810 operand *t = IC_RIGHT(ic);
2811 IC_RIGHT(ic) = IC_LEFT(ic);
2815 /* if both left & right are in bit space */
2816 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2817 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2822 /* if left in bit space & right literal */
2823 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2824 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2825 /* if result in bit space */
2826 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
2827 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
2828 emitcode("movlw","(1 << (%s & 7)) ;%d",AOP(IC_RESULT(ic))->aopu.aop_dir,__LINE__);
2829 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2830 emitcode("btfsc","(%s >> 3), (%s & 7)",
2831 AOP(IC_LEFT(ic))->aopu.aop_dir,
2832 AOP(IC_LEFT(ic))->aopu.aop_dir);
2834 emitcode("xorwf","(%s>>3),f",AOP(IC_RESULT(ic))->aopu.aop_dir);
2837 size = getDataSize(IC_RESULT(ic));
2839 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
2840 emitcode("addc","a,#00 ;%d",__LINE__);
2841 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2847 /* if I can do an increment instead
2848 of add then GOOD for ME */
2849 if (genPlusIncr (ic) == TRUE)
2852 size = getDataSize(IC_RESULT(ic));
2854 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
2855 /* Add a literal to something else */
2857 unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2861 DEBUGemitcode(";","adding lit to something. size %d",size);
2864 DEBUGemitcode(";","size %d",size);
2866 switch (lit & 0xff) {
2870 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2871 emitcode("incf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2874 emitcode("incf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2875 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
2876 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2880 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2881 emitcode("decf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2884 emitcode("decf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2885 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
2886 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2890 if( !know_W || ( (lit&0xff) != l1) ) {
2892 emitcode("movlw","0x%x", lit&0xff);
2894 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
2895 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2898 emitcode("addwf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
2899 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
2902 emitcode("incf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
2912 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2914 emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2915 emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2916 emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2918 /* here we are adding a bit to a char or int */
2920 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2922 emitcode("btfsc","(%s >> 3), (%s & 7)",
2923 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2924 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2925 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2928 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2929 emitcode("btfsc","(%s >> 3), (%s & 7)",
2930 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2931 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2932 emitcode(" xorlw","1");
2934 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2935 emitcode("btfsc","(%s >> 3), (%s & 7)",
2936 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2937 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2938 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2941 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
2943 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2944 emitcode("andlw","1");
2945 emitcode("bcf","(%s >> 3), (%s & 7)",
2946 AOP(IC_RESULT(ic))->aopu.aop_dir,
2947 AOP(IC_RESULT(ic))->aopu.aop_dir);
2949 emitcode("bsf","(%s >> 3), (%s & 7)",
2950 AOP(IC_RESULT(ic))->aopu.aop_dir,
2951 AOP(IC_RESULT(ic))->aopu.aop_dir);
2954 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2961 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2962 emitcode("clrz","");
2964 emitcode("btfsc","(%s >> 3), (%s & 7)",
2965 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2966 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2967 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2971 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2972 emitcode("btfsc","(%s >> 3), (%s & 7)",
2973 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2974 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2975 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2976 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2982 emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
2989 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2990 emitcode("addwf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2991 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2993 //if ( (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) || (AOP_TYPE(IC_RESULT(ic)) == AOP_ACC) )
2994 if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2995 emitcode("addwf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2996 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
2997 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3000 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3002 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3003 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3005 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
3006 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
3007 emitcode("addlw","%s", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3009 emitcode("addwf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3010 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3011 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3021 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3022 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3023 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3025 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3027 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3028 emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3034 //adjustArithmeticResult(ic);
3037 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3038 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3039 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3042 /*-----------------------------------------------------------------*/
3043 /* genMinusDec :- does subtraction with decrement if possible */
3044 /*-----------------------------------------------------------------*/
3045 static bool genMinusDec (iCode *ic)
3047 unsigned int icount ;
3048 unsigned int size = getDataSize(IC_RESULT(ic));
3050 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3051 /* will try to generate an increment */
3052 /* if the right side is not a literal
3054 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3057 DEBUGemitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
3059 /* if the literal value of the right hand side
3060 is greater than 4 then it is not worth it */
3061 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
3064 /* if decrement 16 bits in register */
3065 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3070 emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3071 emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3072 emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3074 /* size is 3 or 4 */
3075 emitcode("movlw","0xff");
3076 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3079 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3081 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3084 emitcode("skpnc","");
3086 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3095 /* if the sizes are greater than 1 then we cannot */
3096 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3097 AOP_SIZE(IC_LEFT(ic)) > 1 )
3100 /* we can if the aops of the left & result match or
3101 if they are in registers and the registers are the
3103 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3106 emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3111 DEBUGemitcode ("; returning"," result=%s, left=%s",
3112 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
3113 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3115 emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3116 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3123 /*-----------------------------------------------------------------*/
3124 /* addSign - complete with sign */
3125 /*-----------------------------------------------------------------*/
3126 static void addSign(operand *result, int offset, int sign)
3128 int size = (getDataSize(result) - offset);
3129 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3132 emitcode("rlc","a");
3133 emitcode("subb","a,acc");
3135 aopPut(AOP(result),"a",offset++);
3138 aopPut(AOP(result),zero,offset++);
3142 /*-----------------------------------------------------------------*/
3143 /* genMinusBits - generates code for subtraction of two bits */
3144 /*-----------------------------------------------------------------*/
3145 static void genMinusBits (iCode *ic)
3147 symbol *lbl = newiTempLabel(NULL);
3148 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3149 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3150 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3151 emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3152 emitcode("cpl","c");
3153 emitcode("","%05d_DS_:",(lbl->key+100));
3154 outBitC(IC_RESULT(ic));
3157 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3158 emitcode("subb","a,acc");
3159 emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3160 emitcode("inc","a");
3161 emitcode("","%05d_DS_:",(lbl->key+100));
3162 aopPut(AOP(IC_RESULT(ic)),"a",0);
3163 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3167 /*-----------------------------------------------------------------*/
3168 /* genMinus - generates code for subtraction */
3169 /*-----------------------------------------------------------------*/
3170 static void genMinus (iCode *ic)
3172 int size, offset = 0;
3173 unsigned long lit = 0L;
3175 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3176 aopOp (IC_LEFT(ic),ic,FALSE);
3177 aopOp (IC_RIGHT(ic),ic,FALSE);
3178 aopOp (IC_RESULT(ic),ic,TRUE);
3180 /* special cases :- */
3181 /* if both left & right are in bit space */
3182 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3183 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3188 /* if I can do an decrement instead
3189 of subtract then GOOD for ME */
3190 if (genMinusDec (ic) == TRUE)
3193 size = getDataSize(IC_RESULT(ic));
3195 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3196 /* Add a literal to something else */
3198 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3201 /* add the first byte: */
3202 emitcode("movlw","0x%x", lit & 0xff);
3203 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3210 emitcode("rlf","_known_zero,w");
3211 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3215 emitcode("movlw","0x%x", lit & 0xff);
3216 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3224 emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3225 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3231 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3233 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3234 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3241 // adjustArithmeticResult(ic);
3244 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3245 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3246 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3250 /*-----------------------------------------------------------------*/
3251 /* genMultbits :- multiplication of bits */
3252 /*-----------------------------------------------------------------*/
3253 static void genMultbits (operand *left,
3257 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3259 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3260 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3265 /*-----------------------------------------------------------------*/
3266 /* genMultOneByte : 8 bit multiplication & division */
3267 /*-----------------------------------------------------------------*/
3268 static void genMultOneByte (operand *left,
3272 sym_link *opetype = operandType(result);
3277 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3278 /* (if two literals, the value is computed before) */
3279 /* if one literal, literal on the right */
3280 if (AOP_TYPE(left) == AOP_LIT){
3286 size = AOP_SIZE(result);
3287 /* signed or unsigned */
3288 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3289 l = aopGet(AOP(left),0,FALSE,FALSE);
3291 emitcode("mul","ab");
3292 /* if result size = 1, mul signed = mul unsigned */
3293 aopPut(AOP(result),"a",0);
3295 if (SPEC_USIGN(opetype)){
3296 aopPut(AOP(result),"b",1);
3298 /* for filling the MSBs */
3299 emitcode("clr","a");
3302 emitcode("mov","a,b");
3304 /* adjust the MSB if left or right neg */
3306 /* if one literal */
3307 if (AOP_TYPE(right) == AOP_LIT){
3308 /* AND literal negative */
3309 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3310 /* adjust MSB (c==0 after mul) */
3311 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3315 lbl = newiTempLabel(NULL);
3316 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3317 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3318 emitcode("","%05d_DS_:",(lbl->key+100));
3319 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3320 lbl = newiTempLabel(NULL);
3321 emitcode("jc","%05d_DS_",(lbl->key+100));
3322 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3323 emitcode("","%05d_DS_:",(lbl->key+100));
3326 lbl = newiTempLabel(NULL);
3327 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3328 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3329 emitcode("","%05d_DS_:",(lbl->key+100));
3330 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3331 lbl = newiTempLabel(NULL);
3332 emitcode("jc","%05d_DS_",(lbl->key+100));
3333 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3334 emitcode("","%05d_DS_:",(lbl->key+100));
3336 aopPut(AOP(result),"a",1);
3339 emitcode("rlc","a");
3340 emitcode("subb","a,acc");
3347 aopPut(AOP(result),"a",offset++);
3351 /*-----------------------------------------------------------------*/
3352 /* genMult - generates code for multiplication */
3353 /*-----------------------------------------------------------------*/
3354 static void genMult (iCode *ic)
3356 operand *left = IC_LEFT(ic);
3357 operand *right = IC_RIGHT(ic);
3358 operand *result= IC_RESULT(ic);
3360 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3361 /* assign the amsops */
3362 aopOp (left,ic,FALSE);
3363 aopOp (right,ic,FALSE);
3364 aopOp (result,ic,TRUE);
3366 /* special cases first */
3368 if (AOP_TYPE(left) == AOP_CRY &&
3369 AOP_TYPE(right)== AOP_CRY) {
3370 genMultbits(left,right,result);
3374 /* if both are of size == 1 */
3375 if (AOP_SIZE(left) == 1 &&
3376 AOP_SIZE(right) == 1 ) {
3377 genMultOneByte(left,right,result);
3381 /* should have been converted to function call */
3385 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3386 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3387 freeAsmop(result,NULL,ic,TRUE);
3390 /*-----------------------------------------------------------------*/
3391 /* genDivbits :- division of bits */
3392 /*-----------------------------------------------------------------*/
3393 static void genDivbits (operand *left,
3400 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3401 /* the result must be bit */
3402 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3403 l = aopGet(AOP(left),0,FALSE,FALSE);
3407 emitcode("div","ab");
3408 emitcode("rrc","a");
3409 aopPut(AOP(result),"c",0);
3412 /*-----------------------------------------------------------------*/
3413 /* genDivOneByte : 8 bit division */
3414 /*-----------------------------------------------------------------*/
3415 static void genDivOneByte (operand *left,
3419 sym_link *opetype = operandType(result);
3424 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3425 size = AOP_SIZE(result) - 1;
3427 /* signed or unsigned */
3428 if (SPEC_USIGN(opetype)) {
3429 /* unsigned is easy */
3430 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3431 l = aopGet(AOP(left),0,FALSE,FALSE);
3433 emitcode("div","ab");
3434 aopPut(AOP(result),"a",0);
3436 aopPut(AOP(result),zero,offset++);
3440 /* signed is a little bit more difficult */
3442 /* save the signs of the operands */
3443 l = aopGet(AOP(left),0,FALSE,FALSE);
3445 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3446 emitcode("push","acc"); /* save it on the stack */
3448 /* now sign adjust for both left & right */
3449 l = aopGet(AOP(right),0,FALSE,FALSE);
3451 lbl = newiTempLabel(NULL);
3452 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3453 emitcode("cpl","a");
3454 emitcode("inc","a");
3455 emitcode("","%05d_DS_:",(lbl->key+100));
3456 emitcode("mov","b,a");
3458 /* sign adjust left side */
3459 l = aopGet(AOP(left),0,FALSE,FALSE);
3462 lbl = newiTempLabel(NULL);
3463 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3464 emitcode("cpl","a");
3465 emitcode("inc","a");
3466 emitcode("","%05d_DS_:",(lbl->key+100));
3468 /* now the division */
3469 emitcode("div","ab");
3470 /* we are interested in the lower order
3472 emitcode("mov","b,a");
3473 lbl = newiTempLabel(NULL);
3474 emitcode("pop","acc");
3475 /* if there was an over flow we don't
3476 adjust the sign of the result */
3477 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3478 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3480 emitcode("clr","a");
3481 emitcode("subb","a,b");
3482 emitcode("mov","b,a");
3483 emitcode("","%05d_DS_:",(lbl->key+100));
3485 /* now we are done */
3486 aopPut(AOP(result),"b",0);
3488 emitcode("mov","c,b.7");
3489 emitcode("subb","a,acc");
3492 aopPut(AOP(result),"a",offset++);
3496 /*-----------------------------------------------------------------*/
3497 /* genDiv - generates code for division */
3498 /*-----------------------------------------------------------------*/
3499 static void genDiv (iCode *ic)
3501 operand *left = IC_LEFT(ic);
3502 operand *right = IC_RIGHT(ic);
3503 operand *result= IC_RESULT(ic);
3505 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3506 /* assign the amsops */
3507 aopOp (left,ic,FALSE);
3508 aopOp (right,ic,FALSE);
3509 aopOp (result,ic,TRUE);
3511 /* special cases first */
3513 if (AOP_TYPE(left) == AOP_CRY &&
3514 AOP_TYPE(right)== AOP_CRY) {
3515 genDivbits(left,right,result);
3519 /* if both are of size == 1 */
3520 if (AOP_SIZE(left) == 1 &&
3521 AOP_SIZE(right) == 1 ) {
3522 genDivOneByte(left,right,result);
3526 /* should have been converted to function call */
3529 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3530 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3531 freeAsmop(result,NULL,ic,TRUE);
3534 /*-----------------------------------------------------------------*/
3535 /* genModbits :- modulus of bits */
3536 /*-----------------------------------------------------------------*/
3537 static void genModbits (operand *left,
3544 /* the result must be bit */
3545 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3546 l = aopGet(AOP(left),0,FALSE,FALSE);
3550 emitcode("div","ab");
3551 emitcode("mov","a,b");
3552 emitcode("rrc","a");
3553 aopPut(AOP(result),"c",0);
3556 /*-----------------------------------------------------------------*/
3557 /* genModOneByte : 8 bit modulus */
3558 /*-----------------------------------------------------------------*/
3559 static void genModOneByte (operand *left,
3563 sym_link *opetype = operandType(result);
3567 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3568 /* signed or unsigned */
3569 if (SPEC_USIGN(opetype)) {
3570 /* unsigned is easy */
3571 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3572 l = aopGet(AOP(left),0,FALSE,FALSE);
3574 emitcode("div","ab");
3575 aopPut(AOP(result),"b",0);
3579 /* signed is a little bit more difficult */
3581 /* save the signs of the operands */
3582 l = aopGet(AOP(left),0,FALSE,FALSE);
3585 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3586 emitcode("push","acc"); /* save it on the stack */
3588 /* now sign adjust for both left & right */
3589 l = aopGet(AOP(right),0,FALSE,FALSE);
3592 lbl = newiTempLabel(NULL);
3593 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3594 emitcode("cpl","a");
3595 emitcode("inc","a");
3596 emitcode("","%05d_DS_:",(lbl->key+100));
3597 emitcode("mov","b,a");
3599 /* sign adjust left side */
3600 l = aopGet(AOP(left),0,FALSE,FALSE);
3603 lbl = newiTempLabel(NULL);
3604 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3605 emitcode("cpl","a");
3606 emitcode("inc","a");
3607 emitcode("","%05d_DS_:",(lbl->key+100));
3609 /* now the multiplication */
3610 emitcode("div","ab");
3611 /* we are interested in the lower order
3613 lbl = newiTempLabel(NULL);
3614 emitcode("pop","acc");
3615 /* if there was an over flow we don't
3616 adjust the sign of the result */
3617 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3618 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3620 emitcode("clr","a");
3621 emitcode("subb","a,b");
3622 emitcode("mov","b,a");
3623 emitcode("","%05d_DS_:",(lbl->key+100));
3625 /* now we are done */
3626 aopPut(AOP(result),"b",0);
3630 /*-----------------------------------------------------------------*/
3631 /* genMod - generates code for division */
3632 /*-----------------------------------------------------------------*/
3633 static void genMod (iCode *ic)
3635 operand *left = IC_LEFT(ic);
3636 operand *right = IC_RIGHT(ic);
3637 operand *result= IC_RESULT(ic);
3639 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3640 /* assign the amsops */
3641 aopOp (left,ic,FALSE);
3642 aopOp (right,ic,FALSE);
3643 aopOp (result,ic,TRUE);
3645 /* special cases first */
3647 if (AOP_TYPE(left) == AOP_CRY &&
3648 AOP_TYPE(right)== AOP_CRY) {
3649 genModbits(left,right,result);
3653 /* if both are of size == 1 */
3654 if (AOP_SIZE(left) == 1 &&
3655 AOP_SIZE(right) == 1 ) {
3656 genModOneByte(left,right,result);
3660 /* should have been converted to function call */
3664 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3665 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3666 freeAsmop(result,NULL,ic,TRUE);
3669 /*-----------------------------------------------------------------*/
3670 /* genIfxJump :- will create a jump depending on the ifx */
3671 /*-----------------------------------------------------------------*/
3672 static void genIfxJump (iCode *ic, char *jval)
3675 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3676 /* if true label then we jump if condition
3678 if ( IC_TRUE(ic) ) {
3680 if(strcmp(jval,"a") == 0)
3682 else if (strcmp(jval,"c") == 0)
3685 emitcode("btfsc","(%s >> 3),(%s & 7)",jval,jval);
3687 emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3691 /* false label is present */
3692 if(strcmp(jval,"a") == 0)
3694 else if (strcmp(jval,"c") == 0)
3697 emitcode("btfss","(%s >> 3),(%s & 7)",jval,jval);
3699 emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3704 /* mark the icode as generated */
3708 /*-----------------------------------------------------------------*/
3710 /*-----------------------------------------------------------------*/
3711 static void genSkip(iCode *ifx,int status_bit)
3716 if ( IC_TRUE(ifx) ) {
3717 switch(status_bit) {
3727 emitcode("skpndc","");
3732 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3736 switch(status_bit) {
3747 emitcode("skpdc","");
3750 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3756 /*-----------------------------------------------------------------*/
3758 /*-----------------------------------------------------------------*/
3759 static void genSkipc(iCode *ifx, int condition)
3770 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3772 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3776 /*-----------------------------------------------------------------*/
3778 /*-----------------------------------------------------------------*/
3779 static void genSkipz(iCode *ifx, int condition)
3790 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3792 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3795 /*-----------------------------------------------------------------*/
3796 /* genCmp :- greater or less than comparison */
3797 /*-----------------------------------------------------------------*/
3798 static void genCmp (operand *left,operand *right,
3799 operand *result, iCode *ifx, int sign)
3801 int size, offset = 0 ;
3802 unsigned long lit = 0L,i = 0;
3804 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3805 /* if left & right are bit variables */
3806 if (AOP_TYPE(left) == AOP_CRY &&
3807 AOP_TYPE(right) == AOP_CRY ) {
3808 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3809 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3811 /* subtract right from left if at the
3812 end the carry flag is set then we know that
3813 left is greater than right */
3814 size = max(AOP_SIZE(left),AOP_SIZE(right));
3816 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3817 if((size == 1) && !sign &&
3818 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3819 symbol *lbl = newiTempLabel(NULL);
3820 emitcode("cjne","%s,%s,%05d_DS_",
3821 aopGet(AOP(left),offset,FALSE,FALSE),
3822 aopGet(AOP(right),offset,FALSE,FALSE),
3824 emitcode("","%05d_DS_:",lbl->key+100);
3827 if(AOP_TYPE(right) == AOP_LIT) {
3829 DEBUGemitcode(";right lit","%d",sign);
3831 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3834 i = (lit >> (size*8)) & 0xff;
3836 emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
3837 genSkipz(ifx,IC_TRUE(ifx) == NULL);
3839 emitcode("movlw","0x%x",i);
3840 emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
3841 genSkipc(ifx,IC_TRUE(ifx) == NULL);
3848 if(AOP_TYPE(left) == AOP_LIT) {
3850 DEBUGemitcode(";left lit","%d",sign);
3852 lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
3856 i = (lit >> (size*8)) & 0xff;
3858 emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3859 genSkipz(ifx,IC_TRUE(ifx) != NULL);
3860 } else if( i == 1 ) {
3861 emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3862 genSkipz(ifx,IC_TRUE(ifx) != NULL);
3865 emitcode("movlw","0x%x",i);
3866 emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
3867 genSkipc(ifx,IC_TRUE(ifx) != NULL);
3876 DEBUGemitcode(";sign","%d",sign);
3877 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3878 emitcode("subwf","%s,w",aopGet(AOP(left),offset++,FALSE,FALSE));
3882 /*if (AOP_TYPE(right) == AOP_LIT){
3883 unsigned long lit = (unsigned long)
3884 floatFromVal(AOP(right)->aopu.aop_lit);
3885 emitcode("subb","a,#0x%02x",
3886 0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
3888 emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3889 emitcode("xrl","b,#0x80");
3890 emitcode("subb","a,b");
3893 emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
3895 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3897 emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
3898 emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
3905 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
3908 /* if the result is used in the next
3909 ifx conditional branch then generate
3910 code a little differently */
3912 genIfxJump (ifx,"c");
3915 /* leave the result in acc */
3920 /*-----------------------------------------------------------------*/
3921 /* genCmpGt :- greater than comparison */
3922 /*-----------------------------------------------------------------*/
3923 static void genCmpGt (iCode *ic, iCode *ifx)
3925 operand *left, *right, *result;
3926 sym_link *letype , *retype;
3929 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3931 right= IC_RIGHT(ic);
3932 result = IC_RESULT(ic);
3934 letype = getSpec(operandType(left));
3935 retype =getSpec(operandType(right));
3936 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3937 /* assign the amsops */
3938 aopOp (left,ic,FALSE);
3939 aopOp (right,ic,FALSE);
3940 aopOp (result,ic,TRUE);
3942 genCmp(right, left, result, ifx, sign);
3944 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3945 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3946 freeAsmop(result,NULL,ic,TRUE);
3949 /*-----------------------------------------------------------------*/
3950 /* genCmpLt - less than comparisons */
3951 /*-----------------------------------------------------------------*/
3952 static void genCmpLt (iCode *ic, iCode *ifx)
3954 operand *left, *right, *result;
3955 sym_link *letype , *retype;
3958 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3960 right= IC_RIGHT(ic);
3961 result = IC_RESULT(ic);
3963 letype = getSpec(operandType(left));
3964 retype =getSpec(operandType(right));
3965 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
3967 /* assign the amsops */
3968 aopOp (left,ic,FALSE);
3969 aopOp (right,ic,FALSE);
3970 aopOp (result,ic,TRUE);
3972 genCmp(left, right, result, ifx, sign);
3974 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3975 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3976 freeAsmop(result,NULL,ic,TRUE);
3979 /*-----------------------------------------------------------------*/
3980 /* gencjneshort - compare and jump if not equal */
3981 /*-----------------------------------------------------------------*/
3982 static void gencjneshort(operand *left, operand *right, symbol *lbl)
3984 int size = max(AOP_SIZE(left),AOP_SIZE(right));
3986 unsigned long lit = 0L;
3988 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3989 /* if the left side is a literal or
3990 if the right is in a pointer register and left
3992 if ((AOP_TYPE(left) == AOP_LIT) ||
3993 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
3998 if(AOP_TYPE(right) == AOP_LIT)
3999 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4001 /* if the right side is a literal then anything goes */
4002 if (AOP_TYPE(right) == AOP_LIT &&
4003 AOP_TYPE(left) != AOP_DIR ) {
4006 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4007 emitcode("xorlw","0x%x",lit & 0xff);
4009 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4012 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4018 /* if the right side is in a register or in direct space or
4019 if the left is a pointer register & right is not */
4020 else if (AOP_TYPE(right) == AOP_REG ||
4021 AOP_TYPE(right) == AOP_DIR ||
4022 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4023 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4025 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4026 ( (lit & 0xff) != 0)) {
4027 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4028 emitcode("xorlw","0x%x",lit & 0xff);
4031 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4034 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4037 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4038 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4039 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4040 emitcode("jnz","%05d_DS_",lbl->key+100);
4042 emitcode("cjne","a,%s,%05d_DS_",
4043 aopGet(AOP(right),offset,FALSE,TRUE),
4049 /* right is a pointer reg need both a & b */
4051 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4053 emitcode("mov","b,%s",l);
4054 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4055 emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
4061 /*-----------------------------------------------------------------*/
4062 /* gencjne - compare and jump if not equal */
4063 /*-----------------------------------------------------------------*/
4064 static void gencjne(operand *left, operand *right, symbol *lbl)
4066 symbol *tlbl = newiTempLabel(NULL);
4068 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4069 gencjneshort(left, right, lbl);
4071 emitcode("mov","a,%s",one);
4072 emitcode("sjmp","%05d_DS_",tlbl->key+100);
4073 emitcode("","%05d_DS_:",lbl->key+100);
4074 emitcode("clr","a");
4075 emitcode("","%05d_DS_:",tlbl->key+100);
4079 /*-----------------------------------------------------------------*/
4080 /* genCmpEq - generates code for equal to */
4081 /*-----------------------------------------------------------------*/
4082 static void genCmpEq (iCode *ic, iCode *ifx)
4084 operand *left, *right, *result;
4085 unsigned long lit = 0L;
4088 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4090 DEBUGemitcode ("; ifx is non-null","");
4092 DEBUGemitcode ("; ifx is null","");
4094 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4095 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4096 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4098 size = max(AOP_SIZE(left),AOP_SIZE(right));
4100 /* if literal, literal on the right or
4101 if the right is in a pointer register and left
4103 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4104 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4105 operand *t = IC_RIGHT(ic);
4106 IC_RIGHT(ic) = IC_LEFT(ic);
4110 if(ifx && !AOP_SIZE(result)){
4112 /* if they are both bit variables */
4113 if (AOP_TYPE(left) == AOP_CRY &&
4114 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4115 if(AOP_TYPE(right) == AOP_LIT){
4116 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4118 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4119 emitcode("cpl","c");
4120 } else if(lit == 1L) {
4121 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4123 emitcode("clr","c");
4125 /* AOP_TYPE(right) == AOP_CRY */
4127 symbol *lbl = newiTempLabel(NULL);
4128 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4129 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4130 emitcode("cpl","c");
4131 emitcode("","%05d_DS_:",(lbl->key+100));
4133 /* if true label then we jump if condition
4135 tlbl = newiTempLabel(NULL);
4136 if ( IC_TRUE(ifx) ) {
4137 emitcode("jnc","%05d_DS_",tlbl->key+100);
4138 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4140 emitcode("jc","%05d_DS_",tlbl->key+100);
4141 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4143 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4146 /* They're not both bit variables. Is the right a literal? */
4147 if(AOP_TYPE(right) == AOP_LIT) {
4149 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4154 int h = (lit>>8) & 0xff;
4157 /* Check special cases for integers */
4158 switch(lit & 0xffff) {
4160 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4161 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4166 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4167 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4172 emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4173 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4178 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4179 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4184 emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4185 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4191 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4192 emitcode("xorlw","0x%x",l);
4193 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4196 } else if (l == 0) {
4197 emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4198 emitcode("xorlw","0x%x",h);
4199 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4203 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4204 emitcode("xorlw","0x%x",l);
4205 emitcode("movlw","0x%x",h);
4207 emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4223 switch(lit & 0xff) {
4225 if ( IC_TRUE(ifx) ) {
4226 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4228 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4230 emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4231 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4235 if ( IC_TRUE(ifx) ) {
4236 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4238 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4240 emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4241 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4245 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4247 emitcode("xorlw","0x%x",lit & 0xff);
4252 // emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4253 //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4258 } else if(AOP_TYPE(right) == AOP_CRY ) {
4259 /* we know the left is not a bit, but that the right is */
4260 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4262 emitcode("btfsc","(%s >> 3), (%s & 7)",
4263 AOP(right)->aopu.aop_dir,
4264 AOP(right)->aopu.aop_dir);
4266 emitcode("btfss","(%s >> 3), (%s & 7)",
4267 AOP(right)->aopu.aop_dir,
4268 AOP(right)->aopu.aop_dir);
4270 emitcode("xorlw","1");
4272 /* if the two are equal, then W will be 0 and the Z bit is set
4273 * we could test Z now, or go ahead and check the high order bytes if
4274 * the variable we're comparing is larger than a byte. */
4277 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4279 if ( IC_TRUE(ifx) ) {
4281 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4284 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4288 /* They're both variables that are larger than bits */
4291 tlbl = newiTempLabel(NULL);
4295 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4296 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4298 if ( IC_TRUE(ifx) ) {
4301 emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4304 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4308 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4312 if(s>1 && IC_TRUE(ifx))
4313 emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4316 /* mark the icode as generated */
4321 /* if they are both bit variables */
4322 if (AOP_TYPE(left) == AOP_CRY &&
4323 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4324 if(AOP_TYPE(right) == AOP_LIT){
4325 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4327 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4328 emitcode("cpl","c");
4329 } else if(lit == 1L) {
4330 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4332 emitcode("clr","c");
4334 /* AOP_TYPE(right) == AOP_CRY */
4336 symbol *lbl = newiTempLabel(NULL);
4337 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4338 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4339 emitcode("cpl","c");
4340 emitcode("","%05d_DS_:",(lbl->key+100));
4343 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4348 genIfxJump (ifx,"c");
4351 /* if the result is used in an arithmetic operation
4352 then put the result in place */
4355 gencjne(left,right,newiTempLabel(NULL));
4356 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4357 aopPut(AOP(result),"a",0);
4361 genIfxJump (ifx,"a");
4364 /* if the result is used in an arithmetic operation
4365 then put the result in place */
4366 if (AOP_TYPE(result) != AOP_CRY)
4368 /* leave the result in acc */
4372 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4373 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4374 freeAsmop(result,NULL,ic,TRUE);
4377 /*-----------------------------------------------------------------*/
4378 /* ifxForOp - returns the icode containing the ifx for operand */
4379 /*-----------------------------------------------------------------*/
4380 static iCode *ifxForOp ( operand *op, iCode *ic )
4382 /* if true symbol then needs to be assigned */
4383 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4384 if (IS_TRUE_SYMOP(op))
4387 /* if this has register type condition and
4388 the next instruction is ifx with the same operand
4389 and live to of the operand is upto the ifx only then */
4391 ic->next->op == IFX &&
4392 IC_COND(ic->next)->key == op->key &&
4393 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4398 /*-----------------------------------------------------------------*/
4399 /* genAndOp - for && operation */
4400 /*-----------------------------------------------------------------*/
4401 static void genAndOp (iCode *ic)
4403 operand *left,*right, *result;
4406 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4407 /* note here that && operations that are in an
4408 if statement are taken away by backPatchLabels
4409 only those used in arthmetic operations remain */
4410 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4411 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4412 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4414 /* if both are bit variables */
4415 if (AOP_TYPE(left) == AOP_CRY &&
4416 AOP_TYPE(right) == AOP_CRY ) {
4417 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4418 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4421 tlbl = newiTempLabel(NULL);
4423 emitcode("jz","%05d_DS_",tlbl->key+100);
4425 emitcode("","%05d_DS_:",tlbl->key+100);
4429 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4430 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4431 freeAsmop(result,NULL,ic,TRUE);
4435 /*-----------------------------------------------------------------*/
4436 /* genOrOp - for || operation */
4437 /*-----------------------------------------------------------------*/
4440 modified this code, but it doesn't appear to ever get called
4443 static void genOrOp (iCode *ic)
4445 operand *left,*right, *result;
4448 /* note here that || operations that are in an
4449 if statement are taken away by backPatchLabels
4450 only those used in arthmetic operations remain */
4451 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4452 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4453 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4454 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4456 /* if both are bit variables */
4457 if (AOP_TYPE(left) == AOP_CRY &&
4458 AOP_TYPE(right) == AOP_CRY ) {
4459 emitcode("clrc","");
4460 emitcode("btfss","(%s >> 3), (%s & 7)",
4461 AOP(left)->aopu.aop_dir,
4462 AOP(left)->aopu.aop_dir);
4463 emitcode("btfsc","(%s >> 3), (%s & 7)",
4464 AOP(right)->aopu.aop_dir,
4465 AOP(right)->aopu.aop_dir);
4466 emitcode("setc","");
4469 tlbl = newiTempLabel(NULL);
4472 emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4474 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4479 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4480 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4481 freeAsmop(result,NULL,ic,TRUE);
4484 /*-----------------------------------------------------------------*/
4485 /* isLiteralBit - test if lit == 2^n */
4486 /*-----------------------------------------------------------------*/
4487 static int isLiteralBit(unsigned long lit)
4489 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4490 0x100L,0x200L,0x400L,0x800L,
4491 0x1000L,0x2000L,0x4000L,0x8000L,
4492 0x10000L,0x20000L,0x40000L,0x80000L,
4493 0x100000L,0x200000L,0x400000L,0x800000L,
4494 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4495 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4498 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4499 for(idx = 0; idx < 32; idx++)
4505 /*-----------------------------------------------------------------*/
4506 /* continueIfTrue - */
4507 /*-----------------------------------------------------------------*/
4508 static void continueIfTrue (iCode *ic)
4510 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4512 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4516 /*-----------------------------------------------------------------*/
4518 /*-----------------------------------------------------------------*/
4519 static void jumpIfTrue (iCode *ic)
4521 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4523 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4527 /*-----------------------------------------------------------------*/
4528 /* jmpTrueOrFalse - */
4529 /*-----------------------------------------------------------------*/
4530 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4532 // ugly but optimized by peephole
4533 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4535 symbol *nlbl = newiTempLabel(NULL);
4536 emitcode("sjmp","%05d_DS_",nlbl->key+100);
4537 emitcode("","%05d_DS_:",tlbl->key+100);
4538 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4539 emitcode("","%05d_DS_:",nlbl->key+100);
4542 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4543 emitcode("","%05d_DS_:",tlbl->key+100);
4548 /*-----------------------------------------------------------------*/
4549 /* genAnd - code for and */
4550 /*-----------------------------------------------------------------*/
4551 static void genAnd (iCode *ic, iCode *ifx)
4553 operand *left, *right, *result;
4555 unsigned long lit = 0L;
4559 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4560 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4561 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4562 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4565 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4567 AOP_TYPE(left), AOP_TYPE(right));
4568 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4570 AOP_SIZE(left), AOP_SIZE(right));
4573 /* if left is a literal & right is not then exchange them */
4574 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4575 AOP_NEEDSACC(left)) {
4576 operand *tmp = right ;
4581 /* if result = right then exchange them */
4582 if(sameRegs(AOP(result),AOP(right))){
4583 operand *tmp = right ;
4588 /* if right is bit then exchange them */
4589 if (AOP_TYPE(right) == AOP_CRY &&
4590 AOP_TYPE(left) != AOP_CRY){
4591 operand *tmp = right ;
4595 if(AOP_TYPE(right) == AOP_LIT)
4596 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4598 size = AOP_SIZE(result);
4601 // result = bit & yy;
4602 if (AOP_TYPE(left) == AOP_CRY){
4603 // c = bit & literal;
4604 if(AOP_TYPE(right) == AOP_LIT){
4606 if(size && sameRegs(AOP(result),AOP(left)))
4609 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4612 if(size && (AOP_TYPE(result) == AOP_CRY)){
4613 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
4616 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4620 emitcode("clr","c");
4623 if (AOP_TYPE(right) == AOP_CRY){
4625 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4626 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4629 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
4631 emitcode("rrc","a");
4632 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
4640 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4641 genIfxJump(ifx, "c");
4645 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4646 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4647 if((AOP_TYPE(right) == AOP_LIT) &&
4648 (AOP_TYPE(result) == AOP_CRY) &&
4649 (AOP_TYPE(left) != AOP_CRY)){
4650 int posbit = isLiteralBit(lit);
4654 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
4657 emitcode("mov","c,acc.%d",posbit&0x07);
4661 sprintf(buffer,"acc.%d",posbit&0x07);
4662 genIfxJump(ifx, buffer);
4667 symbol *tlbl = newiTempLabel(NULL);
4668 int sizel = AOP_SIZE(left);
4670 emitcode("setb","c");
4672 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
4673 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
4675 if((posbit = isLiteralBit(bytelit)) != 0)
4676 emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
4678 if(bytelit != 0x0FFL)
4679 emitcode("anl","a,%s",
4680 aopGet(AOP(right),offset,FALSE,TRUE));
4681 emitcode("jnz","%05d_DS_",tlbl->key+100);
4686 // bit = left & literal
4688 emitcode("clr","c");
4689 emitcode("","%05d_DS_:",tlbl->key+100);
4691 // if(left & literal)
4694 jmpTrueOrFalse(ifx, tlbl);
4702 /* if left is same as result */
4703 if(sameRegs(AOP(result),AOP(left))){
4704 for(;size--; offset++,lit>>=8) {
4705 if(AOP_TYPE(right) == AOP_LIT){
4706 switch(lit & 0xff) {
4708 /* and'ing with 0 has clears the result */
4709 emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4712 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4717 int p = my_powof2( (~lit) & 0xff );
4719 /* only one bit is set in the literal, so use a bcf instruction */
4720 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4722 emitcode("movlw","0x%x", (lit & 0xff));
4723 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
4728 if (AOP_TYPE(left) == AOP_ACC)
4729 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4731 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4732 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4739 // left & result in different registers
4740 if(AOP_TYPE(result) == AOP_CRY){
4742 // if(size), result in bit
4743 // if(!size && ifx), conditional oper: if(left & right)
4744 symbol *tlbl = newiTempLabel(NULL);
4745 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
4747 emitcode("setb","c");
4749 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4750 emitcode("anl","a,%s",
4751 aopGet(AOP(left),offset,FALSE,FALSE));
4752 emitcode("jnz","%05d_DS_",tlbl->key+100);
4757 emitcode("","%05d_DS_:",tlbl->key+100);
4760 jmpTrueOrFalse(ifx, tlbl);
4762 for(;(size--);offset++) {
4764 // result = left & right
4765 if(AOP_TYPE(right) == AOP_LIT){
4766 int t = (lit >> (offset*8)) & 0x0FFL;
4769 emitcode("clrf","%s",
4770 aopGet(AOP(result),offset,FALSE,FALSE));
4773 emitcode("movf","%s,w",
4774 aopGet(AOP(left),offset,FALSE,FALSE));
4775 emitcode("movwf","%s",
4776 aopGet(AOP(result),offset,FALSE,FALSE));
4779 emitcode("movlw","0x%x",t);
4780 emitcode("andwf","%s,w",
4781 aopGet(AOP(left),offset,FALSE,FALSE));
4782 emitcode("movwf","%s",
4783 aopGet(AOP(result),offset,FALSE,FALSE));
4789 if (AOP_TYPE(left) == AOP_ACC)
4790 emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4792 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4793 emitcode("andwf","%s,w",
4794 aopGet(AOP(left),offset,FALSE,FALSE));
4796 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
4802 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4803 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4804 freeAsmop(result,NULL,ic,TRUE);
4807 /*-----------------------------------------------------------------*/
4808 /* genOr - code for or */
4809 /*-----------------------------------------------------------------*/
4810 static void genOr (iCode *ic, iCode *ifx)
4812 operand *left, *right, *result;
4814 unsigned long lit = 0L;
4816 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4818 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4819 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4820 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4823 /* if left is a literal & right is not then exchange them */
4824 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4825 AOP_NEEDSACC(left)) {
4826 operand *tmp = right ;
4831 /* if result = right then exchange them */
4832 if(sameRegs(AOP(result),AOP(right))){
4833 operand *tmp = right ;
4838 /* if right is bit then exchange them */
4839 if (AOP_TYPE(right) == AOP_CRY &&
4840 AOP_TYPE(left) != AOP_CRY){
4841 operand *tmp = right ;
4846 if(AOP_TYPE(right) == AOP_LIT)
4847 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4849 size = AOP_SIZE(result);
4853 if (AOP_TYPE(left) == AOP_CRY){
4854 if(AOP_TYPE(right) == AOP_LIT){
4855 // c = bit & literal;
4857 // lit != 0 => result = 1
4858 if(AOP_TYPE(result) == AOP_CRY){
4860 emitcode("bsf","(%s >> 3), (%s & 7)",
4861 AOP(result)->aopu.aop_dir,
4862 AOP(result)->aopu.aop_dir);
4864 continueIfTrue(ifx);
4867 emitcode(";XXXsetb","c %s,%d",__FILE__,__LINE__);
4869 // lit == 0 => result = left
4870 if(size && sameRegs(AOP(result),AOP(left)))
4872 emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
4875 if (AOP_TYPE(right) == AOP_CRY){
4876 if(sameRegs(AOP(result),AOP(left))){
4878 emitcode("bcf","(%s >> 3), (%s & 7)",
4879 AOP(result)->aopu.aop_dir,
4880 AOP(result)->aopu.aop_dir);
4881 emitcode("btfsc","(%s >> 3), (%s & 7)",
4882 AOP(right)->aopu.aop_dir,
4883 AOP(right)->aopu.aop_dir);
4884 emitcode("bsf","(%s >> 3), (%s & 7)",
4885 AOP(result)->aopu.aop_dir,
4886 AOP(result)->aopu.aop_dir);
4889 emitcode("bcf","(%s >> 3), (%s & 7)",
4890 AOP(result)->aopu.aop_dir,
4891 AOP(result)->aopu.aop_dir);
4892 emitcode("btfss","(%s >> 3), (%s & 7)",
4893 AOP(right)->aopu.aop_dir,
4894 AOP(right)->aopu.aop_dir);
4895 emitcode("btfsc","(%s >> 3), (%s & 7)",
4896 AOP(left)->aopu.aop_dir,
4897 AOP(left)->aopu.aop_dir);
4898 emitcode("bsf","(%s >> 3), (%s & 7)",
4899 AOP(result)->aopu.aop_dir,
4900 AOP(result)->aopu.aop_dir);
4905 symbol *tlbl = newiTempLabel(NULL);
4906 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4907 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
4908 emitcode(";XXX setb","c");
4909 emitcode(";XXX jb","%s,%05d_DS_",
4910 AOP(left)->aopu.aop_dir,tlbl->key+100);
4912 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4913 if((AOP_TYPE(result) == AOP_CRY) && ifx){
4914 jmpTrueOrFalse(ifx, tlbl);
4918 emitcode("","%05d_DS_:",tlbl->key+100);
4927 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
4928 genIfxJump(ifx, "c");
4932 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4933 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4934 if((AOP_TYPE(right) == AOP_LIT) &&
4935 (AOP_TYPE(result) == AOP_CRY) &&
4936 (AOP_TYPE(left) != AOP_CRY)){
4938 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4941 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
4943 continueIfTrue(ifx);
4946 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
4947 // lit = 0, result = boolean(left)
4949 emitcode(";XXX setb","c");
4952 symbol *tlbl = newiTempLabel(NULL);
4953 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
4955 emitcode("","%05d_DS_:",tlbl->key+100);
4957 genIfxJump (ifx,"a");
4965 /* if left is same as result */
4966 if(sameRegs(AOP(result),AOP(left))){
4967 for(;size--; offset++,lit>>=8) {
4968 if(AOP_TYPE(right) == AOP_LIT){
4969 if((lit & 0xff) == 0)
4970 /* or'ing with 0 has no effect */
4973 int p = my_powof2(lit & 0xff);
4975 /* only one bit is set in the literal, so use a bsf instruction */
4976 emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
4978 emitcode("movlw","0x%x", (lit & 0xff));
4979 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
4984 if (AOP_TYPE(left) == AOP_ACC)
4985 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4987 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4988 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4994 // left & result in different registers
4995 if(AOP_TYPE(result) == AOP_CRY){
4997 // if(size), result in bit
4998 // if(!size && ifx), conditional oper: if(left | right)
4999 symbol *tlbl = newiTempLabel(NULL);
5000 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5001 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5004 emitcode(";XXX setb","c");
5006 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5007 emitcode(";XXX orl","a,%s",
5008 aopGet(AOP(left),offset,FALSE,FALSE));
5009 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5014 emitcode("","%05d_DS_:",tlbl->key+100);
5017 jmpTrueOrFalse(ifx, tlbl);
5018 } else for(;(size--);offset++){
5020 // result = left & right
5021 if(AOP_TYPE(right) == AOP_LIT){
5022 int t = (lit >> (offset*8)) & 0x0FFL;
5025 emitcode("movf","%s,w",
5026 aopGet(AOP(left),offset,FALSE,FALSE));
5027 emitcode("movwf","%s",
5028 aopGet(AOP(result),offset,FALSE,FALSE));
5031 emitcode("movlw","0x%x",t);
5032 emitcode("iorwf","%s,w",
5033 aopGet(AOP(left),offset,FALSE,FALSE));
5034 emitcode("movwf","%s",
5035 aopGet(AOP(result),offset,FALSE,FALSE));
5041 // faster than result <- left, anl result,right
5042 // and better if result is SFR
5043 if (AOP_TYPE(left) == AOP_ACC)
5044 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5046 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5047 emitcode("iorwf","%s,w",
5048 aopGet(AOP(left),offset,FALSE,FALSE));
5050 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5055 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5056 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5057 freeAsmop(result,NULL,ic,TRUE);
5060 /*-----------------------------------------------------------------*/
5061 /* genXor - code for xclusive or */
5062 /*-----------------------------------------------------------------*/
5063 static void genXor (iCode *ic, iCode *ifx)
5065 operand *left, *right, *result;
5067 unsigned long lit = 0L;
5069 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5071 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5072 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5073 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5075 /* if left is a literal & right is not ||
5076 if left needs acc & right does not */
5077 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5078 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5079 operand *tmp = right ;
5084 /* if result = right then exchange them */
5085 if(sameRegs(AOP(result),AOP(right))){
5086 operand *tmp = right ;
5091 /* if right is bit then exchange them */
5092 if (AOP_TYPE(right) == AOP_CRY &&
5093 AOP_TYPE(left) != AOP_CRY){
5094 operand *tmp = right ;
5098 if(AOP_TYPE(right) == AOP_LIT)
5099 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5101 size = AOP_SIZE(result);
5105 if (AOP_TYPE(left) == AOP_CRY){
5106 if(AOP_TYPE(right) == AOP_LIT){
5107 // c = bit & literal;
5109 // lit>>1 != 0 => result = 1
5110 if(AOP_TYPE(result) == AOP_CRY){
5112 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5114 continueIfTrue(ifx);
5117 emitcode("setb","c");
5121 // lit == 0, result = left
5122 if(size && sameRegs(AOP(result),AOP(left)))
5124 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5126 // lit == 1, result = not(left)
5127 if(size && sameRegs(AOP(result),AOP(left))){
5128 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5131 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5132 emitcode("cpl","c");
5139 symbol *tlbl = newiTempLabel(NULL);
5140 if (AOP_TYPE(right) == AOP_CRY){
5142 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5145 int sizer = AOP_SIZE(right);
5147 // if val>>1 != 0, result = 1
5148 emitcode("setb","c");
5150 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5152 // test the msb of the lsb
5153 emitcode("anl","a,#0xfe");
5154 emitcode("jnz","%05d_DS_",tlbl->key+100);
5158 emitcode("rrc","a");
5160 emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5161 emitcode("cpl","c");
5162 emitcode("","%05d_DS_:",(tlbl->key+100));
5169 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5170 genIfxJump(ifx, "c");
5174 if(sameRegs(AOP(result),AOP(left))){
5175 /* if left is same as result */
5176 for(;size--; offset++) {
5177 if(AOP_TYPE(right) == AOP_LIT){
5178 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5181 if (IS_AOP_PREG(left)) {
5182 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5183 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5184 aopPut(AOP(result),"a",offset);
5186 emitcode("xrl","%s,%s",
5187 aopGet(AOP(left),offset,FALSE,TRUE),
5188 aopGet(AOP(right),offset,FALSE,FALSE));
5190 if (AOP_TYPE(left) == AOP_ACC)
5191 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5193 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5194 if (IS_AOP_PREG(left)) {
5195 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5196 aopPut(AOP(result),"a",offset);
5198 emitcode("xrl","%s,a",
5199 aopGet(AOP(left),offset,FALSE,TRUE));
5204 // left & result in different registers
5205 if(AOP_TYPE(result) == AOP_CRY){
5207 // if(size), result in bit
5208 // if(!size && ifx), conditional oper: if(left ^ right)
5209 symbol *tlbl = newiTempLabel(NULL);
5210 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5212 emitcode("setb","c");
5214 if((AOP_TYPE(right) == AOP_LIT) &&
5215 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5216 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5218 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5219 emitcode("xrl","a,%s",
5220 aopGet(AOP(left),offset,FALSE,FALSE));
5222 emitcode("jnz","%05d_DS_",tlbl->key+100);
5227 emitcode("","%05d_DS_:",tlbl->key+100);
5230 jmpTrueOrFalse(ifx, tlbl);
5231 } else for(;(size--);offset++){
5233 // result = left & right
5234 if(AOP_TYPE(right) == AOP_LIT){
5235 int t = (lit >> (offset*8)) & 0x0FFL;
5238 emitcode("movf","%s,w",
5239 aopGet(AOP(left),offset,FALSE,FALSE));
5240 emitcode("movwf","%s",
5241 aopGet(AOP(result),offset,FALSE,FALSE));
5244 emitcode("comf","%s,w",
5245 aopGet(AOP(left),offset,FALSE,FALSE));
5246 emitcode("movwf","%s",
5247 aopGet(AOP(result),offset,FALSE,FALSE));
5250 emitcode("movlw","0x%x",t);
5251 emitcode("xorwf","%s,w",
5252 aopGet(AOP(left),offset,FALSE,FALSE));
5253 emitcode("movwf","%s",
5254 aopGet(AOP(result),offset,FALSE,FALSE));
5260 // faster than result <- left, anl result,right
5261 // and better if result is SFR
5262 if (AOP_TYPE(left) == AOP_ACC)
5263 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5265 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5266 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5268 if ( AOP_TYPE(result) != AOP_ACC)
5269 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5274 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5275 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5276 freeAsmop(result,NULL,ic,TRUE);
5279 /*-----------------------------------------------------------------*/
5280 /* genInline - write the inline code out */
5281 /*-----------------------------------------------------------------*/
5282 static void genInline (iCode *ic)
5284 char buffer[MAX_INLINEASM];
5288 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5290 _G.inLine += (!options.asmpeep);
5291 strcpy(buffer,IC_INLINE(ic));
5293 /* emit each line as a code */
5312 /* emitcode("",buffer); */
5313 _G.inLine -= (!options.asmpeep);
5316 /*-----------------------------------------------------------------*/
5317 /* genRRC - rotate right with carry */
5318 /*-----------------------------------------------------------------*/
5319 static void genRRC (iCode *ic)
5321 operand *left , *result ;
5322 int size, offset = 0;
5325 /* rotate right with carry */
5327 result=IC_RESULT(ic);
5328 aopOp (left,ic,FALSE);
5329 aopOp (result,ic,FALSE);
5331 /* move it to the result */
5332 size = AOP_SIZE(result);
5336 l = aopGet(AOP(left),offset,FALSE,FALSE);
5338 emitcode("rrc","a");
5339 if (AOP_SIZE(result) > 1)
5340 aopPut(AOP(result),"a",offset--);
5342 /* now we need to put the carry into the
5343 highest order byte of the result */
5344 if (AOP_SIZE(result) > 1) {
5345 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5348 emitcode("mov","acc.7,c");
5349 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5350 freeAsmop(left,NULL,ic,TRUE);
5351 freeAsmop(result,NULL,ic,TRUE);
5354 /*-----------------------------------------------------------------*/
5355 /* genRLC - generate code for rotate left with carry */
5356 /*-----------------------------------------------------------------*/
5357 static void genRLC (iCode *ic)
5359 operand *left , *result ;
5360 int size, offset = 0;
5363 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5364 /* rotate right with carry */
5366 result=IC_RESULT(ic);
5367 aopOp (left,ic,FALSE);
5368 aopOp (result,ic,FALSE);
5370 /* move it to the result */
5371 size = AOP_SIZE(result);
5374 l = aopGet(AOP(left),offset,FALSE,FALSE);
5376 emitcode("add","a,acc");
5377 if (AOP_SIZE(result) > 1)
5378 aopPut(AOP(result),"a",offset++);
5380 l = aopGet(AOP(left),offset,FALSE,FALSE);
5382 emitcode("rlc","a");
5383 if (AOP_SIZE(result) > 1)
5384 aopPut(AOP(result),"a",offset++);
5387 /* now we need to put the carry into the
5388 highest order byte of the result */
5389 if (AOP_SIZE(result) > 1) {
5390 l = aopGet(AOP(result),0,FALSE,FALSE);
5393 emitcode("mov","acc.0,c");
5394 aopPut(AOP(result),"a",0);
5395 freeAsmop(left,NULL,ic,TRUE);
5396 freeAsmop(result,NULL,ic,TRUE);
5399 /*-----------------------------------------------------------------*/
5400 /* genGetHbit - generates code get highest order bit */
5401 /*-----------------------------------------------------------------*/
5402 static void genGetHbit (iCode *ic)
5404 operand *left, *result;
5406 result=IC_RESULT(ic);
5407 aopOp (left,ic,FALSE);
5408 aopOp (result,ic,FALSE);
5410 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5411 /* get the highest order byte into a */
5412 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5413 if(AOP_TYPE(result) == AOP_CRY){
5414 emitcode("rlc","a");
5419 emitcode("anl","a,#0x01");
5424 freeAsmop(left,NULL,ic,TRUE);
5425 freeAsmop(result,NULL,ic,TRUE);
5428 /*-----------------------------------------------------------------*/
5429 /* AccRol - rotate left accumulator by known count */
5430 /*-----------------------------------------------------------------*/
5431 static void AccRol (int shCount)
5433 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5434 shCount &= 0x0007; // shCount : 0..7
5446 emitcode("swap","a");
5450 emitcode("swap","a");
5453 emitcode("swap","a");
5466 /*-----------------------------------------------------------------*/
5467 /* AccLsh - left shift accumulator by known count */
5468 /*-----------------------------------------------------------------*/
5469 static void AccLsh (int shCount)
5471 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5474 emitcode("add","a,acc");
5477 emitcode("add","a,acc");
5478 emitcode("add","a,acc");
5480 /* rotate left accumulator */
5482 /* and kill the lower order bits */
5483 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5488 /*-----------------------------------------------------------------*/
5489 /* AccRsh - right shift accumulator by known count */
5490 /*-----------------------------------------------------------------*/
5491 static void AccRsh (int shCount)
5493 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5497 emitcode("rrc","a");
5499 /* rotate right accumulator */
5500 AccRol(8 - shCount);
5501 /* and kill the higher order bits */
5502 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5507 /*-----------------------------------------------------------------*/
5508 /* AccSRsh - signed right shift accumulator by known count */
5509 /*-----------------------------------------------------------------*/
5510 static void AccSRsh (int shCount)
5513 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5516 emitcode("mov","c,acc.7");
5517 emitcode("rrc","a");
5518 } else if(shCount == 2){
5519 emitcode("mov","c,acc.7");
5520 emitcode("rrc","a");
5521 emitcode("mov","c,acc.7");
5522 emitcode("rrc","a");
5524 tlbl = newiTempLabel(NULL);
5525 /* rotate right accumulator */
5526 AccRol(8 - shCount);
5527 /* and kill the higher order bits */
5528 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5529 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5530 emitcode("orl","a,#0x%02x",
5531 (unsigned char)~SRMask[shCount]);
5532 emitcode("","%05d_DS_:",tlbl->key+100);
5537 /*-----------------------------------------------------------------*/
5538 /* shiftR1Left2Result - shift right one byte from left to result */
5539 /*-----------------------------------------------------------------*/
5540 static void shiftR1Left2Result (operand *left, int offl,
5541 operand *result, int offr,
5542 int shCount, int sign)
5544 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5545 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5546 /* shift right accumulator */
5551 aopPut(AOP(result),"a",offr);
5554 /*-----------------------------------------------------------------*/
5555 /* shiftL1Left2Result - shift left one byte from left to result */
5556 /*-----------------------------------------------------------------*/
5557 static void shiftL1Left2Result (operand *left, int offl,
5558 operand *result, int offr, int shCount)
5561 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5562 l = aopGet(AOP(left),offl,FALSE,FALSE);
5564 /* shift left accumulator */
5566 aopPut(AOP(result),"a",offr);
5569 /*-----------------------------------------------------------------*/
5570 /* movLeft2Result - move byte from left to result */
5571 /*-----------------------------------------------------------------*/
5572 static void movLeft2Result (operand *left, int offl,
5573 operand *result, int offr, int sign)
5576 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5577 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
5578 l = aopGet(AOP(left),offl,FALSE,FALSE);
5580 if (*l == '@' && (IS_AOP_PREG(result))) {
5581 emitcode("mov","a,%s",l);
5582 aopPut(AOP(result),"a",offr);
5585 aopPut(AOP(result),l,offr);
5587 /* MSB sign in acc.7 ! */
5588 if(getDataSize(left) == offl+1){
5589 emitcode("mov","a,%s",l);
5590 aopPut(AOP(result),"a",offr);
5597 /*-----------------------------------------------------------------*/
5598 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5599 /*-----------------------------------------------------------------*/
5600 static void AccAXRrl1 (char *x)
5602 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5603 emitcode("rrc","a");
5604 emitcode("xch","a,%s", x);
5605 emitcode("rrc","a");
5606 emitcode("xch","a,%s", x);
5609 /*-----------------------------------------------------------------*/
5610 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5611 /*-----------------------------------------------------------------*/
5612 static void AccAXLrl1 (char *x)
5614 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5615 emitcode("xch","a,%s",x);
5616 emitcode("rlc","a");
5617 emitcode("xch","a,%s",x);
5618 emitcode("rlc","a");
5621 /*-----------------------------------------------------------------*/
5622 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5623 /*-----------------------------------------------------------------*/
5624 static void AccAXLsh1 (char *x)
5626 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5627 emitcode("xch","a,%s",x);
5628 emitcode("add","a,acc");
5629 emitcode("xch","a,%s",x);
5630 emitcode("rlc","a");
5633 /*-----------------------------------------------------------------*/
5634 /* AccAXLsh - left shift a:x by known count (0..7) */
5635 /*-----------------------------------------------------------------*/
5636 static void AccAXLsh (char *x, int shCount)
5638 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5651 case 5 : // AAAAABBB:CCCCCDDD
5652 AccRol(shCount); // BBBAAAAA:CCCCCDDD
5653 emitcode("anl","a,#0x%02x",
5654 SLMask[shCount]); // BBB00000:CCCCCDDD
5655 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
5656 AccRol(shCount); // DDDCCCCC:BBB00000
5657 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
5658 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
5659 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
5660 emitcode("anl","a,#0x%02x",
5661 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5662 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
5663 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
5665 case 6 : // AAAAAABB:CCCCCCDD
5666 emitcode("anl","a,#0x%02x",
5667 SRMask[shCount]); // 000000BB:CCCCCCDD
5668 emitcode("mov","c,acc.0"); // c = B
5669 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
5670 AccAXRrl1(x); // BCCCCCCD:D000000B
5671 AccAXRrl1(x); // BBCCCCCC:DD000000
5673 case 7 : // a:x <<= 7
5674 emitcode("anl","a,#0x%02x",
5675 SRMask[shCount]); // 0000000B:CCCCCCCD
5676 emitcode("mov","c,acc.0"); // c = B
5677 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
5678 AccAXRrl1(x); // BCCCCCCC:D0000000
5685 /*-----------------------------------------------------------------*/
5686 /* AccAXRsh - right shift a:x known count (0..7) */
5687 /*-----------------------------------------------------------------*/
5688 static void AccAXRsh (char *x, int shCount)
5690 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5696 AccAXRrl1(x); // 0->a:x
5700 AccAXRrl1(x); // 0->a:x
5702 AccAXRrl1(x); // 0->a:x
5706 case 5 : // AAAAABBB:CCCCCDDD = a:x
5707 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
5708 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5709 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5710 emitcode("anl","a,#0x%02x",
5711 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5712 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5713 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5714 emitcode("anl","a,#0x%02x",
5715 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5716 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5717 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5718 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
5720 case 6 : // AABBBBBB:CCDDDDDD
5721 emitcode("mov","c,acc.7");
5722 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5723 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5724 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5725 emitcode("anl","a,#0x%02x",
5726 SRMask[shCount]); // 000000AA:BBBBBBCC
5728 case 7 : // ABBBBBBB:CDDDDDDD
5729 emitcode("mov","c,acc.7"); // c = A
5730 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5731 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5732 emitcode("anl","a,#0x%02x",
5733 SRMask[shCount]); // 0000000A:BBBBBBBC
5740 /*-----------------------------------------------------------------*/
5741 /* AccAXRshS - right shift signed a:x known count (0..7) */
5742 /*-----------------------------------------------------------------*/
5743 static void AccAXRshS (char *x, int shCount)
5746 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5751 emitcode("mov","c,acc.7");
5752 AccAXRrl1(x); // s->a:x
5755 emitcode("mov","c,acc.7");
5756 AccAXRrl1(x); // s->a:x
5757 emitcode("mov","c,acc.7");
5758 AccAXRrl1(x); // s->a:x
5762 case 5 : // AAAAABBB:CCCCCDDD = a:x
5763 tlbl = newiTempLabel(NULL);
5764 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
5765 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
5766 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
5767 emitcode("anl","a,#0x%02x",
5768 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5769 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
5770 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5771 emitcode("anl","a,#0x%02x",
5772 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5773 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
5774 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
5775 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
5776 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5777 emitcode("orl","a,#0x%02x",
5778 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5779 emitcode("","%05d_DS_:",tlbl->key+100);
5780 break; // SSSSAAAA:BBBCCCCC
5781 case 6 : // AABBBBBB:CCDDDDDD
5782 tlbl = newiTempLabel(NULL);
5783 emitcode("mov","c,acc.7");
5784 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
5785 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
5786 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
5787 emitcode("anl","a,#0x%02x",
5788 SRMask[shCount]); // 000000AA:BBBBBBCC
5789 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5790 emitcode("orl","a,#0x%02x",
5791 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
5792 emitcode("","%05d_DS_:",tlbl->key+100);
5794 case 7 : // ABBBBBBB:CDDDDDDD
5795 tlbl = newiTempLabel(NULL);
5796 emitcode("mov","c,acc.7"); // c = A
5797 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
5798 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
5799 emitcode("anl","a,#0x%02x",
5800 SRMask[shCount]); // 0000000A:BBBBBBBC
5801 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5802 emitcode("orl","a,#0x%02x",
5803 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
5804 emitcode("","%05d_DS_:",tlbl->key+100);
5811 /*-----------------------------------------------------------------*/
5812 /* shiftL2Left2Result - shift left two bytes from left to result */
5813 /*-----------------------------------------------------------------*/
5814 static void shiftL2Left2Result (operand *left, int offl,
5815 operand *result, int offr, int shCount)
5817 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5818 if(sameRegs(AOP(result), AOP(left)) &&
5819 ((offl + MSB16) == offr)){
5820 /* don't crash result[offr] */
5821 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5822 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5824 movLeft2Result(left,offl, result, offr, 0);
5825 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5827 /* ax << shCount (x = lsb(result))*/
5828 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5829 aopPut(AOP(result),"a",offr+MSB16);
5833 /*-----------------------------------------------------------------*/
5834 /* shiftR2Left2Result - shift right two bytes from left to result */
5835 /*-----------------------------------------------------------------*/
5836 static void shiftR2Left2Result (operand *left, int offl,
5837 operand *result, int offr,
5838 int shCount, int sign)
5840 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5841 if(sameRegs(AOP(result), AOP(left)) &&
5842 ((offl + MSB16) == offr)){
5843 /* don't crash result[offr] */
5844 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5845 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5847 movLeft2Result(left,offl, result, offr, 0);
5848 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
5850 /* a:x >> shCount (x = lsb(result))*/
5852 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5854 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
5855 if(getDataSize(result) > 1)
5856 aopPut(AOP(result),"a",offr+MSB16);
5859 /*-----------------------------------------------------------------*/
5860 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
5861 /*-----------------------------------------------------------------*/
5862 static void shiftLLeftOrResult (operand *left, int offl,
5863 operand *result, int offr, int shCount)
5865 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5866 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5867 /* shift left accumulator */
5869 /* or with result */
5870 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5871 /* back to result */
5872 aopPut(AOP(result),"a",offr);
5875 /*-----------------------------------------------------------------*/
5876 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
5877 /*-----------------------------------------------------------------*/
5878 static void shiftRLeftOrResult (operand *left, int offl,
5879 operand *result, int offr, int shCount)
5881 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5882 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5883 /* shift right accumulator */
5885 /* or with result */
5886 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
5887 /* back to result */
5888 aopPut(AOP(result),"a",offr);
5891 /*-----------------------------------------------------------------*/
5892 /* genlshOne - left shift a one byte quantity by known count */
5893 /*-----------------------------------------------------------------*/
5894 static void genlshOne (operand *result, operand *left, int shCount)
5896 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5897 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5900 /*-----------------------------------------------------------------*/
5901 /* genlshTwo - left shift two bytes by known amount != 0 */
5902 /*-----------------------------------------------------------------*/
5903 static void genlshTwo (operand *result,operand *left, int shCount)
5907 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5908 size = getDataSize(result);
5910 /* if shCount >= 8 */
5916 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
5918 movLeft2Result(left, LSB, result, MSB16, 0);
5920 aopPut(AOP(result),zero,LSB);
5923 /* 1 <= shCount <= 7 */
5926 shiftL1Left2Result(left, LSB, result, LSB, shCount);
5928 shiftL2Left2Result(left, LSB, result, LSB, shCount);
5932 /*-----------------------------------------------------------------*/
5933 /* shiftLLong - shift left one long from left to result */
5934 /* offl = LSB or MSB16 */
5935 /*-----------------------------------------------------------------*/
5936 static void shiftLLong (operand *left, operand *result, int offr )
5939 int size = AOP_SIZE(result);
5941 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5942 if(size >= LSB+offr){
5943 l = aopGet(AOP(left),LSB,FALSE,FALSE);
5945 emitcode("add","a,acc");
5946 if (sameRegs(AOP(left),AOP(result)) &&
5947 size >= MSB16+offr && offr != LSB )
5948 emitcode("xch","a,%s",
5949 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
5951 aopPut(AOP(result),"a",LSB+offr);
5954 if(size >= MSB16+offr){
5955 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
5956 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
5959 emitcode("rlc","a");
5960 if (sameRegs(AOP(left),AOP(result)) &&
5961 size >= MSB24+offr && offr != LSB)
5962 emitcode("xch","a,%s",
5963 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
5965 aopPut(AOP(result),"a",MSB16+offr);
5968 if(size >= MSB24+offr){
5969 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
5970 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
5973 emitcode("rlc","a");
5974 if (sameRegs(AOP(left),AOP(result)) &&
5975 size >= MSB32+offr && offr != LSB )
5976 emitcode("xch","a,%s",
5977 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
5979 aopPut(AOP(result),"a",MSB24+offr);
5982 if(size > MSB32+offr){
5983 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
5984 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
5987 emitcode("rlc","a");
5988 aopPut(AOP(result),"a",MSB32+offr);
5991 aopPut(AOP(result),zero,LSB);
5994 /*-----------------------------------------------------------------*/
5995 /* genlshFour - shift four byte by a known amount != 0 */
5996 /*-----------------------------------------------------------------*/
5997 static void genlshFour (operand *result, operand *left, int shCount)
6001 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6002 size = AOP_SIZE(result);
6004 /* if shifting more that 3 bytes */
6005 if (shCount >= 24 ) {
6008 /* lowest order of left goes to the highest
6009 order of the destination */
6010 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6012 movLeft2Result(left, LSB, result, MSB32, 0);
6013 aopPut(AOP(result),zero,LSB);
6014 aopPut(AOP(result),zero,MSB16);
6015 aopPut(AOP(result),zero,MSB32);
6019 /* more than two bytes */
6020 else if ( shCount >= 16 ) {
6021 /* lower order two bytes goes to higher order two bytes */
6023 /* if some more remaining */
6025 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6027 movLeft2Result(left, MSB16, result, MSB32, 0);
6028 movLeft2Result(left, LSB, result, MSB24, 0);
6030 aopPut(AOP(result),zero,MSB16);
6031 aopPut(AOP(result),zero,LSB);
6035 /* if more than 1 byte */
6036 else if ( shCount >= 8 ) {
6037 /* lower order three bytes goes to higher order three bytes */
6041 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6043 movLeft2Result(left, LSB, result, MSB16, 0);
6045 else{ /* size = 4 */
6047 movLeft2Result(left, MSB24, result, MSB32, 0);
6048 movLeft2Result(left, MSB16, result, MSB24, 0);
6049 movLeft2Result(left, LSB, result, MSB16, 0);
6050 aopPut(AOP(result),zero,LSB);
6052 else if(shCount == 1)
6053 shiftLLong(left, result, MSB16);
6055 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6056 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6057 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6058 aopPut(AOP(result),zero,LSB);
6063 /* 1 <= shCount <= 7 */
6064 else if(shCount <= 2){
6065 shiftLLong(left, result, LSB);
6067 shiftLLong(result, result, LSB);
6069 /* 3 <= shCount <= 7, optimize */
6071 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6072 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6073 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6077 /*-----------------------------------------------------------------*/
6078 /* genLeftShiftLiteral - left shifting by known count */
6079 /*-----------------------------------------------------------------*/
6080 static void genLeftShiftLiteral (operand *left,
6085 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6088 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6089 freeAsmop(right,NULL,ic,TRUE);
6091 aopOp(left,ic,FALSE);
6092 aopOp(result,ic,FALSE);
6094 size = getSize(operandType(result));
6097 emitcode("; shift left ","result %d, left %d",size,
6101 /* I suppose that the left size >= result size */
6104 movLeft2Result(left, size, result, size, 0);
6108 else if(shCount >= (size * 8))
6110 aopPut(AOP(result),zero,size);
6114 genlshOne (result,left,shCount);
6119 genlshTwo (result,left,shCount);
6123 genlshFour (result,left,shCount);
6127 freeAsmop(left,NULL,ic,TRUE);
6128 freeAsmop(result,NULL,ic,TRUE);
6131 /*-----------------------------------------------------------------*/
6132 /* genLeftShift - generates code for left shifting */
6133 /*-----------------------------------------------------------------*/
6134 static void genLeftShift (iCode *ic)
6136 operand *left,*right, *result;
6139 symbol *tlbl , *tlbl1;
6141 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6143 right = IC_RIGHT(ic);
6145 result = IC_RESULT(ic);
6147 aopOp(right,ic,FALSE);
6149 /* if the shift count is known then do it
6150 as efficiently as possible */
6151 if (AOP_TYPE(right) == AOP_LIT) {
6152 genLeftShiftLiteral (left,right,result,ic);
6156 /* shift count is unknown then we have to form
6157 a loop get the loop count in B : Note: we take
6158 only the lower order byte since shifting
6159 more that 32 bits make no sense anyway, ( the
6160 largest size of an object can be only 32 bits ) */
6162 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6163 emitcode("inc","b");
6164 freeAsmop (right,NULL,ic,TRUE);
6165 aopOp(left,ic,FALSE);
6166 aopOp(result,ic,FALSE);
6168 /* now move the left to the result if they are not the
6170 if (!sameRegs(AOP(left),AOP(result)) &&
6171 AOP_SIZE(result) > 1) {
6173 size = AOP_SIZE(result);
6176 l = aopGet(AOP(left),offset,FALSE,TRUE);
6177 if (*l == '@' && (IS_AOP_PREG(result))) {
6179 emitcode("mov","a,%s",l);
6180 aopPut(AOP(result),"a",offset);
6182 aopPut(AOP(result),l,offset);
6187 tlbl = newiTempLabel(NULL);
6188 size = AOP_SIZE(result);
6190 tlbl1 = newiTempLabel(NULL);
6192 /* if it is only one byte then */
6194 symbol *tlbl1 = newiTempLabel(NULL);
6196 l = aopGet(AOP(left),0,FALSE,FALSE);
6198 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6199 emitcode("","%05d_DS_:",tlbl->key+100);
6200 emitcode("add","a,acc");
6201 emitcode("","%05d_DS_:",tlbl1->key+100);
6202 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6203 aopPut(AOP(result),"a",0);
6207 reAdjustPreg(AOP(result));
6209 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6210 emitcode("","%05d_DS_:",tlbl->key+100);
6211 l = aopGet(AOP(result),offset,FALSE,FALSE);
6213 emitcode("add","a,acc");
6214 aopPut(AOP(result),"a",offset++);
6216 l = aopGet(AOP(result),offset,FALSE,FALSE);
6218 emitcode("rlc","a");
6219 aopPut(AOP(result),"a",offset++);
6221 reAdjustPreg(AOP(result));
6223 emitcode("","%05d_DS_:",tlbl1->key+100);
6224 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6226 freeAsmop(left,NULL,ic,TRUE);
6227 freeAsmop(result,NULL,ic,TRUE);
6230 /*-----------------------------------------------------------------*/
6231 /* genrshOne - right shift a one byte quantity by known count */
6232 /*-----------------------------------------------------------------*/
6233 static void genrshOne (operand *result, operand *left,
6234 int shCount, int sign)
6236 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6237 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6240 /*-----------------------------------------------------------------*/
6241 /* genrshTwo - right shift two bytes by known amount != 0 */
6242 /*-----------------------------------------------------------------*/
6243 static void genrshTwo (operand *result,operand *left,
6244 int shCount, int sign)
6246 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6247 /* if shCount >= 8 */
6251 shiftR1Left2Result(left, MSB16, result, LSB,
6254 movLeft2Result(left, MSB16, result, LSB, sign);
6255 addSign(result, MSB16, sign);
6258 /* 1 <= shCount <= 7 */
6260 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6263 /*-----------------------------------------------------------------*/
6264 /* shiftRLong - shift right one long from left to result */
6265 /* offl = LSB or MSB16 */
6266 /*-----------------------------------------------------------------*/
6267 static void shiftRLong (operand *left, int offl,
6268 operand *result, int sign)
6270 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6272 emitcode("clr","c");
6273 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6275 emitcode("mov","c,acc.7");
6276 emitcode("rrc","a");
6277 aopPut(AOP(result),"a",MSB32-offl);
6279 /* add sign of "a" */
6280 addSign(result, MSB32, sign);
6282 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6283 emitcode("rrc","a");
6284 aopPut(AOP(result),"a",MSB24-offl);
6286 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6287 emitcode("rrc","a");
6288 aopPut(AOP(result),"a",MSB16-offl);
6291 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6292 emitcode("rrc","a");
6293 aopPut(AOP(result),"a",LSB);
6297 /*-----------------------------------------------------------------*/
6298 /* genrshFour - shift four byte by a known amount != 0 */
6299 /*-----------------------------------------------------------------*/
6300 static void genrshFour (operand *result, operand *left,
6301 int shCount, int sign)
6303 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6304 /* if shifting more that 3 bytes */
6305 if(shCount >= 24 ) {
6308 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6310 movLeft2Result(left, MSB32, result, LSB, sign);
6311 addSign(result, MSB16, sign);
6313 else if(shCount >= 16){
6316 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6318 movLeft2Result(left, MSB24, result, LSB, 0);
6319 movLeft2Result(left, MSB32, result, MSB16, sign);
6321 addSign(result, MSB24, sign);
6323 else if(shCount >= 8){
6326 shiftRLong(left, MSB16, result, sign);
6327 else if(shCount == 0){
6328 movLeft2Result(left, MSB16, result, LSB, 0);
6329 movLeft2Result(left, MSB24, result, MSB16, 0);
6330 movLeft2Result(left, MSB32, result, MSB24, sign);
6331 addSign(result, MSB32, sign);
6334 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6335 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6336 /* the last shift is signed */
6337 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6338 addSign(result, MSB32, sign);
6341 else{ /* 1 <= shCount <= 7 */
6343 shiftRLong(left, LSB, result, sign);
6345 shiftRLong(result, LSB, result, sign);
6348 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6349 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6350 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6355 /*-----------------------------------------------------------------*/
6356 /* genRightShiftLiteral - right shifting by known count */
6357 /*-----------------------------------------------------------------*/
6358 static void genRightShiftLiteral (operand *left,
6364 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6367 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6368 freeAsmop(right,NULL,ic,TRUE);
6370 aopOp(left,ic,FALSE);
6371 aopOp(result,ic,FALSE);
6374 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6378 size = getDataSize(left);
6379 /* test the LEFT size !!! */
6381 /* I suppose that the left size >= result size */
6383 size = getDataSize(result);
6385 movLeft2Result(left, size, result, size, 0);
6388 else if(shCount >= (size * 8)){
6390 /* get sign in acc.7 */
6391 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6392 addSign(result, LSB, sign);
6396 genrshOne (result,left,shCount,sign);
6400 genrshTwo (result,left,shCount,sign);
6404 genrshFour (result,left,shCount,sign);
6410 freeAsmop(left,NULL,ic,TRUE);
6411 freeAsmop(result,NULL,ic,TRUE);
6415 /*-----------------------------------------------------------------*/
6416 /* genSignedRightShift - right shift of signed number */
6417 /*-----------------------------------------------------------------*/
6418 static void genSignedRightShift (iCode *ic)
6420 operand *right, *left, *result;
6423 symbol *tlbl, *tlbl1 ;
6425 /* we do it the hard way put the shift count in b
6426 and loop thru preserving the sign */
6427 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6429 right = IC_RIGHT(ic);
6431 result = IC_RESULT(ic);
6433 aopOp(right,ic,FALSE);
6436 if ( AOP_TYPE(right) == AOP_LIT) {
6437 genRightShiftLiteral (left,right,result,ic,1);
6440 /* shift count is unknown then we have to form
6441 a loop get the loop count in B : Note: we take
6442 only the lower order byte since shifting
6443 more that 32 bits make no sense anyway, ( the
6444 largest size of an object can be only 32 bits ) */
6446 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6447 emitcode("inc","b");
6448 freeAsmop (right,NULL,ic,TRUE);
6449 aopOp(left,ic,FALSE);
6450 aopOp(result,ic,FALSE);
6452 /* now move the left to the result if they are not the
6454 if (!sameRegs(AOP(left),AOP(result)) &&
6455 AOP_SIZE(result) > 1) {
6457 size = AOP_SIZE(result);
6460 l = aopGet(AOP(left),offset,FALSE,TRUE);
6461 if (*l == '@' && IS_AOP_PREG(result)) {
6463 emitcode("mov","a,%s",l);
6464 aopPut(AOP(result),"a",offset);
6466 aopPut(AOP(result),l,offset);
6471 /* mov the highest order bit to OVR */
6472 tlbl = newiTempLabel(NULL);
6473 tlbl1= newiTempLabel(NULL);
6475 size = AOP_SIZE(result);
6477 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6478 emitcode("rlc","a");
6479 emitcode("mov","ov,c");
6480 /* if it is only one byte then */
6482 l = aopGet(AOP(left),0,FALSE,FALSE);
6484 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6485 emitcode("","%05d_DS_:",tlbl->key+100);
6486 emitcode("mov","c,ov");
6487 emitcode("rrc","a");
6488 emitcode("","%05d_DS_:",tlbl1->key+100);
6489 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6490 aopPut(AOP(result),"a",0);
6494 reAdjustPreg(AOP(result));
6495 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6496 emitcode("","%05d_DS_:",tlbl->key+100);
6497 emitcode("mov","c,ov");
6499 l = aopGet(AOP(result),offset,FALSE,FALSE);
6501 emitcode("rrc","a");
6502 aopPut(AOP(result),"a",offset--);
6504 reAdjustPreg(AOP(result));
6505 emitcode("","%05d_DS_:",tlbl1->key+100);
6506 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6509 freeAsmop(left,NULL,ic,TRUE);
6510 freeAsmop(result,NULL,ic,TRUE);
6513 /*-----------------------------------------------------------------*/
6514 /* genRightShift - generate code for right shifting */
6515 /*-----------------------------------------------------------------*/
6516 static void genRightShift (iCode *ic)
6518 operand *right, *left, *result;
6522 symbol *tlbl, *tlbl1 ;
6524 /* if signed then we do it the hard way preserve the
6525 sign bit moving it inwards */
6526 retype = getSpec(operandType(IC_RESULT(ic)));
6527 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6529 if (!SPEC_USIGN(retype)) {
6530 genSignedRightShift (ic);
6534 /* signed & unsigned types are treated the same : i.e. the
6535 signed is NOT propagated inwards : quoting from the
6536 ANSI - standard : "for E1 >> E2, is equivalent to division
6537 by 2**E2 if unsigned or if it has a non-negative value,
6538 otherwise the result is implementation defined ", MY definition
6539 is that the sign does not get propagated */
6541 right = IC_RIGHT(ic);
6543 result = IC_RESULT(ic);
6545 aopOp(right,ic,FALSE);
6547 /* if the shift count is known then do it
6548 as efficiently as possible */
6549 if (AOP_TYPE(right) == AOP_LIT) {
6550 genRightShiftLiteral (left,right,result,ic, 0);
6554 /* shift count is unknown then we have to form
6555 a loop get the loop count in B : Note: we take
6556 only the lower order byte since shifting
6557 more that 32 bits make no sense anyway, ( the
6558 largest size of an object can be only 32 bits ) */
6560 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6561 emitcode("inc","b");
6562 freeAsmop (right,NULL,ic,TRUE);
6563 aopOp(left,ic,FALSE);
6564 aopOp(result,ic,FALSE);
6566 /* now move the left to the result if they are not the
6568 if (!sameRegs(AOP(left),AOP(result)) &&
6569 AOP_SIZE(result) > 1) {
6571 size = AOP_SIZE(result);
6574 l = aopGet(AOP(left),offset,FALSE,TRUE);
6575 if (*l == '@' && IS_AOP_PREG(result)) {
6577 emitcode("mov","a,%s",l);
6578 aopPut(AOP(result),"a",offset);
6580 aopPut(AOP(result),l,offset);
6585 tlbl = newiTempLabel(NULL);
6586 tlbl1= newiTempLabel(NULL);
6587 size = AOP_SIZE(result);
6590 /* if it is only one byte then */
6592 l = aopGet(AOP(left),0,FALSE,FALSE);
6594 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6595 emitcode("","%05d_DS_:",tlbl->key+100);
6597 emitcode("rrc","a");
6598 emitcode("","%05d_DS_:",tlbl1->key+100);
6599 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6600 aopPut(AOP(result),"a",0);
6604 reAdjustPreg(AOP(result));
6605 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6606 emitcode("","%05d_DS_:",tlbl->key+100);
6609 l = aopGet(AOP(result),offset,FALSE,FALSE);
6611 emitcode("rrc","a");
6612 aopPut(AOP(result),"a",offset--);
6614 reAdjustPreg(AOP(result));
6616 emitcode("","%05d_DS_:",tlbl1->key+100);
6617 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6620 freeAsmop(left,NULL,ic,TRUE);
6621 freeAsmop(result,NULL,ic,TRUE);
6624 /*-----------------------------------------------------------------*/
6625 /* genUnpackBits - generates code for unpacking bits */
6626 /*-----------------------------------------------------------------*/
6627 static void genUnpackBits (operand *result, char *rname, int ptype)
6634 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6635 etype = getSpec(operandType(result));
6637 /* read the first byte */
6642 emitcode("mov","a,@%s",rname);
6646 emitcode("movx","a,@%s",rname);
6650 emitcode("movx","a,@dptr");
6654 emitcode("clr","a");
6655 emitcode("movc","a","@a+dptr");
6659 emitcode("lcall","__gptrget");
6663 /* if we have bitdisplacement then it fits */
6664 /* into this byte completely or if length is */
6665 /* less than a byte */
6666 if ((shCnt = SPEC_BSTR(etype)) ||
6667 (SPEC_BLEN(etype) <= 8)) {
6669 /* shift right acc */
6672 emitcode("anl","a,#0x%02x",
6673 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
6674 aopPut(AOP(result),"a",offset);
6678 /* bit field did not fit in a byte */
6679 rlen = SPEC_BLEN(etype) - 8;
6680 aopPut(AOP(result),"a",offset++);
6687 emitcode("inc","%s",rname);
6688 emitcode("mov","a,@%s",rname);
6692 emitcode("inc","%s",rname);
6693 emitcode("movx","a,@%s",rname);
6697 emitcode("inc","dptr");
6698 emitcode("movx","a,@dptr");
6702 emitcode("clr","a");
6703 emitcode("inc","dptr");
6704 emitcode("movc","a","@a+dptr");
6708 emitcode("inc","dptr");
6709 emitcode("lcall","__gptrget");
6714 /* if we are done */
6718 aopPut(AOP(result),"a",offset++);
6723 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
6724 aopPut(AOP(result),"a",offset);
6731 /*-----------------------------------------------------------------*/
6732 /* genDataPointerGet - generates code when ptr offset is known */
6733 /*-----------------------------------------------------------------*/
6734 static void genDataPointerGet (operand *left,
6740 int size , offset = 0;
6741 aopOp(result,ic,TRUE);
6743 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6745 /* get the string representation of the name */
6746 l = aopGet(AOP(left),0,FALSE,TRUE);
6747 size = AOP_SIZE(result);
6748 // tsd, was l+1 - the underline `_' prefix was being stripped
6751 sprintf(buffer,"(%s + %d)",l,offset);
6753 sprintf(buffer,"%s",l);
6754 aopPut(AOP(result),buffer,offset++);
6757 freeAsmop(left,NULL,ic,TRUE);
6758 freeAsmop(result,NULL,ic,TRUE);
6761 /*-----------------------------------------------------------------*/
6762 /* genNearPointerGet - emitcode for near pointer fetch */
6763 /*-----------------------------------------------------------------*/
6764 static void genNearPointerGet (operand *left,
6771 sym_link *rtype, *retype;
6772 sym_link *ltype = operandType(left);
6775 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6777 rtype = operandType(result);
6778 retype= getSpec(rtype);
6780 aopOp(left,ic,FALSE);
6782 /* if left is rematerialisable and
6783 result is not bit variable type and
6784 the left is pointer to data space i.e
6785 lower 128 bytes of space */
6786 if (AOP_TYPE(left) == AOP_IMMD &&
6787 !IS_BITVAR(retype) &&
6788 DCL_TYPE(ltype) == POINTER) {
6789 genDataPointerGet (left,result,ic);
6793 /* if the value is already in a pointer register
6794 then don't need anything more */
6795 if (!AOP_INPREG(AOP(left))) {
6796 /* otherwise get a free pointer register */
6798 preg = getFreePtr(ic,&aop,FALSE);
6799 emitcode("mov","%s,%s",
6801 aopGet(AOP(left),0,FALSE,TRUE));
6802 rname = preg->name ;
6804 rname = aopGet(AOP(left),0,FALSE,FALSE);
6806 freeAsmop(left,NULL,ic,TRUE);
6807 aopOp (result,ic,FALSE);
6809 /* if bitfield then unpack the bits */
6810 if (IS_BITVAR(retype))
6811 genUnpackBits (result,rname,POINTER);
6813 /* we have can just get the values */
6814 int size = AOP_SIZE(result);
6818 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
6820 emitcode("mov","a,@%s",rname);
6821 aopPut(AOP(result),"a",offset);
6823 sprintf(buffer,"@%s",rname);
6824 aopPut(AOP(result),buffer,offset);
6828 emitcode("inc","%s",rname);
6832 /* now some housekeeping stuff */
6834 /* we had to allocate for this iCode */
6835 freeAsmop(NULL,aop,ic,TRUE);
6837 /* we did not allocate which means left
6838 already in a pointer register, then
6839 if size > 0 && this could be used again
6840 we have to point it back to where it
6842 if (AOP_SIZE(result) > 1 &&
6843 !OP_SYMBOL(left)->remat &&
6844 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6846 int size = AOP_SIZE(result) - 1;
6848 emitcode("dec","%s",rname);
6853 freeAsmop(result,NULL,ic,TRUE);
6857 /*-----------------------------------------------------------------*/
6858 /* genPagedPointerGet - emitcode for paged pointer fetch */
6859 /*-----------------------------------------------------------------*/
6860 static void genPagedPointerGet (operand *left,
6867 sym_link *rtype, *retype;
6869 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6871 rtype = operandType(result);
6872 retype= getSpec(rtype);
6874 aopOp(left,ic,FALSE);
6876 /* if the value is already in a pointer register
6877 then don't need anything more */
6878 if (!AOP_INPREG(AOP(left))) {
6879 /* otherwise get a free pointer register */
6881 preg = getFreePtr(ic,&aop,FALSE);
6882 emitcode("mov","%s,%s",
6884 aopGet(AOP(left),0,FALSE,TRUE));
6885 rname = preg->name ;
6887 rname = aopGet(AOP(left),0,FALSE,FALSE);
6889 freeAsmop(left,NULL,ic,TRUE);
6890 aopOp (result,ic,FALSE);
6892 /* if bitfield then unpack the bits */
6893 if (IS_BITVAR(retype))
6894 genUnpackBits (result,rname,PPOINTER);
6896 /* we have can just get the values */
6897 int size = AOP_SIZE(result);
6902 emitcode("movx","a,@%s",rname);
6903 aopPut(AOP(result),"a",offset);
6908 emitcode("inc","%s",rname);
6912 /* now some housekeeping stuff */
6914 /* we had to allocate for this iCode */
6915 freeAsmop(NULL,aop,ic,TRUE);
6917 /* we did not allocate which means left
6918 already in a pointer register, then
6919 if size > 0 && this could be used again
6920 we have to point it back to where it
6922 if (AOP_SIZE(result) > 1 &&
6923 !OP_SYMBOL(left)->remat &&
6924 ( OP_SYMBOL(left)->liveTo > ic->seq ||
6926 int size = AOP_SIZE(result) - 1;
6928 emitcode("dec","%s",rname);
6933 freeAsmop(result,NULL,ic,TRUE);
6938 /*-----------------------------------------------------------------*/
6939 /* genFarPointerGet - gget value from far space */
6940 /*-----------------------------------------------------------------*/
6941 static void genFarPointerGet (operand *left,
6942 operand *result, iCode *ic)
6945 sym_link *retype = getSpec(operandType(result));
6947 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6949 aopOp(left,ic,FALSE);
6951 /* if the operand is already in dptr
6952 then we do nothing else we move the value to dptr */
6953 if (AOP_TYPE(left) != AOP_STR) {
6954 /* if this is remateriazable */
6955 if (AOP_TYPE(left) == AOP_IMMD)
6956 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
6957 else { /* we need to get it byte by byte */
6958 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
6959 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
6960 if (options.model == MODEL_FLAT24)
6962 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
6966 /* so dptr know contains the address */
6967 freeAsmop(left,NULL,ic,TRUE);
6968 aopOp(result,ic,FALSE);
6970 /* if bit then unpack */
6971 if (IS_BITVAR(retype))
6972 genUnpackBits(result,"dptr",FPOINTER);
6974 size = AOP_SIZE(result);
6978 emitcode("movx","a,@dptr");
6979 aopPut(AOP(result),"a",offset++);
6981 emitcode("inc","dptr");
6985 freeAsmop(result,NULL,ic,TRUE);
6988 /*-----------------------------------------------------------------*/
6989 /* emitcodePointerGet - gget value from code space */
6990 /*-----------------------------------------------------------------*/
6991 static void emitcodePointerGet (operand *left,
6992 operand *result, iCode *ic)
6995 sym_link *retype = getSpec(operandType(result));
6997 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6999 aopOp(left,ic,FALSE);
7001 /* if the operand is already in dptr
7002 then we do nothing else we move the value to dptr */
7003 if (AOP_TYPE(left) != AOP_STR) {
7004 /* if this is remateriazable */
7005 if (AOP_TYPE(left) == AOP_IMMD)
7006 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7007 else { /* we need to get it byte by byte */
7008 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7009 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7010 if (options.model == MODEL_FLAT24)
7012 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7016 /* so dptr know contains the address */
7017 freeAsmop(left,NULL,ic,TRUE);
7018 aopOp(result,ic,FALSE);
7020 /* if bit then unpack */
7021 if (IS_BITVAR(retype))
7022 genUnpackBits(result,"dptr",CPOINTER);
7024 size = AOP_SIZE(result);
7028 emitcode("clr","a");
7029 emitcode("movc","a,@a+dptr");
7030 aopPut(AOP(result),"a",offset++);
7032 emitcode("inc","dptr");
7036 freeAsmop(result,NULL,ic,TRUE);
7039 /*-----------------------------------------------------------------*/
7040 /* genGenPointerGet - gget value from generic pointer space */
7041 /*-----------------------------------------------------------------*/
7042 static void genGenPointerGet (operand *left,
7043 operand *result, iCode *ic)
7046 sym_link *retype = getSpec(operandType(result));
7048 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7049 aopOp(left,ic,FALSE);
7051 /* if the operand is already in dptr
7052 then we do nothing else we move the value to dptr */
7053 if (AOP_TYPE(left) != AOP_STR) {
7054 /* if this is remateriazable */
7055 if (AOP_TYPE(left) == AOP_IMMD) {
7056 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7057 emitcode("mov","b,#%d",pointerCode(retype));
7059 else { /* we need to get it byte by byte */
7061 emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7062 emitcode("movwf","FSR");
7064 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7065 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7066 if (options.model == MODEL_FLAT24)
7068 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7069 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7073 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7078 /* so dptr know contains the address */
7079 freeAsmop(left,NULL,ic,TRUE);
7080 aopOp(result,ic,FALSE);
7082 /* if bit then unpack */
7083 if (IS_BITVAR(retype))
7084 genUnpackBits(result,"dptr",GPOINTER);
7086 size = AOP_SIZE(result);
7090 //emitcode("lcall","__gptrget");
7091 emitcode("movf","indf,w");
7092 //aopPut(AOP(result),"a",offset++);
7093 emitcode("movwf","%s",
7094 aopGet(AOP(result),offset++,FALSE,FALSE));
7096 emitcode("incf","fsr,f");
7100 freeAsmop(result,NULL,ic,TRUE);
7103 /*-----------------------------------------------------------------*/
7104 /* genPointerGet - generate code for pointer get */
7105 /*-----------------------------------------------------------------*/
7106 static void genPointerGet (iCode *ic)
7108 operand *left, *result ;
7109 sym_link *type, *etype;
7112 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7115 result = IC_RESULT(ic) ;
7117 /* depending on the type of pointer we need to
7118 move it to the correct pointer register */
7119 type = operandType(left);
7120 etype = getSpec(type);
7121 /* if left is of type of pointer then it is simple */
7122 if (IS_PTR(type) && !IS_FUNC(type->next))
7123 p_type = DCL_TYPE(type);
7125 /* we have to go by the storage class */
7126 p_type = PTR_TYPE(SPEC_OCLS(etype));
7128 /* if (SPEC_OCLS(etype)->codesp ) { */
7129 /* p_type = CPOINTER ; */
7132 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7133 /* p_type = FPOINTER ; */
7135 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7136 /* p_type = PPOINTER; */
7138 /* if (SPEC_OCLS(etype) == idata ) */
7139 /* p_type = IPOINTER; */
7141 /* p_type = POINTER ; */
7144 /* now that we have the pointer type we assign
7145 the pointer values */
7150 genNearPointerGet (left,result,ic);
7154 genPagedPointerGet(left,result,ic);
7158 genFarPointerGet (left,result,ic);
7162 emitcodePointerGet (left,result,ic);
7166 genGenPointerGet (left,result,ic);
7172 /*-----------------------------------------------------------------*/
7173 /* genPackBits - generates code for packed bit storage */
7174 /*-----------------------------------------------------------------*/
7175 static void genPackBits (sym_link *etype ,
7177 char *rname, int p_type)
7185 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7186 blen = SPEC_BLEN(etype);
7187 bstr = SPEC_BSTR(etype);
7189 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7192 /* if the bit lenth is less than or */
7193 /* it exactly fits a byte then */
7194 if (SPEC_BLEN(etype) <= 8 ) {
7195 shCount = SPEC_BSTR(etype) ;
7197 /* shift left acc */
7200 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7205 emitcode ("mov","b,a");
7206 emitcode("mov","a,@%s",rname);
7210 emitcode ("mov","b,a");
7211 emitcode("movx","a,@dptr");
7215 emitcode ("push","b");
7216 emitcode ("push","acc");
7217 emitcode ("lcall","__gptrget");
7218 emitcode ("pop","b");
7222 emitcode ("anl","a,#0x%02x",(unsigned char)
7223 ((unsigned char)(0xFF << (blen+bstr)) |
7224 (unsigned char)(0xFF >> (8-bstr)) ) );
7225 emitcode ("orl","a,b");
7226 if (p_type == GPOINTER)
7227 emitcode("pop","b");
7233 emitcode("mov","@%s,a",rname);
7237 emitcode("movx","@dptr,a");
7241 DEBUGemitcode(";lcall","__gptrput");
7246 if ( SPEC_BLEN(etype) <= 8 )
7249 emitcode("inc","%s",rname);
7250 rLen = SPEC_BLEN(etype) ;
7252 /* now generate for lengths greater than one byte */
7255 l = aopGet(AOP(right),offset++,FALSE,TRUE);
7265 emitcode("mov","@%s,a",rname);
7267 emitcode("mov","@%s,%s",rname,l);
7272 emitcode("movx","@dptr,a");
7277 DEBUGemitcode(";lcall","__gptrput");
7280 emitcode ("inc","%s",rname);
7285 /* last last was not complete */
7287 /* save the byte & read byte */
7290 emitcode ("mov","b,a");
7291 emitcode("mov","a,@%s",rname);
7295 emitcode ("mov","b,a");
7296 emitcode("movx","a,@dptr");
7300 emitcode ("push","b");
7301 emitcode ("push","acc");
7302 emitcode ("lcall","__gptrget");
7303 emitcode ("pop","b");
7307 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7308 emitcode ("orl","a,b");
7311 if (p_type == GPOINTER)
7312 emitcode("pop","b");
7317 emitcode("mov","@%s,a",rname);
7321 emitcode("movx","@dptr,a");
7325 DEBUGemitcode(";lcall","__gptrput");
7329 /*-----------------------------------------------------------------*/
7330 /* genDataPointerSet - remat pointer to data space */
7331 /*-----------------------------------------------------------------*/
7332 static void genDataPointerSet(operand *right,
7336 int size, offset = 0 ;
7337 char *l, buffer[256];
7339 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7340 aopOp(right,ic,FALSE);
7342 l = aopGet(AOP(result),0,FALSE,TRUE);
7343 size = AOP_SIZE(right);
7344 // tsd, was l+1 - the underline `_' prefix was being stripped
7347 sprintf(buffer,"(%s + %d)",l,offset);
7349 sprintf(buffer,"%s",l);
7351 if (AOP_TYPE(right) == AOP_LIT) {
7352 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7353 lit = lit >> (8*offset);
7355 emitcode("movlw","%s",lit);
7356 emitcode("movwf","%s",buffer);
7358 emitcode("clrf","%s",buffer);
7360 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7361 emitcode("movwf","%s",buffer);
7367 freeAsmop(right,NULL,ic,TRUE);
7368 freeAsmop(result,NULL,ic,TRUE);
7371 /*-----------------------------------------------------------------*/
7372 /* genNearPointerSet - emitcode for near pointer put */
7373 /*-----------------------------------------------------------------*/
7374 static void genNearPointerSet (operand *right,
7381 sym_link *ptype = operandType(result);
7384 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7385 retype= getSpec(operandType(right));
7387 aopOp(result,ic,FALSE);
7389 /* if the result is rematerializable &
7390 in data space & not a bit variable */
7391 if (AOP_TYPE(result) == AOP_IMMD &&
7392 DCL_TYPE(ptype) == POINTER &&
7393 !IS_BITVAR(retype)) {
7394 genDataPointerSet (right,result,ic);
7398 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7400 /* if the value is already in a pointer register
7401 then don't need anything more */
7402 if (!AOP_INPREG(AOP(result))) {
7403 /* otherwise get a free pointer register */
7404 //aop = newAsmop(0);
7405 //preg = getFreePtr(ic,&aop,FALSE);
7406 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7407 //emitcode("mov","%s,%s",
7409 // aopGet(AOP(result),0,FALSE,TRUE));
7410 //rname = preg->name ;
7411 emitcode("movwf","fsr");
7413 // rname = aopGet(AOP(result),0,FALSE,FALSE);
7415 freeAsmop(result,NULL,ic,TRUE);
7416 aopOp (right,ic,FALSE);
7417 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7419 /* if bitfield then unpack the bits */
7420 if (IS_BITVAR(retype)) {
7421 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7422 "The programmer is obviously confused");
7423 //genPackBits (retype,right,rname,POINTER);
7427 /* we have can just get the values */
7428 int size = AOP_SIZE(right);
7431 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7433 l = aopGet(AOP(right),offset,FALSE,TRUE);
7436 //emitcode("mov","@%s,a",rname);
7437 emitcode("movf","indf,w ;1");
7440 if (AOP_TYPE(right) == AOP_LIT) {
7441 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7443 emitcode("movlw","%s",l);
7444 emitcode("movwf","indf ;2");
7446 emitcode("clrf","indf");
7448 emitcode("movf","%s,w",l);
7449 emitcode("movwf","indf ;2");
7451 //emitcode("mov","@%s,%s",rname,l);
7454 emitcode("incf","fsr,f ;3");
7455 //emitcode("inc","%s",rname);
7460 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7461 /* now some housekeeping stuff */
7463 /* we had to allocate for this iCode */
7464 freeAsmop(NULL,aop,ic,TRUE);
7466 /* we did not allocate which means left
7467 already in a pointer register, then
7468 if size > 0 && this could be used again
7469 we have to point it back to where it
7471 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7472 if (AOP_SIZE(right) > 1 &&
7473 !OP_SYMBOL(result)->remat &&
7474 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7476 int size = AOP_SIZE(right) - 1;
7478 emitcode("decf","fsr,f");
7479 //emitcode("dec","%s",rname);
7483 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7485 freeAsmop(right,NULL,ic,TRUE);
7490 /*-----------------------------------------------------------------*/
7491 /* genPagedPointerSet - emitcode for Paged pointer put */
7492 /*-----------------------------------------------------------------*/
7493 static void genPagedPointerSet (operand *right,
7502 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7504 retype= getSpec(operandType(right));
7506 aopOp(result,ic,FALSE);
7508 /* if the value is already in a pointer register
7509 then don't need anything more */
7510 if (!AOP_INPREG(AOP(result))) {
7511 /* otherwise get a free pointer register */
7513 preg = getFreePtr(ic,&aop,FALSE);
7514 emitcode("mov","%s,%s",
7516 aopGet(AOP(result),0,FALSE,TRUE));
7517 rname = preg->name ;
7519 rname = aopGet(AOP(result),0,FALSE,FALSE);
7521 freeAsmop(result,NULL,ic,TRUE);
7522 aopOp (right,ic,FALSE);
7524 /* if bitfield then unpack the bits */
7525 if (IS_BITVAR(retype))
7526 genPackBits (retype,right,rname,PPOINTER);
7528 /* we have can just get the values */
7529 int size = AOP_SIZE(right);
7533 l = aopGet(AOP(right),offset,FALSE,TRUE);
7536 emitcode("movx","@%s,a",rname);
7539 emitcode("inc","%s",rname);
7545 /* now some housekeeping stuff */
7547 /* we had to allocate for this iCode */
7548 freeAsmop(NULL,aop,ic,TRUE);
7550 /* we did not allocate which means left
7551 already in a pointer register, then
7552 if size > 0 && this could be used again
7553 we have to point it back to where it
7555 if (AOP_SIZE(right) > 1 &&
7556 !OP_SYMBOL(result)->remat &&
7557 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7559 int size = AOP_SIZE(right) - 1;
7561 emitcode("dec","%s",rname);
7566 freeAsmop(right,NULL,ic,TRUE);
7571 /*-----------------------------------------------------------------*/
7572 /* genFarPointerSet - set value from far space */
7573 /*-----------------------------------------------------------------*/
7574 static void genFarPointerSet (operand *right,
7575 operand *result, iCode *ic)
7578 sym_link *retype = getSpec(operandType(right));
7580 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7581 aopOp(result,ic,FALSE);
7583 /* if the operand is already in dptr
7584 then we do nothing else we move the value to dptr */
7585 if (AOP_TYPE(result) != AOP_STR) {
7586 /* if this is remateriazable */
7587 if (AOP_TYPE(result) == AOP_IMMD)
7588 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7589 else { /* we need to get it byte by byte */
7590 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
7591 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
7592 if (options.model == MODEL_FLAT24)
7594 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
7598 /* so dptr know contains the address */
7599 freeAsmop(result,NULL,ic,TRUE);
7600 aopOp(right,ic,FALSE);
7602 /* if bit then unpack */
7603 if (IS_BITVAR(retype))
7604 genPackBits(retype,right,"dptr",FPOINTER);
7606 size = AOP_SIZE(right);
7610 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7612 emitcode("movx","@dptr,a");
7614 emitcode("inc","dptr");
7618 freeAsmop(right,NULL,ic,TRUE);
7621 /*-----------------------------------------------------------------*/
7622 /* genGenPointerSet - set value from generic pointer space */
7623 /*-----------------------------------------------------------------*/
7624 static void genGenPointerSet (operand *right,
7625 operand *result, iCode *ic)
7628 sym_link *retype = getSpec(operandType(right));
7630 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7632 aopOp(result,ic,FALSE);
7634 /* if the operand is already in dptr
7635 then we do nothing else we move the value to dptr */
7636 if (AOP_TYPE(result) != AOP_STR) {
7637 /* if this is remateriazable */
7638 if (AOP_TYPE(result) == AOP_IMMD) {
7639 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
7640 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
7642 else { /* we need to get it byte by byte */
7643 char *l = aopGet(AOP(result),0,FALSE,FALSE);
7645 emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
7647 emitcode("movwf","INDF");
7650 /* so dptr know contains the address */
7651 freeAsmop(result,NULL,ic,TRUE);
7652 aopOp(right,ic,FALSE);
7654 /* if bit then unpack */
7655 if (IS_BITVAR(retype))
7656 genPackBits(retype,right,"dptr",GPOINTER);
7658 size = AOP_SIZE(right);
7662 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
7664 emitcode("incf","fsr,f");
7665 emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
7666 emitcode("movwf","indf");
7668 //DEBUGemitcode(";lcall","__gptrput");
7670 // emitcode("inc","dptr");
7674 freeAsmop(right,NULL,ic,TRUE);
7677 /*-----------------------------------------------------------------*/
7678 /* genPointerSet - stores the value into a pointer location */
7679 /*-----------------------------------------------------------------*/
7680 static void genPointerSet (iCode *ic)
7682 operand *right, *result ;
7683 sym_link *type, *etype;
7686 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7688 right = IC_RIGHT(ic);
7689 result = IC_RESULT(ic) ;
7691 /* depending on the type of pointer we need to
7692 move it to the correct pointer register */
7693 type = operandType(result);
7694 etype = getSpec(type);
7695 /* if left is of type of pointer then it is simple */
7696 if (IS_PTR(type) && !IS_FUNC(type->next)) {
7697 p_type = DCL_TYPE(type);
7700 /* we have to go by the storage class */
7701 p_type = PTR_TYPE(SPEC_OCLS(etype));
7703 /* if (SPEC_OCLS(etype)->codesp ) { */
7704 /* p_type = CPOINTER ; */
7707 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7708 /* p_type = FPOINTER ; */
7710 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7711 /* p_type = PPOINTER ; */
7713 /* if (SPEC_OCLS(etype) == idata ) */
7714 /* p_type = IPOINTER ; */
7716 /* p_type = POINTER ; */
7719 /* now that we have the pointer type we assign
7720 the pointer values */
7725 genNearPointerSet (right,result,ic);
7729 genPagedPointerSet (right,result,ic);
7733 genFarPointerSet (right,result,ic);
7737 genGenPointerSet (right,result,ic);
7743 /*-----------------------------------------------------------------*/
7744 /* genIfx - generate code for Ifx statement */
7745 /*-----------------------------------------------------------------*/
7746 static void genIfx (iCode *ic, iCode *popIc)
7748 operand *cond = IC_COND(ic);
7751 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7752 aopOp(cond,ic,FALSE);
7754 /* get the value into acc */
7755 if (AOP_TYPE(cond) != AOP_CRY)
7759 /* the result is now in the accumulator */
7760 freeAsmop(cond,NULL,ic,TRUE);
7762 /* if there was something to be popped then do it */
7766 /* if the condition is a bit variable */
7767 if (isbit && IS_ITEMP(cond) &&
7769 genIfxJump(ic,SPIL_LOC(cond)->rname);
7770 DEBUGemitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
7774 if (isbit && !IS_ITEMP(cond))
7775 DEBUGemitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
7777 DEBUGemitcode ("; isbit","a");
7780 if (isbit && !IS_ITEMP(cond))
7781 genIfxJump(ic,OP_SYMBOL(cond)->rname);
7788 /*-----------------------------------------------------------------*/
7789 /* genAddrOf - generates code for address of */
7790 /*-----------------------------------------------------------------*/
7791 static void genAddrOf (iCode *ic)
7793 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
7796 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7798 aopOp(IC_RESULT(ic),ic,FALSE);
7800 /* if the operand is on the stack then we
7801 need to get the stack offset of this
7804 /* if it has an offset then we need to compute
7807 emitcode("mov","a,_bp");
7808 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
7809 aopPut(AOP(IC_RESULT(ic)),"a",0);
7811 /* we can just move _bp */
7812 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
7814 /* fill the result with zero */
7815 size = AOP_SIZE(IC_RESULT(ic)) - 1;
7818 if (options.stack10bit && size < (FPTRSIZE - 1))
7821 "*** warning: pointer to stack var truncated.\n");
7828 if (options.stack10bit && offset == 2)
7830 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
7834 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
7841 /* object not on stack then we need the name */
7842 size = AOP_SIZE(IC_RESULT(ic));
7846 char s[SDCC_NAME_MAX];
7848 sprintf(s,"#(%s >> %d)",
7852 sprintf(s,"#%s",sym->rname);
7853 aopPut(AOP(IC_RESULT(ic)),s,offset++);
7857 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
7862 /*-----------------------------------------------------------------*/
7863 /* genFarFarAssign - assignment when both are in far space */
7864 /*-----------------------------------------------------------------*/
7865 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
7867 int size = AOP_SIZE(right);
7870 /* first push the right side on to the stack */
7872 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7874 emitcode ("push","acc");
7877 freeAsmop(right,NULL,ic,FALSE);
7878 /* now assign DPTR to result */
7879 aopOp(result,ic,FALSE);
7880 size = AOP_SIZE(result);
7882 emitcode ("pop","acc");
7883 aopPut(AOP(result),"a",--offset);
7885 freeAsmop(result,NULL,ic,FALSE);
7890 /*-----------------------------------------------------------------*/
7891 /* genAssign - generate code for assignment */
7892 /*-----------------------------------------------------------------*/
7893 static void genAssign (iCode *ic)
7895 operand *result, *right;
7897 unsigned long lit = 0L;
7899 result = IC_RESULT(ic);
7900 right = IC_RIGHT(ic) ;
7902 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7904 /* if they are the same */
7905 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
7908 aopOp(right,ic,FALSE);
7909 aopOp(result,ic,TRUE);
7911 /* if they are the same registers */
7912 if (sameRegs(AOP(right),AOP(result)))
7915 /* if the result is a bit */
7916 if (AOP_TYPE(result) == AOP_CRY) {
7918 /* if the right size is a literal then
7919 we know what the value is */
7920 if (AOP_TYPE(right) == AOP_LIT) {
7921 if (((int) operandLitValue(right)))
7922 emitcode("bsf","(%s >> 3),(%s & 7)",
7923 AOP(result)->aopu.aop_dir,
7924 AOP(result)->aopu.aop_dir);
7926 emitcode("bcf","(%s >> 3),(%s & 7)",
7927 AOP(result)->aopu.aop_dir,
7928 AOP(result)->aopu.aop_dir);
7932 /* the right is also a bit variable */
7933 if (AOP_TYPE(right) == AOP_CRY) {
7934 emitcode("bcf","(%s >> 3),(%s & 7)",
7935 AOP(result)->aopu.aop_dir,
7936 AOP(result)->aopu.aop_dir);
7937 emitcode("btfsc","(%s >> 3),(%s & 7)",
7938 AOP(right)->aopu.aop_dir,
7939 AOP(right)->aopu.aop_dir);
7940 emitcode("bsf","(%s >> 3),(%s & 7)",
7941 AOP(result)->aopu.aop_dir,
7942 AOP(result)->aopu.aop_dir);
7948 aopPut(AOP(result),"a",0);
7952 /* bit variables done */
7954 size = AOP_SIZE(result);
7956 if(AOP_TYPE(right) == AOP_LIT)
7957 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7958 if((AOP_TYPE(result) != AOP_REG) &&
7959 (AOP_TYPE(right) == AOP_LIT) &&
7960 !IS_FLOAT(operandType(right)) &&
7964 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
7965 emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
7967 emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
7968 emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
7973 if(AOP_TYPE(right) == AOP_LIT)
7974 emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
7976 emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
7978 emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
7984 freeAsmop (right,NULL,ic,FALSE);
7985 freeAsmop (result,NULL,ic,TRUE);
7988 /*-----------------------------------------------------------------*/
7989 /* genJumpTab - genrates code for jump table */
7990 /*-----------------------------------------------------------------*/
7991 static void genJumpTab (iCode *ic)
7996 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7998 aopOp(IC_JTCOND(ic),ic,FALSE);
7999 /* get the condition into accumulator */
8000 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8002 /* multiply by three */
8003 emitcode("add","a,acc");
8004 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8005 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8007 jtab = newiTempLabel(NULL);
8008 emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8009 emitcode("jmp","@a+dptr");
8010 emitcode("","%05d_DS_:",jtab->key+100);
8011 /* now generate the jump labels */
8012 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8013 jtab = setNextItem(IC_JTLABELS(ic)))
8014 emitcode("ljmp","%05d_DS_",jtab->key+100);
8018 /*-----------------------------------------------------------------*/
8019 /* genMixedOperation - gen code for operators between mixed types */
8020 /*-----------------------------------------------------------------*/
8022 TSD - Written for the PIC port - but this unfortunately is buggy.
8023 This routine is good in that it is able to efficiently promote
8024 types to different (larger) sizes. Unfortunately, the temporary
8025 variables that are optimized out by this routine are sometimes
8026 used in other places. So until I know how to really parse the
8027 iCode tree, I'm going to not be using this routine :(.
8029 static int genMixedOperation (iCode *ic)
8032 operand *result = IC_RESULT(ic);
8033 sym_link *ctype = operandType(IC_LEFT(ic));
8034 operand *right = IC_RIGHT(ic);
8040 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8042 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8048 nextright = IC_RIGHT(nextic);
8049 nextleft = IC_LEFT(nextic);
8050 nextresult = IC_RESULT(nextic);
8052 aopOp(right,ic,FALSE);
8053 aopOp(result,ic,FALSE);
8054 aopOp(nextright, nextic, FALSE);
8055 aopOp(nextleft, nextic, FALSE);
8056 aopOp(nextresult, nextic, FALSE);
8058 if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8064 emitcode(";remove right +","");
8066 } else if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8072 emitcode(";remove left +","");
8076 big = AOP_SIZE(nextleft);
8077 small = AOP_SIZE(nextright);
8079 switch(nextic->op) {
8082 emitcode(";optimize a +","");
8083 /* if unsigned or not an integral type */
8084 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8085 emitcode(";add a bit to something","");
8088 emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8090 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8091 emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8092 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8094 emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8102 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8103 emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8104 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8107 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8109 emitcode("btfsc","(%s >> 3), (%s & 7)",
8110 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8111 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8112 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8113 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8116 emitcode("rlf","known_zero,w");
8123 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8124 emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8125 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8127 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8137 freeAsmop(right,NULL,ic,TRUE);
8138 freeAsmop(result,NULL,ic,TRUE);
8139 freeAsmop(nextright,NULL,ic,TRUE);
8140 freeAsmop(nextleft,NULL,ic,TRUE);
8142 nextic->generated = 1;
8149 /*-----------------------------------------------------------------*/
8150 /* genCast - gen code for casting */
8151 /*-----------------------------------------------------------------*/
8152 static void genCast (iCode *ic)
8154 operand *result = IC_RESULT(ic);
8155 sym_link *ctype = operandType(IC_LEFT(ic));
8156 operand *right = IC_RIGHT(ic);
8159 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8160 /* if they are equivalent then do nothing */
8161 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8164 aopOp(right,ic,FALSE) ;
8165 aopOp(result,ic,FALSE);
8167 /* if the result is a bit */
8168 if (AOP_TYPE(result) == AOP_CRY) {
8169 /* if the right size is a literal then
8170 we know what the value is */
8171 if (AOP_TYPE(right) == AOP_LIT) {
8172 emitcode("; *** right is a lit","%s %d",__FUNCTION__,__LINE__);
8173 if (((int) operandLitValue(right)))
8174 emitcode("bsf","(%s >> 3), (%s & 7)",
8175 AOP(result)->aopu.aop_dir,
8176 AOP(result)->aopu.aop_dir);
8178 emitcode("bcf","(%s >> 3), (%s & 7)",
8179 AOP(result)->aopu.aop_dir,
8180 AOP(result)->aopu.aop_dir);
8185 /* the right is also a bit variable */
8186 if (AOP_TYPE(right) == AOP_CRY) {
8187 emitcode("clrc","");
8188 emitcode("btfsc","(%s >> 3), (%s & 7)",
8189 AOP(right)->aopu.aop_dir,
8190 AOP(right)->aopu.aop_dir);
8191 aopPut(AOP(result),"c",0);
8197 aopPut(AOP(result),"a",0);
8201 /* if they are the same size : or less */
8202 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8204 /* if they are in the same place */
8205 if (sameRegs(AOP(right),AOP(result)))
8208 /* if they in different places then copy */
8209 size = AOP_SIZE(result);
8213 aopGet(AOP(right),offset,FALSE,FALSE),
8221 /* if the result is of type pointer */
8222 if (IS_PTR(ctype)) {
8225 sym_link *type = operandType(right);
8226 sym_link *etype = getSpec(type);
8228 /* pointer to generic pointer */
8229 if (IS_GENPTR(ctype)) {
8233 p_type = DCL_TYPE(type);
8235 /* we have to go by the storage class */
8236 p_type = PTR_TYPE(SPEC_OCLS(etype));
8238 /* if (SPEC_OCLS(etype)->codesp ) */
8239 /* p_type = CPOINTER ; */
8241 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8242 /* p_type = FPOINTER ; */
8244 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8245 /* p_type = PPOINTER; */
8247 /* if (SPEC_OCLS(etype) == idata ) */
8248 /* p_type = IPOINTER ; */
8250 /* p_type = POINTER ; */
8253 /* the first two bytes are known */
8254 size = GPTRSIZE - 1;
8258 aopGet(AOP(right),offset,FALSE,FALSE),
8262 /* the last byte depending on type */
8279 /* this should never happen */
8280 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8281 "got unknown pointer type");
8283 aopPut(AOP(result),l, GPTRSIZE - 1);
8287 /* just copy the pointers */
8288 size = AOP_SIZE(result);
8292 aopGet(AOP(right),offset,FALSE,FALSE),
8300 if (AOP_TYPE(right) == AOP_CRY) {
8302 size = AOP_SIZE(right);
8304 emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8305 emitcode("btfsc","(%s >> 3), (%s & 7)",
8306 AOP(right)->aopu.aop_dir,
8307 AOP(right)->aopu.aop_dir);
8308 emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8310 emitcode("clrf","%s", aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8315 /* so we now know that the size of destination is greater
8316 than the size of the source.
8317 Now, if the next iCode is an operator then we might be
8318 able to optimize the operation without performing a cast.
8320 if(genMixedOperation(ic))
8324 /* we move to result for the size of source */
8325 size = AOP_SIZE(right);
8328 emitcode(";","%d",__LINE__);
8330 aopGet(AOP(right),offset,FALSE,FALSE),
8335 /* now depending on the sign of the destination */
8336 size = AOP_SIZE(result) - AOP_SIZE(right);
8337 /* if unsigned or not an integral type */
8338 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8340 emitcode("clrf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8342 /* we need to extend the sign :{ */
8343 //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8346 emitcode("clrw","");
8347 emitcode("btfsc","(%s >> 3), (%s & 7)",
8348 AOP(right)->aopu.aop_dir,
8349 AOP(right)->aopu.aop_dir);
8350 emitcode("movlw","0xff");
8352 emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8353 // aopPut(AOP(result),"a",offset++);
8358 /* we are done hurray !!!! */
8361 freeAsmop(right,NULL,ic,TRUE);
8362 freeAsmop(result,NULL,ic,TRUE);
8366 /*-----------------------------------------------------------------*/
8367 /* genDjnz - generate decrement & jump if not zero instrucion */
8368 /*-----------------------------------------------------------------*/
8369 static int genDjnz (iCode *ic, iCode *ifx)
8372 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8377 /* if the if condition has a false label
8378 then we cannot save */
8382 /* if the minus is not of the form
8384 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8385 !IS_OP_LITERAL(IC_RIGHT(ic)))
8388 if (operandLitValue(IC_RIGHT(ic)) != 1)
8391 /* if the size of this greater than one then no
8393 if (getSize(operandType(IC_RESULT(ic))) > 1)
8396 /* otherwise we can save BIG */
8397 lbl = newiTempLabel(NULL);
8398 lbl1= newiTempLabel(NULL);
8400 aopOp(IC_RESULT(ic),ic,FALSE);
8402 if (IS_AOP_PREG(IC_RESULT(ic))) {
8403 emitcode("dec","%s",
8404 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8405 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8406 emitcode("jnz","%05d_DS_",lbl->key+100);
8408 emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8409 emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8412 /* emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8413 /* emitcode ("","%05d_DS_:",lbl->key+100); */
8414 /* emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8415 /* emitcode ("","%05d_DS_:",lbl1->key+100); */
8418 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8423 /*-----------------------------------------------------------------*/
8424 /* genReceive - generate code for a receive iCode */
8425 /*-----------------------------------------------------------------*/
8426 static void genReceive (iCode *ic)
8428 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8430 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8431 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8432 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8434 int size = getSize(operandType(IC_RESULT(ic)));
8435 int offset = fReturnSize - size;
8437 emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
8438 fReturn[fReturnSize - offset - 1] : "acc"));
8441 aopOp(IC_RESULT(ic),ic,FALSE);
8442 size = AOP_SIZE(IC_RESULT(ic));
8445 emitcode ("pop","acc");
8446 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8451 aopOp(IC_RESULT(ic),ic,FALSE);
8453 assignResultValue(IC_RESULT(ic));
8456 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8459 /*-----------------------------------------------------------------*/
8460 /* genpic14Code - generate code for pic14 based controllers */
8461 /*-----------------------------------------------------------------*/
8462 void genpic14Code (iCode *lic)
8467 lineHead = lineCurr = NULL;
8469 /* if debug information required */
8470 /* if (options.debug && currFunc) { */
8472 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8474 if (IS_STATIC(currFunc->etype))
8475 emitcode("",";F%s$%s$0$0 %d",moduleName,currFunc->name,__LINE__);
8477 emitcode("",";G$%s$0$0 %d",currFunc->name,__LINE__);
8482 for (ic = lic ; ic ; ic = ic->next ) {
8484 DEBUGemitcode(";ic","");
8485 if ( cln != ic->lineno ) {
8486 if ( options.debug ) {
8488 emitcode("",";C$%s$%d$%d$%d ==.",
8489 FileBaseName(ic->filename),ic->lineno,
8490 ic->level,ic->block);
8493 emitcode(";","%s %d",ic->filename,ic->lineno);
8496 /* if the result is marked as
8497 spilt and rematerializable or code for
8498 this has already been generated then
8500 if (resultRemat(ic) || ic->generated )
8503 /* depending on the operation */
8522 /* IPOP happens only when trying to restore a
8523 spilt live range, if there is an ifx statement
8524 following this pop then the if statement might
8525 be using some of the registers being popped which
8526 would destory the contents of the register so
8527 we need to check for this condition and handle it */
8529 ic->next->op == IFX &&
8530 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
8531 genIfx (ic->next,ic);
8549 genEndFunction (ic);
8569 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
8586 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
8590 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
8597 /* note these two are xlated by algebraic equivalence
8598 during parsing SDCC.y */
8599 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8600 "got '>=' or '<=' shouldn't have come here");
8604 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
8616 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
8620 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
8624 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
8651 case GET_VALUE_AT_ADDRESS:
8656 if (POINTER_SET(ic))
8683 addSet(&_G.sendSet,ic);
8688 /* piCode(ic,stdout); */
8694 /* now we are ready to call the
8695 peep hole optimizer */
8696 if (!options.nopeep) {
8697 printf("peep hole optimizing\n");
8698 peepHole (&lineHead);
8700 /* now do the actual printing */
8701 printLine (lineHead,codeOutFile);