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"
62 //char *aopLiteral (value *val, int offset);
63 unsigned int pic14aopLiteral (value *val, int offset);
65 /* this is the down and dirty file with all kinds of
66 kludgy & hacky stuff. This is what it is all about
67 CODE GENERATION for a specific MCU . some of the
68 routines may be reusable, will have to see */
70 static char *zero = "#0x00";
71 static char *one = "#0x01";
72 static char *spname = "sp";
74 char *fReturnpic14[] = {"FSR","dph","b","a" };
75 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
76 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
77 static char **fReturn = fReturnpic14;
79 static char *accUse[] = {"a","b"};
81 //static short rbank = -1;
93 extern int pic14_ptrRegReq ;
94 extern int pic14_nRegs;
95 extern FILE *codeOutFile;
96 static void saverbank (int, iCode *,bool);
97 #define RESULTONSTACK(x) \
98 (IC_RESULT(x) && IC_RESULT(x)->aop && \
99 IC_RESULT(x)->aop->type == AOP_STK )
101 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode(";XXX mov","a,%s %s,%d",x,__FILE__,__LINE__);
102 #define CLRC emitcode(";XXX clr","c %s,%d",__FILE__,__LINE__);
104 #define BIT_NUMBER(x) (x & 7)
105 #define BIT_REGISTER(x) (x>>3)
107 static lineNode *lineHead = NULL;
108 static lineNode *lineCurr = NULL;
110 static unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
111 0xE0, 0xC0, 0x80, 0x00};
112 static unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113 0x07, 0x03, 0x01, 0x00};
121 #define FUNCTION_LABEL_INC 20
122 static int labelOffset=0;
123 static int debug_verbose=0;
127 /*-----------------------------------------------------------------*/
128 /* Macros for emitting instructions */
129 /*-----------------------------------------------------------------*/
131 #define emitSKPC emitpcode(POC_BTFSS,popCopyGPR2Bit(&pc_status,PIC_C_BIT))
132 #define emitSKPNC emitpcode(POC_BTFSC,popCopyGPR2Bit(&pc_status,PIC_C_BIT))
133 #define emitSKPZ emitpcode(POC_BTFSS,popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
134 #define emitSKPNZ emitpcode(POC_BTFSC,popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
135 #define emitCLRZ emitpcode(POC_BCF, popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
136 #define emitCLRC emitpcode(POC_BCF, popCopyGPR2Bit(&pc_status,PIC_C_BIT))
137 #define emitSETZ emitpcode(POC_BSF, popCopyGPR2Bit(&pc_status,PIC_Z_BIT))
138 #define emitSETC emitpcode(POC_BSF, popCopyGPR2Bit(&pc_status,PIC_C_BIT))
140 //#define emitSKPC emitcode("btfss","status,c")
141 //#define emitSKPNC emitcode("btfsc","status,c")
142 //#define emitSKPZ emitcode("btfss","status,z")
143 //#define emitSKPNZ emitcode("btfsc","status,z")
145 /*-----------------------------------------------------------------*/
146 /* my_powof2(n) - If `n' is an integaer power of 2, then the */
147 /* exponent of 2 is returned, otherwise -1 is */
149 /* note that this is similar to the function `powof2' in SDCCsymt */
153 /*-----------------------------------------------------------------*/
154 static int my_powof2 (unsigned long num)
157 if( (num & (num-1)) == 0) {
170 static void emitpLabel(int key)
172 addpCode2pBlock(pb,newpCodeLabel(key));
175 static void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
178 addpCode2pBlock(pb,newpCode(poc,pcop));
181 /*-----------------------------------------------------------------*/
182 /* emitcode - writes the code into a file : for now it is simple */
183 /*-----------------------------------------------------------------*/
184 static void emitcode (char *inst,char *fmt, ...)
187 char lb[MAX_INLINEASM];
194 sprintf(lb,"%s\t",inst);
196 sprintf(lb,"%s",inst);
197 vsprintf(lb+(strlen(lb)),fmt,ap);
201 while (isspace(*lbp)) lbp++;
204 lineCurr = (lineCurr ?
205 connectLine(lineCurr,newLineNode(lb)) :
206 (lineHead = newLineNode(lb)));
207 lineCurr->isInline = _G.inLine;
208 lineCurr->isDebug = _G.debugLine;
211 addpCode2pBlock(pb,newpCodeCharP(lb));
216 static void DEBUGemitcode (char *inst,char *fmt, ...)
219 char lb[MAX_INLINEASM];
229 sprintf(lb,"%s\t",inst);
231 sprintf(lb,"%s",inst);
232 vsprintf(lb+(strlen(lb)),fmt,ap);
236 while (isspace(*lbp)) lbp++;
239 lineCurr = (lineCurr ?
240 connectLine(lineCurr,newLineNode(lb)) :
241 (lineHead = newLineNode(lb)));
242 lineCurr->isInline = _G.inLine;
243 lineCurr->isDebug = _G.debugLine;
245 addpCode2pBlock(pb,newpCodeCharP(lb));
251 /*-----------------------------------------------------------------*/
252 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
253 /*-----------------------------------------------------------------*/
254 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
256 bool r0iu = FALSE , r1iu = FALSE;
257 bool r0ou = FALSE , r1ou = FALSE;
259 /* the logic: if r0 & r1 used in the instruction
260 then we are in trouble otherwise */
262 /* first check if r0 & r1 are used by this
263 instruction, in which case we are in trouble */
264 if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
265 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX)))
270 r0ou = bitVectBitValue(ic->rMask,R0_IDX);
271 r1ou = bitVectBitValue(ic->rMask,R1_IDX);
273 /* if no usage of r0 then return it */
274 if (!r0iu && !r0ou) {
275 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
276 (*aopp)->type = AOP_R0;
278 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
281 /* if no usage of r1 then return it */
282 if (!r1iu && !r1ou) {
283 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
284 (*aopp)->type = AOP_R1;
286 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
289 /* now we know they both have usage */
290 /* if r0 not used in this instruction */
292 /* push it if not already pushed */
294 emitcode ("push","%s",
295 pic14_regWithIdx(R0_IDX)->dname);
299 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
300 (*aopp)->type = AOP_R0;
302 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
305 /* if r1 not used then */
308 /* push it if not already pushed */
310 emitcode ("push","%s",
311 pic14_regWithIdx(R1_IDX)->dname);
315 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
316 (*aopp)->type = AOP_R1;
317 return pic14_regWithIdx(R1_IDX);
321 /* I said end of world but not quite end of world yet */
322 /* if this is a result then we can push it on the stack*/
324 (*aopp)->type = AOP_STK;
329 /* other wise this is true end of the world */
330 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
331 "getFreePtr should never reach here");
335 /*-----------------------------------------------------------------*/
336 /* newAsmop - creates a new asmOp */
337 /*-----------------------------------------------------------------*/
338 static asmop *newAsmop (short type)
342 aop = Safe_calloc(1,sizeof(asmop));
347 static void genSetDPTR(int n)
351 emitcode(";", "Select standard DPTR");
352 emitcode("mov", "dps, #0x00");
356 emitcode(";", "Select alternate DPTR");
357 emitcode("mov", "dps, #0x01");
361 /*-----------------------------------------------------------------*/
362 /* pointerCode - returns the code for a pointer type */
363 /*-----------------------------------------------------------------*/
364 static int pointerCode (sym_link *etype)
367 return PTR_TYPE(SPEC_OCLS(etype));
371 /*-----------------------------------------------------------------*/
372 /* aopForSym - for a true symbol */
373 /*-----------------------------------------------------------------*/
374 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
377 memmap *space= SPEC_OCLS(sym->etype);
379 DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
380 /* if already has one */
384 /* assign depending on the storage class */
385 /* if it is on the stack or indirectly addressable */
386 /* space we need to assign either r0 or r1 to it */
387 if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
388 sym->aop = aop = newAsmop(0);
389 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
390 aop->size = getSize(sym->type);
392 /* now assign the address of the variable to
393 the pointer register */
394 if (aop->type != AOP_STK) {
398 emitcode("push","acc");
400 emitcode("mov","a,_bp");
401 emitcode("add","a,#0x%02x",
403 ((char)(sym->stack - _G.nRegsSaved )) :
404 ((char)sym->stack)) & 0xff);
405 emitcode("mov","%s,a",
406 aop->aopu.aop_ptr->name);
409 emitcode("pop","acc");
411 emitcode("mov","%s,#%s",
412 aop->aopu.aop_ptr->name,
414 aop->paged = space->paged;
416 aop->aopu.aop_stk = sym->stack;
420 if (sym->onStack && options.stack10bit)
422 /* It's on the 10 bit stack, which is located in
426 //DEBUGemitcode(";","%d",__LINE__);
429 emitcode("push","acc");
431 emitcode("mov","a,_bp");
432 emitcode("add","a,#0x%02x",
434 ((char)(sym->stack - _G.nRegsSaved )) :
435 ((char)sym->stack)) & 0xff);
438 emitcode ("mov","dpx1,#0x40");
439 emitcode ("mov","dph1,#0x00");
440 emitcode ("mov","dpl1, a");
444 emitcode("pop","acc");
446 sym->aop = aop = newAsmop(AOP_DPTR2);
447 aop->size = getSize(sym->type);
451 //DEBUGemitcode(";","%d",__LINE__);
452 /* if in bit space */
453 if (IN_BITSPACE(space)) {
454 sym->aop = aop = newAsmop (AOP_CRY);
455 aop->aopu.aop_dir = sym->rname ;
456 aop->size = getSize(sym->type);
457 DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
460 /* if it is in direct space */
461 if (IN_DIRSPACE(space)) {
462 sym->aop = aop = newAsmop (AOP_DIR);
463 aop->aopu.aop_dir = sym->rname ;
464 aop->size = getSize(sym->type);
465 DEBUGemitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
469 /* special case for a function */
470 if (IS_FUNC(sym->type)) {
471 sym->aop = aop = newAsmop(AOP_IMMD);
472 //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
473 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
474 strcpy(aop->aopu.aop_immd,sym->rname);
475 aop->size = FPTRSIZE;
480 /* only remaining is far space */
481 /* in which case DPTR gets the address */
482 sym->aop = aop = newAsmop(AOP_DPTR);
483 emitcode ("mov","dptr,#%s", sym->rname);
484 aop->size = getSize(sym->type);
486 DEBUGemitcode(";","%d size = %d",__LINE__,aop->size);
487 /* if it is in code space */
488 if (IN_CODESPACE(space))
494 /*-----------------------------------------------------------------*/
495 /* aopForRemat - rematerialzes an object */
496 /*-----------------------------------------------------------------*/
497 static asmop *aopForRemat (symbol *sym)
499 iCode *ic = sym->rematiCode;
500 asmop *aop = newAsmop(AOP_IMMD);
502 DEBUGemitcode(";","%s %d",__FUNCTION__,__LINE__);
505 val += operandLitValue(IC_RIGHT(ic));
506 else if (ic->op == '-')
507 val -= operandLitValue(IC_RIGHT(ic));
511 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
515 sprintf(buffer,"(%s %c 0x%04x)",
516 OP_SYMBOL(IC_LEFT(ic))->rname,
517 val >= 0 ? '+' : '-',
520 strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
522 //DEBUGemitcode(";","%s",buffer);
523 aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
524 strcpy(aop->aopu.aop_immd,buffer);
528 /*-----------------------------------------------------------------*/
529 /* regsInCommon - two operands have some registers in common */
530 /*-----------------------------------------------------------------*/
531 static bool regsInCommon (operand *op1, operand *op2)
536 /* if they have registers in common */
537 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
540 sym1 = OP_SYMBOL(op1);
541 sym2 = OP_SYMBOL(op2);
543 if (sym1->nRegs == 0 || sym2->nRegs == 0)
546 for (i = 0 ; i < sym1->nRegs ; i++) {
551 for (j = 0 ; j < sym2->nRegs ;j++ ) {
555 if (sym2->regs[j] == sym1->regs[i])
563 /*-----------------------------------------------------------------*/
564 /* operandsEqu - equivalent */
565 /*-----------------------------------------------------------------*/
566 static bool operandsEqu ( operand *op1, operand *op2)
570 /* if they not symbols */
571 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
574 sym1 = OP_SYMBOL(op1);
575 sym2 = OP_SYMBOL(op2);
577 /* if both are itemps & one is spilt
578 and the other is not then false */
579 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
580 sym1->isspilt != sym2->isspilt )
583 /* if they are the same */
587 if (strcmp(sym1->rname,sym2->rname) == 0)
591 /* if left is a tmp & right is not */
595 (sym1->usl.spillLoc == sym2))
602 (sym2->usl.spillLoc == sym1))
608 /*-----------------------------------------------------------------*/
609 /* sameRegs - two asmops have the same registers */
610 /*-----------------------------------------------------------------*/
611 static bool sameRegs (asmop *aop1, asmop *aop2 )
618 if (aop1->type != AOP_REG ||
619 aop2->type != AOP_REG )
622 if (aop1->size != aop2->size )
625 for (i = 0 ; i < aop1->size ; i++ )
626 if (aop1->aopu.aop_reg[i] !=
627 aop2->aopu.aop_reg[i] )
633 /*-----------------------------------------------------------------*/
634 /* aopOp - allocates an asmop for an operand : */
635 /*-----------------------------------------------------------------*/
636 static void aopOp (operand *op, iCode *ic, bool result)
645 DEBUGemitcode(";","%d",__LINE__);
646 /* if this a literal */
647 if (IS_OP_LITERAL(op)) {
648 DEBUGemitcode(";","%d",__LINE__);
649 op->aop = aop = newAsmop(AOP_LIT);
650 aop->aopu.aop_lit = op->operand.valOperand;
651 aop->size = getSize(operandType(op));
655 /* if already has a asmop then continue */
659 /* if the underlying symbol has a aop */
660 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
661 DEBUGemitcode(";","%d",__LINE__);
662 op->aop = OP_SYMBOL(op)->aop;
666 /* if this is a true symbol */
667 if (IS_TRUE_SYMOP(op)) {
668 DEBUGemitcode(";","%d",__LINE__);
669 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
673 /* this is a temporary : this has
679 e) can be a return use only */
684 /* if the type is a conditional */
685 if (sym->regType == REG_CND) {
686 DEBUGemitcode(";","%d",__LINE__);
687 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
692 /* if it is spilt then two situations
694 b) has a spill location */
695 if (sym->isspilt || sym->nRegs == 0) {
697 DEBUGemitcode(";","%d",__LINE__);
698 /* rematerialize it NOW */
700 sym->aop = op->aop = aop =
702 aop->size = getSize(sym->type);
703 DEBUGemitcode(";","%d",__LINE__);
709 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
710 aop->size = getSize(sym->type);
711 for ( i = 0 ; i < 2 ; i++ )
712 aop->aopu.aop_str[i] = accUse[i];
713 DEBUGemitcode(";","%d",__LINE__);
719 aop = op->aop = sym->aop = newAsmop(AOP_STR);
720 aop->size = getSize(sym->type);
721 for ( i = 0 ; i < fReturnSizePic ; i++ )
722 aop->aopu.aop_str[i] = fReturn[i];
723 DEBUGemitcode(";","%d",__LINE__);
727 /* else spill location */
728 DEBUGemitcode(";","%s %d %s",__FUNCTION__,__LINE__,sym->usl.spillLoc->rname);
729 sym->aop = op->aop = aop =
730 aopForSym(ic,sym->usl.spillLoc,result);
731 aop->size = getSize(sym->type);
735 /* must be in a register */
736 sym->aop = op->aop = aop = newAsmop(AOP_REG);
737 aop->size = sym->nRegs;
738 for ( i = 0 ; i < sym->nRegs ;i++)
739 aop->aopu.aop_reg[i] = sym->regs[i];
742 /*-----------------------------------------------------------------*/
743 /* freeAsmop - free up the asmop given to an operand */
744 /*----------------------------------------------------------------*/
745 static void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
762 /* depending on the asmop type only three cases need work AOP_RO
763 , AOP_R1 && AOP_STK */
768 emitcode ("pop","ar0");
772 bitVectUnSetBit(ic->rUsed,R0_IDX);
778 emitcode ("pop","ar1");
782 bitVectUnSetBit(ic->rUsed,R1_IDX);
788 int stk = aop->aopu.aop_stk + aop->size;
789 bitVectUnSetBit(ic->rUsed,R0_IDX);
790 bitVectUnSetBit(ic->rUsed,R1_IDX);
792 getFreePtr(ic,&aop,FALSE);
794 if (options.stack10bit)
796 /* I'm not sure what to do here yet... */
799 "*** Warning: probably generating bad code for "
800 "10 bit stack mode.\n");
804 emitcode ("mov","a,_bp");
805 emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
806 emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
808 emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
812 emitcode("pop","acc");
813 emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
815 emitcode("dec","%s",aop->aopu.aop_ptr->name);
818 freeAsmop(op,NULL,ic,TRUE);
820 emitcode("pop","ar0");
825 emitcode("pop","ar1");
832 /* all other cases just dealloc */
836 OP_SYMBOL(op)->aop = NULL;
837 /* if the symbol has a spill */
839 SPIL_LOC(op)->aop = NULL;
844 /*-----------------------------------------------------------------*/
845 /* aopGet - for fetching value of the aop */
846 /*-----------------------------------------------------------------*/
847 static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
852 //DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
853 /* offset is greater than
855 if (offset > (aop->size - 1) &&
856 aop->type != AOP_LIT)
859 /* depending on type */
864 DEBUGemitcode(";","%d",__LINE__);
865 /* if we need to increment it */
866 while (offset > aop->coff) {
867 emitcode ("inc","%s",aop->aopu.aop_ptr->name);
871 while (offset < aop->coff) {
872 emitcode("dec","%s",aop->aopu.aop_ptr->name);
878 emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
879 return (dname ? "acc" : "a");
881 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
882 rs = Safe_calloc(1,strlen(s)+1);
888 DEBUGemitcode(";","%d",__LINE__);
889 if (aop->type == AOP_DPTR2)
894 while (offset > aop->coff) {
895 emitcode ("inc","dptr");
899 while (offset < aop->coff) {
900 emitcode("lcall","__decdptr");
907 emitcode("movc","a,@a+dptr");
910 emitcode("movx","a,@dptr");
913 if (aop->type == AOP_DPTR2)
918 return (dname ? "acc" : "a");
922 DEBUGemitcode(";","%d",__LINE__);
924 sprintf (s,"%s",aop->aopu.aop_immd);
927 sprintf(s,"(%s >> %d)",
933 rs = Safe_calloc(1,strlen(s)+1);
939 sprintf(s,"(%s + %d)",
943 sprintf(s,"%s",aop->aopu.aop_dir);
944 rs = Safe_calloc(1,strlen(s)+1);
949 DEBUGemitcode(";","%d",__LINE__);
951 return aop->aopu.aop_reg[offset]->dname;
953 return aop->aopu.aop_reg[offset]->name;
956 emitcode(";","%d",__LINE__);
957 //emitcode("clr","a");
958 //emitcode("mov","c,%s",aop->aopu.aop_dir);
959 //emitcode("rlc","a") ;
960 //return (dname ? "acc" : "a");
961 return aop->aopu.aop_dir;
964 DEBUGemitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
965 //if (!offset && dname)
967 //return aop->aopu.aop_str[offset];
968 return "AOP_accumulator_bug";
971 DEBUGemitcode(";","%d",__LINE__);
972 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
973 rs = Safe_calloc(1,strlen(s)+1);
978 DEBUGemitcode(";","%d",__LINE__);
980 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
984 return aop->aopu.aop_str[offset];
988 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
989 "aopget got unsupported aop->type");
993 /*-----------------------------------------------------------------*/
994 /* popGetLabel - create a new pCodeOp of type PO_LABEL */
995 /*-----------------------------------------------------------------*/
996 static pCodeOp *popGetLabel(unsigned int key)
998 return newpCodeOpLabel(key+100+labelOffset);
1001 /*-----------------------------------------------------------------*/
1002 /* popCopy - copy a pcode operator */
1003 /*-----------------------------------------------------------------*/
1004 static pCodeOp *popCopy(pCodeOp *pc)
1008 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1009 pcop->type = pc->type;
1010 if(!(pcop->name = strdup(pc->name)))
1011 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1016 /*-----------------------------------------------------------------*/
1017 /* popCopy - copy a pcode operator */
1018 /*-----------------------------------------------------------------*/
1019 static pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
1023 pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1024 pcop->type = PO_BIT;
1025 if(!(pcop->name = strdup(pc->name)))
1026 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1027 ((pCodeOpBit *)pcop)->bit = bitval;
1029 ((pCodeOpBit *)pcop)->inBitSpace = 0; //(pc->type == PO_BIT) ? 1 : 0;
1034 /*-----------------------------------------------------------------*/
1035 /* popGet - asm operator to pcode operator conversion */
1036 /*-----------------------------------------------------------------*/
1037 static pCodeOp *popGetLit(unsigned int lit)
1040 return newpCodeOpLit(lit);
1044 /*-----------------------------------------------------------------*/
1045 /* popGet - asm operator to pcode operator conversion */
1046 /*-----------------------------------------------------------------*/
1047 static pCodeOp *popGetWithString(char *str)
1053 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1057 pcop = newpCodeOp(str,PO_STR);
1061 /*-----------------------------------------------------------------*/
1062 /* popGet - asm operator to pcode operator conversion */
1063 /*-----------------------------------------------------------------*/
1064 static pCodeOp *popGet (asmop *aop, int offset, bool bit16, bool dname)
1071 //DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1072 /* offset is greater than
1075 if (offset > (aop->size - 1) &&
1076 aop->type != AOP_LIT)
1077 return NULL; //zero;
1079 /* depending on type */
1080 switch (aop->type) {
1087 DEBUGemitcode(";8051 legacy","%d",__LINE__);
1091 DEBUGemitcode(";","%d",__LINE__);
1092 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1093 pcop->type = PO_IMMEDIATE;
1095 sprintf (s,"%s",aop->aopu.aop_immd);
1098 sprintf(s,"(%s >> %d)",
1103 aop->aopu.aop_immd);
1104 pcop->name = Safe_calloc(1,strlen(s)+1);
1105 strcpy(pcop->name,s);
1109 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1110 pcop->type = PO_DIR;
1112 sprintf(s,"(%s + %d)",
1116 sprintf(s,"%s",aop->aopu.aop_dir);
1117 pcop->name = Safe_calloc(1,strlen(s)+1);
1118 strcpy(pcop->name,s);
1125 DEBUGemitcode(";","%d",__LINE__);
1126 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1127 pcop->type = PO_GPR_REGISTER;
1129 rs = aop->aopu.aop_reg[offset]->dname;
1131 rs = aop->aopu.aop_reg[offset]->name;
1133 PCOR(pcop)->rIdx = aop->aopu.aop_reg[offset]->rIdx;
1134 PCOR(pcop)->r = pic14_regWithIdx(aop->aopu.aop_reg[offset]->rIdx);
1135 // Really nasty hack to check for temporary registers
1137 if(len >=3 && rs[0]=='r' && rs[1]=='0' && rs[2]=='x')
1138 pcop->type = PO_GPR_TEMP;
1140 fprintf(stderr,"popGet - AOP_REG is not a temp: %s\n",rs);
1142 DEBUGemitcode(";","%d %s",__LINE__,rs);
1143 pcop->name = NULL;// Safe_calloc(1,(strlen(rs)+1));
1144 //strcpy(pcop->name,rs);
1149 pcop = newpCodeOpBit(aop->aopu.aop_dir,0);
1153 DEBUGemitcode(";","%d",__LINE__);
1154 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1157 DEBUGemitcode(";","%d",__LINE__);
1159 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1160 pcop->type = PO_STR;
1162 //aop->coff = offset ;
1163 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && dname)
1164 sprintf(s,"%s","acc");
1166 sprintf(s,"%s",aop->aopu.aop_str[offset]);
1167 pcop->name = Safe_calloc(1,strlen(s)+1);
1168 strcpy(pcop->name,s);
1173 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1174 "popGet got unsupported aop->type");
1177 /*-----------------------------------------------------------------*/
1178 /* aopPut - puts a string for a aop */
1179 /*-----------------------------------------------------------------*/
1180 static void aopPut (asmop *aop, char *s, int offset)
1185 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1187 if (aop->size && offset > ( aop->size - 1)) {
1188 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1189 "aopPut got offset > aop->size");
1193 /* will assign value to value */
1194 /* depending on where it is ofcourse */
1195 switch (aop->type) {
1198 sprintf(d,"(%s + %d)",
1199 aop->aopu.aop_dir,offset);
1201 sprintf(d,"%s",aop->aopu.aop_dir);
1204 DEBUGemitcode(";","%d",__LINE__);
1206 emitcode("movf","%s,w",s);
1207 emitcode("movwf","%s",d);
1210 emitcode(";BUG! should have this:movf","%s,w %d",s,__LINE__);
1211 emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1218 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
1219 strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1222 strcmp(s,"r0") == 0 ||
1223 strcmp(s,"r1") == 0 ||
1224 strcmp(s,"r2") == 0 ||
1225 strcmp(s,"r3") == 0 ||
1226 strcmp(s,"r4") == 0 ||
1227 strcmp(s,"r5") == 0 ||
1228 strcmp(s,"r6") == 0 ||
1229 strcmp(s,"r7") == 0 )
1230 emitcode("mov","%s,%s ; %d",
1231 aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1236 emitcode("movf","%s,w ; %d",s,__LINE__);
1238 emitcode("movwf","%s",
1239 aop->aopu.aop_reg[offset]->name);
1242 emitcode(";BUG! should have this:movf","%s,w %d",s,__LINE__);
1243 emitpcode(POC_MOVWF,popGet(aop,offset,FALSE,FALSE));
1251 if (aop->type == AOP_DPTR2)
1257 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1258 "aopPut writting to code space");
1262 while (offset > aop->coff) {
1264 emitcode ("inc","dptr");
1267 while (offset < aop->coff) {
1269 emitcode("lcall","__decdptr");
1274 /* if not in accumulater */
1277 emitcode ("movx","@dptr,a");
1279 if (aop->type == AOP_DPTR2)
1287 while (offset > aop->coff) {
1289 emitcode("inc","%s",aop->aopu.aop_ptr->name);
1291 while (offset < aop->coff) {
1293 emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1299 emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1304 emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1306 if (strcmp(s,"r0") == 0 ||
1307 strcmp(s,"r1") == 0 ||
1308 strcmp(s,"r2") == 0 ||
1309 strcmp(s,"r3") == 0 ||
1310 strcmp(s,"r4") == 0 ||
1311 strcmp(s,"r5") == 0 ||
1312 strcmp(s,"r6") == 0 ||
1313 strcmp(s,"r7") == 0 ) {
1315 sprintf(buffer,"a%s",s);
1316 emitcode("mov","@%s,%s",
1317 aop->aopu.aop_ptr->name,buffer);
1319 emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1324 if (strcmp(s,"a") == 0)
1325 emitcode("push","acc");
1327 emitcode("push","%s",s);
1332 /* if bit variable */
1333 if (!aop->aopu.aop_dir) {
1334 emitcode("clr","a");
1335 emitcode("rlc","a");
1338 emitcode("clr","%s",aop->aopu.aop_dir);
1341 emitcode("setb","%s",aop->aopu.aop_dir);
1344 emitcode("mov","%s,c",aop->aopu.aop_dir);
1346 lbl = newiTempLabel(NULL);
1348 if (strcmp(s,"a")) {
1351 emitcode("clr","c");
1352 emitcode("jz","%05d_DS_",lbl->key+100);
1353 emitcode("cpl","c");
1354 emitcode("","%05d_DS_:",lbl->key+100);
1355 emitcode("mov","%s,c",aop->aopu.aop_dir);
1362 if (strcmp(aop->aopu.aop_str[offset],s))
1363 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1368 if (!offset && (strcmp(s,"acc") == 0))
1371 if (strcmp(aop->aopu.aop_str[offset],s))
1372 emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1376 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1377 "aopPut got unsupported aop->type");
1383 /*-----------------------------------------------------------------*/
1384 /* reAdjustPreg - points a register back to where it should */
1385 /*-----------------------------------------------------------------*/
1386 static void reAdjustPreg (asmop *aop)
1390 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1392 if ((size = aop->size) <= 1)
1395 switch (aop->type) {
1399 emitcode("dec","%s",aop->aopu.aop_ptr->name);
1403 if (aop->type == AOP_DPTR2)
1409 emitcode("lcall","__decdptr");
1412 if (aop->type == AOP_DPTR2)
1422 #define AOP(op) op->aop
1423 #define AOP_TYPE(op) AOP(op)->type
1424 #define AOP_SIZE(op) AOP(op)->size
1425 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1426 AOP_TYPE(x) == AOP_R0))
1428 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1429 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1432 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1433 (x->aopu.aop_reg[0] == pic14_regWithIdx(R0_IDX) || \
1434 x->aopu.aop_reg[0] == pic14_regWithIdx(R1_IDX) )))
1436 /*-----------------------------------------------------------------*/
1437 /* genNotFloat - generates not for float operations */
1438 /*-----------------------------------------------------------------*/
1439 static void genNotFloat (operand *op, operand *res)
1445 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1446 /* we will put 127 in the first byte of
1448 aopPut(AOP(res),"#127",0);
1449 size = AOP_SIZE(op) - 1;
1452 l = aopGet(op->aop,offset++,FALSE,FALSE);
1456 emitcode("orl","a,%s",
1458 offset++,FALSE,FALSE));
1460 tlbl = newiTempLabel(NULL);
1462 tlbl = newiTempLabel(NULL);
1463 aopPut(res->aop,one,1);
1464 emitcode("jz","%05d_DS_",(tlbl->key+100));
1465 aopPut(res->aop,zero,1);
1466 emitcode("","%05d_DS_:",(tlbl->key+100));
1468 size = res->aop->size - 2;
1470 /* put zeros in the rest */
1472 aopPut(res->aop,zero,offset++);
1476 /*-----------------------------------------------------------------*/
1477 /* opIsGptr: returns non-zero if the passed operand is */
1478 /* a generic pointer type. */
1479 /*-----------------------------------------------------------------*/
1480 static int opIsGptr(operand *op)
1482 sym_link *type = operandType(op);
1484 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1485 if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1493 /*-----------------------------------------------------------------*/
1494 /* getDataSize - get the operand data size */
1495 /*-----------------------------------------------------------------*/
1496 static int getDataSize(operand *op)
1498 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1501 return AOP_SIZE(op);
1503 // tsd- in the pic port, the genptr size is 1, so this code here
1504 // fails. ( in the 8051 port, the size was 4).
1507 size = AOP_SIZE(op);
1508 if (size == GPTRSIZE)
1510 sym_link *type = operandType(op);
1511 if (IS_GENPTR(type))
1513 /* generic pointer; arithmetic operations
1514 * should ignore the high byte (pointer type).
1517 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1524 /*-----------------------------------------------------------------*/
1525 /* outAcc - output Acc */
1526 /*-----------------------------------------------------------------*/
1527 static void outAcc(operand *result)
1530 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1531 size = getDataSize(result);
1533 aopPut(AOP(result),"a",0);
1536 /* unsigned or positive */
1538 aopPut(AOP(result),zero,offset++);
1543 /*-----------------------------------------------------------------*/
1544 /* outBitC - output a bit C */
1545 /*-----------------------------------------------------------------*/
1546 static void outBitC(operand *result)
1549 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1550 /* if the result is bit */
1551 if (AOP_TYPE(result) == AOP_CRY)
1552 aopPut(AOP(result),"c",0);
1554 emitcode("clr","a ; %d", __LINE__);
1555 emitcode("rlc","a");
1560 /*-----------------------------------------------------------------*/
1561 /* toBoolean - emit code for orl a,operator(sizeop) */
1562 /*-----------------------------------------------------------------*/
1563 static void toBoolean(operand *oper)
1565 int size = AOP_SIZE(oper) - 1;
1568 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1570 if ( AOP_TYPE(oper) != AOP_ACC) {
1571 emitpcode(POC_MOVFW,popGet(AOP(oper),0,FALSE,FALSE));
1572 emitcode("movf","%s,w",aopGet(AOP(oper),0,FALSE,FALSE));
1575 emitcode("iorwf","%s,w",aopGet(AOP(oper),offset,FALSE,FALSE));
1576 emitpcode(POC_IORFW, popGet(AOP(oper),offset++,FALSE,FALSE));
1581 /*-----------------------------------------------------------------*/
1582 /* genNot - generate code for ! operation */
1583 /*-----------------------------------------------------------------*/
1584 static void genNot (iCode *ic)
1587 sym_link *optype = operandType(IC_LEFT(ic));
1589 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1590 /* assign asmOps to operand & result */
1591 aopOp (IC_LEFT(ic),ic,FALSE);
1592 aopOp (IC_RESULT(ic),ic,TRUE);
1594 /* if in bit space then a special case */
1595 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1596 emitcode("movlw","1<<%s");
1597 //emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1598 //emitcode("cpl","c");
1599 //outBitC(IC_RESULT(ic));
1603 /* if type float then do float */
1604 if (IS_FLOAT(optype)) {
1605 genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1609 toBoolean(IC_LEFT(ic));
1611 tlbl = newiTempLabel(NULL);
1612 emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1613 emitcode("","%05d_DS_:",tlbl->key+100);
1614 outBitC(IC_RESULT(ic));
1617 /* release the aops */
1618 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1619 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1623 /*-----------------------------------------------------------------*/
1624 /* genCpl - generate code for complement */
1625 /*-----------------------------------------------------------------*/
1626 static void genCpl (iCode *ic)
1632 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1633 /* assign asmOps to operand & result */
1634 aopOp (IC_LEFT(ic),ic,FALSE);
1635 aopOp (IC_RESULT(ic),ic,TRUE);
1637 /* if both are in bit space then
1639 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1640 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1642 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1643 emitcode("cpl","c");
1644 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1648 size = AOP_SIZE(IC_RESULT(ic));
1650 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1652 emitcode("cpl","a");
1653 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1658 /* release the aops */
1659 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1660 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1663 /*-----------------------------------------------------------------*/
1664 /* genUminusFloat - unary minus for floating points */
1665 /*-----------------------------------------------------------------*/
1666 static void genUminusFloat(operand *op,operand *result)
1668 int size ,offset =0 ;
1671 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1672 /* for this we just need to flip the
1673 first it then copy the rest in place */
1674 size = AOP_SIZE(op) - 1;
1675 l = aopGet(AOP(op),3,FALSE,FALSE);
1679 emitcode("cpl","acc.7");
1680 aopPut(AOP(result),"a",3);
1684 aopGet(AOP(op),offset,FALSE,FALSE),
1690 /*-----------------------------------------------------------------*/
1691 /* genUminus - unary minus code generation */
1692 /*-----------------------------------------------------------------*/
1693 static void genUminus (iCode *ic)
1696 sym_link *optype, *rtype;
1699 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1701 aopOp(IC_LEFT(ic),ic,FALSE);
1702 aopOp(IC_RESULT(ic),ic,TRUE);
1704 /* if both in bit space then special
1706 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1707 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1709 emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir);
1710 emitcode("cpl","c");
1711 emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir);
1715 optype = operandType(IC_LEFT(ic));
1716 rtype = operandType(IC_RESULT(ic));
1718 /* if float then do float stuff */
1719 if (IS_FLOAT(optype)) {
1720 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1724 /* otherwise subtract from zero */
1725 size = AOP_SIZE(IC_LEFT(ic));
1729 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1730 if (!strcmp(l,"a")) {
1731 emitcode("cpl","a");
1732 emitcode("inc","a");
1734 emitcode("clr","a");
1735 emitcode("subb","a,%s",l);
1737 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1740 /* if any remaining bytes in the result */
1741 /* we just need to propagate the sign */
1742 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1743 emitcode("rlc","a");
1744 emitcode("subb","a,acc");
1746 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1750 /* release the aops */
1751 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1752 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1755 /*-----------------------------------------------------------------*/
1756 /* saveRegisters - will look for a call and save the registers */
1757 /*-----------------------------------------------------------------*/
1758 static void saveRegisters(iCode *lic)
1765 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1767 for (ic = lic ; ic ; ic = ic->next)
1768 if (ic->op == CALL || ic->op == PCALL)
1772 fprintf(stderr,"found parameter push with no function call\n");
1776 /* if the registers have been saved already then
1778 if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
1781 /* find the registers in use at this time
1782 and push them away to safety */
1783 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1787 if (options.useXstack) {
1788 if (bitVectBitValue(rsave,R0_IDX))
1789 emitcode("mov","b,r0");
1790 emitcode("mov","r0,%s",spname);
1791 for (i = 0 ; i < pic14_nRegs ; i++) {
1792 if (bitVectBitValue(rsave,i)) {
1794 emitcode("mov","a,b");
1796 emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1797 emitcode("movx","@r0,a");
1798 emitcode("inc","r0");
1801 emitcode("mov","%s,r0",spname);
1802 if (bitVectBitValue(rsave,R0_IDX))
1803 emitcode("mov","r0,b");
1805 for (i = 0 ; i < pic14_nRegs ; i++) {
1806 if (bitVectBitValue(rsave,i))
1807 emitcode("push","%s",pic14_regWithIdx(i)->dname);
1810 detype = getSpec(operandType(IC_LEFT(ic)));
1812 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
1813 IS_ISR(currFunc->etype) &&
1816 saverbank(SPEC_BANK(detype),ic,TRUE);
1819 /*-----------------------------------------------------------------*/
1820 /* unsaveRegisters - pop the pushed registers */
1821 /*-----------------------------------------------------------------*/
1822 static void unsaveRegisters (iCode *ic)
1827 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1828 /* find the registers in use at this time
1829 and push them away to safety */
1830 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1833 if (options.useXstack) {
1834 emitcode("mov","r0,%s",spname);
1835 for (i = pic14_nRegs ; i >= 0 ; i--) {
1836 if (bitVectBitValue(rsave,i)) {
1837 emitcode("dec","r0");
1838 emitcode("movx","a,@r0");
1840 emitcode("mov","b,a");
1842 emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
1846 emitcode("mov","%s,r0",spname);
1847 if (bitVectBitValue(rsave,R0_IDX))
1848 emitcode("mov","r0,b");
1850 for (i = pic14_nRegs ; i >= 0 ; i--) {
1851 if (bitVectBitValue(rsave,i))
1852 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
1858 /*-----------------------------------------------------------------*/
1860 /*-----------------------------------------------------------------*/
1861 static void pushSide(operand * oper, int size)
1864 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1866 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
1867 if (AOP_TYPE(oper) != AOP_REG &&
1868 AOP_TYPE(oper) != AOP_DIR &&
1870 emitcode("mov","a,%s",l);
1871 emitcode("push","acc");
1873 emitcode("push","%s",l);
1877 /*-----------------------------------------------------------------*/
1878 /* assignResultValue - */
1879 /*-----------------------------------------------------------------*/
1880 static void assignResultValue(operand * oper)
1883 int size = AOP_SIZE(oper);
1885 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1887 // The last byte in the assignment is in W
1888 aopPut(AOP(oper),"W",size-1);
1892 aopPut(AOP(oper),fReturn[offset],offset);
1900 /*-----------------------------------------------------------------*/
1901 /* genXpush - pushes onto the external stack */
1902 /*-----------------------------------------------------------------*/
1903 static void genXpush (iCode *ic)
1905 asmop *aop = newAsmop(0);
1907 int size,offset = 0;
1909 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1910 aopOp(IC_LEFT(ic),ic,FALSE);
1911 r = getFreePtr(ic,&aop,FALSE);
1914 emitcode("mov","%s,_spx",r->name);
1916 size = AOP_SIZE(IC_LEFT(ic));
1919 char *l = aopGet(AOP(IC_LEFT(ic)),
1920 offset++,FALSE,FALSE);
1922 emitcode("movx","@%s,a",r->name);
1923 emitcode("inc","%s",r->name);
1928 emitcode("mov","_spx,%s",r->name);
1930 freeAsmop(NULL,aop,ic,TRUE);
1931 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1934 /*-----------------------------------------------------------------*/
1935 /* genIpush - genrate code for pushing this gets a little complex */
1936 /*-----------------------------------------------------------------*/
1937 static void genIpush (iCode *ic)
1939 int size, offset = 0 ;
1943 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
1944 /* if this is not a parm push : ie. it is spill push
1945 and spill push is always done on the local stack */
1946 if (!ic->parmPush) {
1948 /* and the item is spilt then do nothing */
1949 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1952 aopOp(IC_LEFT(ic),ic,FALSE);
1953 size = AOP_SIZE(IC_LEFT(ic));
1954 /* push it on the stack */
1956 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1961 emitcode("push","%s",l);
1966 /* this is a paramter push: in this case we call
1967 the routine to find the call and save those
1968 registers that need to be saved */
1971 /* if use external stack then call the external
1972 stack pushing routine */
1973 if (options.useXstack) {
1978 /* then do the push */
1979 aopOp(IC_LEFT(ic),ic,FALSE);
1982 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1983 size = AOP_SIZE(IC_LEFT(ic));
1986 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
1987 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG &&
1988 AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
1990 emitcode("mov","a,%s",l);
1991 emitcode("push","acc");
1993 emitcode("push","%s",l);
1996 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
1999 /*-----------------------------------------------------------------*/
2000 /* genIpop - recover the registers: can happen only for spilling */
2001 /*-----------------------------------------------------------------*/
2002 static void genIpop (iCode *ic)
2007 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2008 /* if the temp was not pushed then */
2009 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2012 aopOp(IC_LEFT(ic),ic,FALSE);
2013 size = AOP_SIZE(IC_LEFT(ic));
2016 emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2019 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2022 /*-----------------------------------------------------------------*/
2023 /* unsaverbank - restores the resgister bank from stack */
2024 /*-----------------------------------------------------------------*/
2025 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2031 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2033 if (options.useXstack) {
2035 r = getFreePtr(ic,&aop,FALSE);
2038 emitcode("mov","%s,_spx",r->name);
2039 emitcode("movx","a,@%s",r->name);
2040 emitcode("mov","psw,a");
2041 emitcode("dec","%s",r->name);
2044 emitcode ("pop","psw");
2047 for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2048 if (options.useXstack) {
2049 emitcode("movx","a,@%s",r->name);
2050 //emitcode("mov","(%s+%d),a",
2051 // regspic14[i].base,8*bank+regspic14[i].offset);
2052 emitcode("dec","%s",r->name);
2055 emitcode("pop",""); //"(%s+%d)",
2056 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2059 if (options.useXstack) {
2061 emitcode("mov","_spx,%s",r->name);
2062 freeAsmop(NULL,aop,ic,TRUE);
2067 /*-----------------------------------------------------------------*/
2068 /* saverbank - saves an entire register bank on the stack */
2069 /*-----------------------------------------------------------------*/
2070 static void saverbank (int bank, iCode *ic, bool pushPsw)
2076 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2077 if (options.useXstack) {
2080 r = getFreePtr(ic,&aop,FALSE);
2081 emitcode("mov","%s,_spx",r->name);
2085 for (i = 0 ; i < pic14_nRegs ;i++) {
2086 if (options.useXstack) {
2087 emitcode("inc","%s",r->name);
2088 //emitcode("mov","a,(%s+%d)",
2089 // regspic14[i].base,8*bank+regspic14[i].offset);
2090 emitcode("movx","@%s,a",r->name);
2092 emitcode("push","");// "(%s+%d)",
2093 //regspic14[i].base,8*bank+regspic14[i].offset);
2097 if (options.useXstack) {
2098 emitcode("mov","a,psw");
2099 emitcode("movx","@%s,a",r->name);
2100 emitcode("inc","%s",r->name);
2101 emitcode("mov","_spx,%s",r->name);
2102 freeAsmop (NULL,aop,ic,TRUE);
2105 emitcode("push","psw");
2107 emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2113 /*-----------------------------------------------------------------*/
2114 /* genCall - generates a call statement */
2115 /*-----------------------------------------------------------------*/
2116 static void genCall (iCode *ic)
2120 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2122 /* if caller saves & we have not saved then */
2126 /* if we are calling a function that is not using
2127 the same register bank then we need to save the
2128 destination registers on the stack */
2129 detype = getSpec(operandType(IC_LEFT(ic)));
2131 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
2132 IS_ISR(currFunc->etype) &&
2135 saverbank(SPEC_BANK(detype),ic,TRUE);
2137 /* if send set is not empty the assign */
2141 for (sic = setFirstItem(_G.sendSet) ; sic ;
2142 sic = setNextItem(_G.sendSet)) {
2143 int size, offset = 0;
2145 aopOp(IC_LEFT(sic),sic,FALSE);
2146 size = AOP_SIZE(IC_LEFT(sic));
2148 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2150 DEBUGemitcode(";","%d - left type %d",__LINE__,AOP(IC_LEFT(sic))->type);
2152 if (strcmp(l,fReturn[offset])) {
2154 if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
2155 ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2156 emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2157 //emitcode("movlw","%s",l);
2159 emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),size,FALSE,FALSE));
2160 //emitcode("movf","%s,w",l);
2162 // The last one is passed in W
2164 emitcode("movwf","%s",fReturn[offset]);
2168 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2173 emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2174 OP_SYMBOL(IC_LEFT(ic))->rname :
2175 OP_SYMBOL(IC_LEFT(ic))->name));
2177 emitcode("call","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2178 OP_SYMBOL(IC_LEFT(ic))->rname :
2179 OP_SYMBOL(IC_LEFT(ic))->name));
2181 /* if we need assign a result value */
2182 if ((IS_ITEMP(IC_RESULT(ic)) &&
2183 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2184 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2185 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2188 aopOp(IC_RESULT(ic),ic,FALSE);
2191 assignResultValue(IC_RESULT(ic));
2193 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2196 /* adjust the stack for parameters if
2198 if (ic->parmBytes) {
2200 if (ic->parmBytes > 3) {
2201 emitcode("mov","a,%s",spname);
2202 emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2203 emitcode("mov","%s,a",spname);
2205 for ( i = 0 ; i < ic->parmBytes ;i++)
2206 emitcode("dec","%s",spname);
2210 /* if register bank was saved then pop them */
2212 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2214 /* if we hade saved some registers then unsave them */
2215 if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
2216 unsaveRegisters (ic);
2221 /*-----------------------------------------------------------------*/
2222 /* genPcall - generates a call by pointer statement */
2223 /*-----------------------------------------------------------------*/
2224 static void genPcall (iCode *ic)
2227 symbol *rlbl = newiTempLabel(NULL);
2230 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2231 /* if caller saves & we have not saved then */
2235 /* if we are calling a function that is not using
2236 the same register bank then we need to save the
2237 destination registers on the stack */
2238 detype = getSpec(operandType(IC_LEFT(ic)));
2240 IS_ISR(currFunc->etype) &&
2241 (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
2242 saverbank(SPEC_BANK(detype),ic,TRUE);
2245 /* push the return address on to the stack */
2246 emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2247 emitcode("push","acc");
2248 emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2249 emitcode("push","acc");
2251 if (options.model == MODEL_FLAT24)
2253 emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2254 emitcode("push","acc");
2257 /* now push the calling address */
2258 aopOp(IC_LEFT(ic),ic,FALSE);
2260 pushSide(IC_LEFT(ic), FPTRSIZE);
2262 freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2264 /* if send set is not empty the assign */
2268 for (sic = setFirstItem(_G.sendSet) ; sic ;
2269 sic = setNextItem(_G.sendSet)) {
2270 int size, offset = 0;
2271 aopOp(IC_LEFT(sic),sic,FALSE);
2272 size = AOP_SIZE(IC_LEFT(sic));
2274 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2276 if (strcmp(l,fReturn[offset]))
2277 emitcode("mov","%s,%s",
2282 freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2288 emitcode("","%05d_DS_:",(rlbl->key+100));
2291 /* if we need assign a result value */
2292 if ((IS_ITEMP(IC_RESULT(ic)) &&
2293 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2294 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2295 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2298 aopOp(IC_RESULT(ic),ic,FALSE);
2301 assignResultValue(IC_RESULT(ic));
2303 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2306 /* adjust the stack for parameters if
2308 if (ic->parmBytes) {
2310 if (ic->parmBytes > 3) {
2311 emitcode("mov","a,%s",spname);
2312 emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2313 emitcode("mov","%s,a",spname);
2315 for ( i = 0 ; i < ic->parmBytes ;i++)
2316 emitcode("dec","%s",spname);
2320 /* if register bank was saved then unsave them */
2322 (SPEC_BANK(currFunc->etype) !=
2324 unsaverbank(SPEC_BANK(detype),ic,TRUE);
2326 /* if we hade saved some registers then
2329 unsaveRegisters (ic);
2333 /*-----------------------------------------------------------------*/
2334 /* resultRemat - result is rematerializable */
2335 /*-----------------------------------------------------------------*/
2336 static int resultRemat (iCode *ic)
2338 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2339 if (SKIP_IC(ic) || ic->op == IFX)
2342 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2343 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2344 if (sym->remat && !POINTER_SET(ic))
2351 #if defined(__BORLANDC__) || defined(_MSC_VER)
2352 #define STRCASECMP stricmp
2354 #define STRCASECMP strcasecmp
2357 /*-----------------------------------------------------------------*/
2358 /* inExcludeList - return 1 if the string is in exclude Reg list */
2359 /*-----------------------------------------------------------------*/
2360 static bool inExcludeList(char *s)
2364 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2365 if (options.excludeRegs[i] &&
2366 STRCASECMP(options.excludeRegs[i],"none") == 0)
2369 for ( i = 0 ; options.excludeRegs[i]; i++) {
2370 if (options.excludeRegs[i] &&
2371 STRCASECMP(s,options.excludeRegs[i]) == 0)
2377 /*-----------------------------------------------------------------*/
2378 /* genFunction - generated code for function entry */
2379 /*-----------------------------------------------------------------*/
2380 static void genFunction (iCode *ic)
2385 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2386 labelOffset += FUNCTION_LABEL_INC;
2389 /* create the function header */
2390 emitcode(";","-----------------------------------------");
2391 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2392 emitcode(";","-----------------------------------------");
2394 emitcode("","%s:",sym->rname);
2395 addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2397 fetype = getSpec(operandType(IC_LEFT(ic)));
2399 /* if critical function then turn interrupts off */
2400 if (SPEC_CRTCL(fetype))
2401 emitcode("clr","ea");
2403 /* here we need to generate the equates for the
2404 register bank if required */
2406 if (SPEC_BANK(fetype) != rbank) {
2409 rbank = SPEC_BANK(fetype);
2410 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2411 if (strcmp(regspic14[i].base,"0") == 0)
2412 emitcode("","%s = 0x%02x",
2414 8*rbank+regspic14[i].offset);
2416 emitcode ("","%s = %s + 0x%02x",
2419 8*rbank+regspic14[i].offset);
2424 /* if this is an interrupt service routine then
2425 save acc, b, dpl, dph */
2426 if (IS_ISR(sym->etype)) {
2428 if (!inExcludeList("acc"))
2429 emitcode ("push","acc");
2430 if (!inExcludeList("b"))
2431 emitcode ("push","b");
2432 if (!inExcludeList("dpl"))
2433 emitcode ("push","dpl");
2434 if (!inExcludeList("dph"))
2435 emitcode ("push","dph");
2436 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2438 emitcode ("push", "dpx");
2439 /* Make sure we're using standard DPTR */
2440 emitcode ("push", "dps");
2441 emitcode ("mov", "dps, #0x00");
2442 if (options.stack10bit)
2444 /* This ISR could conceivably use DPTR2. Better save it. */
2445 emitcode ("push", "dpl1");
2446 emitcode ("push", "dph1");
2447 emitcode ("push", "dpx1");
2450 /* if this isr has no bank i.e. is going to
2451 run with bank 0 , then we need to save more
2453 if (!SPEC_BANK(sym->etype)) {
2455 /* if this function does not call any other
2456 function then we can be economical and
2457 save only those registers that are used */
2458 if (! sym->hasFcall) {
2461 /* if any registers used */
2462 if (sym->regsUsed) {
2463 /* save the registers used */
2464 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2465 if (bitVectBitValue(sym->regsUsed,i) ||
2466 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2467 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2472 /* this function has a function call cannot
2473 determines register usage so we will have the
2475 saverbank(0,ic,FALSE);
2479 /* if callee-save to be used for this function
2480 then save the registers being used in this function */
2481 if (sym->calleeSave) {
2484 /* if any registers used */
2485 if (sym->regsUsed) {
2486 /* save the registers used */
2487 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2488 if (bitVectBitValue(sym->regsUsed,i) ||
2489 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2490 emitcode("push","%s",pic14_regWithIdx(i)->dname);
2498 /* set the register bank to the desired value */
2499 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
2500 emitcode("push","psw");
2501 emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);
2504 if (IS_RENT(sym->etype) || options.stackAuto) {
2506 if (options.useXstack) {
2507 emitcode("mov","r0,%s",spname);
2508 emitcode("mov","a,_bp");
2509 emitcode("movx","@r0,a");
2510 emitcode("inc","%s",spname);
2514 /* set up the stack */
2515 emitcode ("push","_bp"); /* save the callers stack */
2517 emitcode ("mov","_bp,%s",spname);
2520 /* adjust the stack for the function */
2525 werror(W_STACK_OVERFLOW,sym->name);
2527 if (i > 3 && sym->recvSize < 4) {
2529 emitcode ("mov","a,sp");
2530 emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2531 emitcode ("mov","sp,a");
2536 emitcode("inc","sp");
2541 emitcode ("mov","a,_spx");
2542 emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2543 emitcode ("mov","_spx,a");
2548 /*-----------------------------------------------------------------*/
2549 /* genEndFunction - generates epilogue for functions */
2550 /*-----------------------------------------------------------------*/
2551 static void genEndFunction (iCode *ic)
2553 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2555 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2557 if (IS_RENT(sym->etype) || options.stackAuto)
2559 emitcode ("mov","%s,_bp",spname);
2562 /* if use external stack but some variables were
2563 added to the local stack then decrement the
2565 if (options.useXstack && sym->stack) {
2566 emitcode("mov","a,sp");
2567 emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2568 emitcode("mov","sp,a");
2572 if ((IS_RENT(sym->etype) || options.stackAuto)) {
2573 if (options.useXstack) {
2574 emitcode("mov","r0,%s",spname);
2575 emitcode("movx","a,@r0");
2576 emitcode("mov","_bp,a");
2577 emitcode("dec","%s",spname);
2581 emitcode ("pop","_bp");
2585 /* restore the register bank */
2586 if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
2587 emitcode ("pop","psw");
2589 if (IS_ISR(sym->etype)) {
2591 /* now we need to restore the registers */
2592 /* if this isr has no bank i.e. is going to
2593 run with bank 0 , then we need to save more
2595 if (!SPEC_BANK(sym->etype)) {
2597 /* if this function does not call any other
2598 function then we can be economical and
2599 save only those registers that are used */
2600 if (! sym->hasFcall) {
2603 /* if any registers used */
2604 if (sym->regsUsed) {
2605 /* save the registers used */
2606 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2607 if (bitVectBitValue(sym->regsUsed,i) ||
2608 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2609 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2614 /* this function has a function call cannot
2615 determines register usage so we will have the
2617 unsaverbank(0,ic,FALSE);
2621 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2623 if (options.stack10bit)
2625 emitcode ("pop", "dpx1");
2626 emitcode ("pop", "dph1");
2627 emitcode ("pop", "dpl1");
2629 emitcode ("pop", "dps");
2630 emitcode ("pop", "dpx");
2632 if (!inExcludeList("dph"))
2633 emitcode ("pop","dph");
2634 if (!inExcludeList("dpl"))
2635 emitcode ("pop","dpl");
2636 if (!inExcludeList("b"))
2637 emitcode ("pop","b");
2638 if (!inExcludeList("acc"))
2639 emitcode ("pop","acc");
2641 if (SPEC_CRTCL(sym->etype))
2642 emitcode("setb","ea");
2644 /* if debug then send end of function */
2645 /* if (options.debug && currFunc) { */
2648 emitcode(";","C$%s$%d$%d$%d ==.",
2649 FileBaseName(ic->filename),currFunc->lastLine,
2650 ic->level,ic->block);
2651 if (IS_STATIC(currFunc->etype))
2652 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2654 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2658 emitcode ("reti","");
2661 if (SPEC_CRTCL(sym->etype))
2662 emitcode("setb","ea");
2664 if (sym->calleeSave) {
2667 /* if any registers used */
2668 if (sym->regsUsed) {
2669 /* save the registers used */
2670 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2671 if (bitVectBitValue(sym->regsUsed,i) ||
2672 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2673 emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2679 /* if debug then send end of function */
2682 emitcode(";","C$%s$%d$%d$%d ==.",
2683 FileBaseName(ic->filename),currFunc->lastLine,
2684 ic->level,ic->block);
2685 if (IS_STATIC(currFunc->etype))
2686 emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2688 emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2692 emitcode ("return","");
2693 emitpcode(POC_RETURN,NULL);
2695 /* Mark the end of a function */
2696 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2701 /*-----------------------------------------------------------------*/
2702 /* genRet - generate code for return statement */
2703 /*-----------------------------------------------------------------*/
2704 static void genRet (iCode *ic)
2706 int size,offset = 0 , pushed = 0;
2708 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2709 /* if we have no return value then
2710 just generate the "ret" */
2714 /* we have something to return then
2715 move the return value into place */
2716 aopOp(IC_LEFT(ic),ic,FALSE);
2717 size = AOP_SIZE(IC_LEFT(ic));
2721 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2723 l = aopGet(AOP(IC_LEFT(ic)),offset++,
2725 emitcode("push","%s",l);
2728 l = aopGet(AOP(IC_LEFT(ic)),offset,
2730 if (strcmp(fReturn[offset],l)) {
2731 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2732 ((AOP(IC_LEFT(ic))->type) == AOP_LIT) )
2733 emitcode("movlw","%s",l);
2735 emitcode("movf","%s,w",l);
2737 emitcode("movwf","%s",fReturn[offset]);
2746 if (strcmp(fReturn[pushed],"a"))
2747 emitcode("pop",fReturn[pushed]);
2749 emitcode("pop","acc");
2752 freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2755 /* generate a jump to the return label
2756 if the next is not the return statement */
2757 if (!(ic->next && ic->next->op == LABEL &&
2758 IC_LABEL(ic->next) == returnLabel))
2760 emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2764 /*-----------------------------------------------------------------*/
2765 /* genLabel - generates a label */
2766 /*-----------------------------------------------------------------*/
2767 static void genLabel (iCode *ic)
2769 /* special case never generate */
2770 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2771 if (IC_LABEL(ic) == entryLabel)
2774 emitpLabel(IC_LABEL(ic)->key+100 + labelOffset);
2775 emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2778 /*-----------------------------------------------------------------*/
2779 /* genGoto - generates a goto */
2780 /*-----------------------------------------------------------------*/
2782 static void genGoto (iCode *ic)
2784 emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
2787 /*-----------------------------------------------------------------*/
2788 /* findLabelBackwards: walks back through the iCode chain looking */
2789 /* for the given label. Returns number of iCode instructions */
2790 /* between that label and given ic. */
2791 /* Returns zero if label not found. */
2792 /*-----------------------------------------------------------------*/
2794 static int findLabelBackwards(iCode *ic, int key)
2798 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2804 if (ic->op == LABEL && IC_LABEL(ic)->key == key)
2806 /* printf("findLabelBackwards = %d\n", count); */
2814 /*-----------------------------------------------------------------*/
2815 /* genPlusIncr :- does addition with increment if possible */
2816 /*-----------------------------------------------------------------*/
2817 static bool genPlusIncr (iCode *ic)
2819 unsigned int icount ;
2820 unsigned int size = getDataSize(IC_RESULT(ic));
2822 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2823 DEBUGemitcode ("; ","result %d, left %d, right %d",
2824 AOP_TYPE(IC_RESULT(ic)),
2825 AOP_TYPE(IC_LEFT(ic)),
2826 AOP_TYPE(IC_RIGHT(ic)));
2828 /* will try to generate an increment */
2829 /* if the right side is not a literal
2831 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2834 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2835 /* if the literal value of the right hand side
2836 is greater than 1 then it is faster to add */
2837 if ((icount = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2840 /* if increment 16 bits in register */
2841 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2846 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2847 //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
2851 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2852 //emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
2858 DEBUGemitcode ("; ","%s %d",__FUNCTION__,__LINE__);
2859 /* if left is in accumulator - probably a bit operation*/
2860 if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") &&
2861 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
2863 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2864 emitcode("bcf","(%s >> 3), (%s & 7)",
2865 AOP(IC_RESULT(ic))->aopu.aop_dir,
2866 AOP(IC_RESULT(ic))->aopu.aop_dir);
2868 emitpcode(POC_XORLW,popGetLit(1));
2869 //emitcode("xorlw","1");
2871 emitpcode(POC_ANDLW,popGetLit(1));
2872 //emitcode("andlw","1");
2875 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2876 emitcode("bsf","(%s >> 3), (%s & 7)",
2877 AOP(IC_RESULT(ic))->aopu.aop_dir,
2878 AOP(IC_RESULT(ic))->aopu.aop_dir);
2885 /* if the sizes are greater than 1 then we cannot */
2886 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2887 AOP_SIZE(IC_LEFT(ic)) > 1 )
2890 /* If we are incrementing the same register by two: */
2892 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2895 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2896 //emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2901 DEBUGemitcode ("; ","couldn't increment result-%s left-%s",
2902 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
2903 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2907 /*-----------------------------------------------------------------*/
2908 /* outBitAcc - output a bit in acc */
2909 /*-----------------------------------------------------------------*/
2910 static void outBitAcc(operand *result)
2912 symbol *tlbl = newiTempLabel(NULL);
2913 /* if the result is a bit */
2914 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2916 if (AOP_TYPE(result) == AOP_CRY){
2917 aopPut(AOP(result),"a",0);
2920 emitcode("jz","%05d_DS_",tlbl->key+100);
2921 emitcode("mov","a,%s",one);
2922 emitcode("","%05d_DS_:",tlbl->key+100);
2927 /*-----------------------------------------------------------------*/
2928 /* genPlusBits - generates code for addition of two bits */
2929 /*-----------------------------------------------------------------*/
2930 static void genPlusBits (iCode *ic)
2933 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
2935 The following block of code will add two bits.
2936 Note that it'll even work if the destination is
2937 the carry (C in the status register).
2938 It won't work if the 'Z' bit is a source or destination.
2941 /* If the result is stored in the accumulator (w) */
2942 if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
2943 //emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
2944 // popGet(AOP(result),0,FALSE,FALSE));
2946 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2947 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2948 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2949 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2950 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2951 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
2953 emitcode("movlw","(1 << (%s & 7))",
2954 AOP(IC_RESULT(ic))->aopu.aop_dir,
2955 AOP(IC_RESULT(ic))->aopu.aop_dir);
2956 emitcode("bcf","(%s >> 3), (%s & 7)",
2957 AOP(IC_RESULT(ic))->aopu.aop_dir,
2958 AOP(IC_RESULT(ic))->aopu.aop_dir);
2959 emitcode("btfsc","(%s >> 3), (%s & 7)",
2960 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2961 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2962 emitcode("xorwf","(%s >>3),f",
2963 AOP(IC_RESULT(ic))->aopu.aop_dir);
2964 emitcode("btfsc","(%s >> 3), (%s & 7)",
2965 AOP(IC_LEFT(ic))->aopu.aop_dir,
2966 AOP(IC_LEFT(ic))->aopu.aop_dir);
2967 emitcode("xorwf","(%s>>3),f",
2968 AOP(IC_RESULT(ic))->aopu.aop_dir);
2971 emitpcode(POC_CLRW, NULL);
2972 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
2973 emitpcode(POC_XORLW, popGetLit(1));
2974 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
2975 emitpcode(POC_XORLW, popGetLit(1));
2977 emitcode("clrw","");
2978 emitcode("btfsc","(%s >> 3), (%s & 7)",
2979 AOP(IC_RIGHT(ic))->aopu.aop_dir,
2980 AOP(IC_RIGHT(ic))->aopu.aop_dir);
2981 emitcode("xorlw","1");
2982 emitcode("btfsc","(%s >> 3), (%s & 7)",
2983 AOP(IC_LEFT(ic))->aopu.aop_dir,
2984 AOP(IC_LEFT(ic))->aopu.aop_dir);
2985 emitcode("xorlw","1");
2991 /* This is the original version of this code.
2993 * This is being kept around for reference,
2994 * because I am not entirely sure I got it right...
2996 static void adjustArithmeticResult(iCode *ic)
2998 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2999 AOP_SIZE(IC_LEFT(ic)) == 3 &&
3000 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
3001 aopPut(AOP(IC_RESULT(ic)),
3002 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
3005 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
3006 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
3007 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3008 aopPut(AOP(IC_RESULT(ic)),
3009 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
3012 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
3013 AOP_SIZE(IC_LEFT(ic)) < 3 &&
3014 AOP_SIZE(IC_RIGHT(ic)) < 3 &&
3015 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3016 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3018 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3019 aopPut(AOP(IC_RESULT(ic)),buffer,2);
3023 /* This is the pure and virtuous version of this code.
3024 * I'm pretty certain it's right, but not enough to toss the old
3027 static void adjustArithmeticResult(iCode *ic)
3029 if (opIsGptr(IC_RESULT(ic)) &&
3030 opIsGptr(IC_LEFT(ic)) &&
3031 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
3033 aopPut(AOP(IC_RESULT(ic)),
3034 aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
3038 if (opIsGptr(IC_RESULT(ic)) &&
3039 opIsGptr(IC_RIGHT(ic)) &&
3040 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
3042 aopPut(AOP(IC_RESULT(ic)),
3043 aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
3047 if (opIsGptr(IC_RESULT(ic)) &&
3048 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE &&
3049 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE &&
3050 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
3051 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
3053 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
3054 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
3059 /*-----------------------------------------------------------------*/
3060 /* genPlus - generates code for addition */
3061 /*-----------------------------------------------------------------*/
3062 static void genPlus (iCode *ic)
3064 int size, offset = 0;
3066 /* special cases :- */
3067 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3069 aopOp (IC_LEFT(ic),ic,FALSE);
3070 aopOp (IC_RIGHT(ic),ic,FALSE);
3071 aopOp (IC_RESULT(ic),ic,TRUE);
3073 /* if literal, literal on the right or
3074 if left requires ACC or right is already
3077 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
3078 operand *t = IC_RIGHT(ic);
3079 IC_RIGHT(ic) = IC_LEFT(ic);
3083 /* if both left & right are in bit space */
3084 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3085 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3090 /* if left in bit space & right literal */
3091 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3092 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
3093 /* if result in bit space */
3094 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3095 if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
3096 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3097 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3098 emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3099 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3102 size = getDataSize(IC_RESULT(ic));
3104 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3105 emitcode("addc","a,#00 ;%d",__LINE__);
3106 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
3112 /* if I can do an increment instead
3113 of add then GOOD for ME */
3114 if (genPlusIncr (ic) == TRUE)
3117 size = getDataSize(IC_RESULT(ic));
3119 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3120 /* Add a literal to something else */
3122 unsigned lit = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3126 DEBUGemitcode(";","adding lit to something. size %d",size);
3129 DEBUGemitcode(";","size %d",size);
3131 switch (lit & 0xff) {
3135 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3136 emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3139 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3140 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3141 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3145 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3146 emitpcode(POC_DECF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3149 emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3150 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3151 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3155 if( !know_W || ( (lit&0xff) != l1) ) {
3157 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
3159 if(sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
3160 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3163 emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3164 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3167 emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
3177 } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3179 emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3180 emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3181 emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3183 /* here we are adding a bit to a char or int */
3185 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3187 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3188 emitpcode(POC_INCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3190 emitcode("btfsc","(%s >> 3), (%s & 7)",
3191 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3192 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3193 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3196 if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3197 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3198 emitpcode(POC_XORLW , popGetLit(1));
3200 emitcode("btfsc","(%s >> 3), (%s & 7)",
3201 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3202 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3203 emitcode(" xorlw","1");
3205 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3206 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3207 emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3209 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3210 emitcode("btfsc","(%s >> 3), (%s & 7)",
3211 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3212 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3213 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3216 if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
3218 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
3219 emitpcode(POC_ANDLW , popGetLit(1));
3220 emitpcode(POC_BCF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3222 emitpcode(POC_BSF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3224 emitcode("andlw","1");
3225 emitcode("bcf","(%s >> 3), (%s & 7)",
3226 AOP(IC_RESULT(ic))->aopu.aop_dir,
3227 AOP(IC_RESULT(ic))->aopu.aop_dir);
3229 emitcode("bsf","(%s >> 3), (%s & 7)",
3230 AOP(IC_RESULT(ic))->aopu.aop_dir,
3231 AOP(IC_RESULT(ic))->aopu.aop_dir);
3235 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3236 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3244 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3246 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3247 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3249 emitcode("clrz","");
3251 emitcode("btfsc","(%s >> 3), (%s & 7)",
3252 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3253 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3254 emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3258 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3259 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3260 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3261 emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3264 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3265 emitcode("btfsc","(%s >> 3), (%s & 7)",
3266 AOP(IC_RIGHT(ic))->aopu.aop_dir,
3267 AOP(IC_RIGHT(ic))->aopu.aop_dir);
3268 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3269 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3275 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
3276 //emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
3283 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
3284 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3285 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3288 if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
3289 emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3290 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3291 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3294 emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3296 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
3297 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3299 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
3300 (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
3301 emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3303 emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3304 if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
3305 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3315 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
3316 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3317 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3319 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3320 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3323 emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3325 emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3326 emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3329 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3331 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3332 emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
3340 //adjustArithmeticResult(ic);
3343 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3344 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3345 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3348 /*-----------------------------------------------------------------*/
3349 /* genMinusDec :- does subtraction with decrement if possible */
3350 /*-----------------------------------------------------------------*/
3351 static bool genMinusDec (iCode *ic)
3353 unsigned int icount ;
3354 unsigned int size = getDataSize(IC_RESULT(ic));
3356 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3357 /* will try to generate an increment */
3358 /* if the right side is not a literal
3360 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
3363 DEBUGemitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
3365 /* if the literal value of the right hand side
3366 is greater than 4 then it is not worth it */
3367 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
3370 /* if decrement 16 bits in register */
3371 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
3376 emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3377 emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3378 emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3380 /* size is 3 or 4 */
3381 emitcode("movlw","0xff");
3382 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
3385 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
3387 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
3390 emitcode("skpnc","");
3392 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
3401 /* if the sizes are greater than 1 then we cannot */
3402 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
3403 AOP_SIZE(IC_LEFT(ic)) > 1 )
3406 /* we can if the aops of the left & result match or
3407 if they are in registers and the registers are the
3409 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
3412 emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3414 //emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3419 DEBUGemitcode ("; returning"," result=%s, left=%s",
3420 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
3421 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3423 emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3424 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
3431 /*-----------------------------------------------------------------*/
3432 /* addSign - complete with sign */
3433 /*-----------------------------------------------------------------*/
3434 static void addSign(operand *result, int offset, int sign)
3436 int size = (getDataSize(result) - offset);
3437 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3440 emitcode("rlc","a");
3441 emitcode("subb","a,acc");
3443 aopPut(AOP(result),"a",offset++);
3446 aopPut(AOP(result),zero,offset++);
3450 /*-----------------------------------------------------------------*/
3451 /* genMinusBits - generates code for subtraction of two bits */
3452 /*-----------------------------------------------------------------*/
3453 static void genMinusBits (iCode *ic)
3455 symbol *lbl = newiTempLabel(NULL);
3456 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3457 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
3458 emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
3459 emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
3460 emitcode("cpl","c");
3461 emitcode("","%05d_DS_:",(lbl->key+100));
3462 outBitC(IC_RESULT(ic));
3465 emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
3466 emitcode("subb","a,acc");
3467 emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
3468 emitcode("inc","a");
3469 emitcode("","%05d_DS_:",(lbl->key+100));
3470 aopPut(AOP(IC_RESULT(ic)),"a",0);
3471 addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
3475 /*-----------------------------------------------------------------*/
3476 /* genMinus - generates code for subtraction */
3477 /*-----------------------------------------------------------------*/
3478 static void genMinus (iCode *ic)
3480 int size, offset = 0;
3481 unsigned long lit = 0L;
3483 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3484 aopOp (IC_LEFT(ic),ic,FALSE);
3485 aopOp (IC_RIGHT(ic),ic,FALSE);
3486 aopOp (IC_RESULT(ic),ic,TRUE);
3488 /* special cases :- */
3489 /* if both left & right are in bit space */
3490 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
3491 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
3496 /* if I can do an decrement instead
3497 of subtract then GOOD for ME */
3498 if (genMinusDec (ic) == TRUE)
3501 size = getDataSize(IC_RESULT(ic));
3503 if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
3504 /* Add a literal to something else */
3506 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
3509 /* add the first byte: */
3510 emitcode("movlw","0x%x", lit & 0xff);
3511 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3518 emitcode("rlf","_known_zero,w");
3519 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3523 emitcode("movlw","0x%x", lit & 0xff);
3524 emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3532 emitcode("movf","%s", aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
3533 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
3539 emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3541 emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
3542 emitcode("subwf","%s,f", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
3549 // adjustArithmeticResult(ic);
3552 freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3553 freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3554 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3558 /*-----------------------------------------------------------------*/
3559 /* genMultbits :- multiplication of bits */
3560 /*-----------------------------------------------------------------*/
3561 static void genMultbits (operand *left,
3565 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3567 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
3568 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
3573 /*-----------------------------------------------------------------*/
3574 /* genMultOneByte : 8 bit multiplication & division */
3575 /*-----------------------------------------------------------------*/
3576 static void genMultOneByte (operand *left,
3580 sym_link *opetype = operandType(result);
3585 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3586 /* (if two literals, the value is computed before) */
3587 /* if one literal, literal on the right */
3588 if (AOP_TYPE(left) == AOP_LIT){
3594 size = AOP_SIZE(result);
3595 /* signed or unsigned */
3596 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3597 l = aopGet(AOP(left),0,FALSE,FALSE);
3599 emitcode("mul","ab");
3600 /* if result size = 1, mul signed = mul unsigned */
3601 aopPut(AOP(result),"a",0);
3603 if (SPEC_USIGN(opetype)){
3604 aopPut(AOP(result),"b",1);
3606 /* for filling the MSBs */
3607 emitcode("clr","a");
3610 emitcode("mov","a,b");
3612 /* adjust the MSB if left or right neg */
3614 /* if one literal */
3615 if (AOP_TYPE(right) == AOP_LIT){
3616 /* AND literal negative */
3617 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3618 /* adjust MSB (c==0 after mul) */
3619 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3623 lbl = newiTempLabel(NULL);
3624 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3625 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3626 emitcode("","%05d_DS_:",(lbl->key+100));
3627 emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3628 lbl = newiTempLabel(NULL);
3629 emitcode("jc","%05d_DS_",(lbl->key+100));
3630 emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3631 emitcode("","%05d_DS_:",(lbl->key+100));
3634 lbl = newiTempLabel(NULL);
3635 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3636 emitcode("cjne","a,#0x80,%05d_DS_", (lbl->key+100));
3637 emitcode("","%05d_DS_:",(lbl->key+100));
3638 emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
3639 lbl = newiTempLabel(NULL);
3640 emitcode("jc","%05d_DS_",(lbl->key+100));
3641 emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
3642 emitcode("","%05d_DS_:",(lbl->key+100));
3644 aopPut(AOP(result),"a",1);
3647 emitcode("rlc","a");
3648 emitcode("subb","a,acc");
3655 aopPut(AOP(result),"a",offset++);
3659 /*-----------------------------------------------------------------*/
3660 /* genMult - generates code for multiplication */
3661 /*-----------------------------------------------------------------*/
3662 static void genMult (iCode *ic)
3664 operand *left = IC_LEFT(ic);
3665 operand *right = IC_RIGHT(ic);
3666 operand *result= IC_RESULT(ic);
3668 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3669 /* assign the amsops */
3670 aopOp (left,ic,FALSE);
3671 aopOp (right,ic,FALSE);
3672 aopOp (result,ic,TRUE);
3674 /* special cases first */
3676 if (AOP_TYPE(left) == AOP_CRY &&
3677 AOP_TYPE(right)== AOP_CRY) {
3678 genMultbits(left,right,result);
3682 /* if both are of size == 1 */
3683 if (AOP_SIZE(left) == 1 &&
3684 AOP_SIZE(right) == 1 ) {
3685 genMultOneByte(left,right,result);
3689 /* should have been converted to function call */
3693 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3694 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3695 freeAsmop(result,NULL,ic,TRUE);
3698 /*-----------------------------------------------------------------*/
3699 /* genDivbits :- division of bits */
3700 /*-----------------------------------------------------------------*/
3701 static void genDivbits (operand *left,
3708 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3709 /* the result must be bit */
3710 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3711 l = aopGet(AOP(left),0,FALSE,FALSE);
3715 emitcode("div","ab");
3716 emitcode("rrc","a");
3717 aopPut(AOP(result),"c",0);
3720 /*-----------------------------------------------------------------*/
3721 /* genDivOneByte : 8 bit division */
3722 /*-----------------------------------------------------------------*/
3723 static void genDivOneByte (operand *left,
3727 sym_link *opetype = operandType(result);
3732 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3733 size = AOP_SIZE(result) - 1;
3735 /* signed or unsigned */
3736 if (SPEC_USIGN(opetype)) {
3737 /* unsigned is easy */
3738 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3739 l = aopGet(AOP(left),0,FALSE,FALSE);
3741 emitcode("div","ab");
3742 aopPut(AOP(result),"a",0);
3744 aopPut(AOP(result),zero,offset++);
3748 /* signed is a little bit more difficult */
3750 /* save the signs of the operands */
3751 l = aopGet(AOP(left),0,FALSE,FALSE);
3753 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3754 emitcode("push","acc"); /* save it on the stack */
3756 /* now sign adjust for both left & right */
3757 l = aopGet(AOP(right),0,FALSE,FALSE);
3759 lbl = newiTempLabel(NULL);
3760 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3761 emitcode("cpl","a");
3762 emitcode("inc","a");
3763 emitcode("","%05d_DS_:",(lbl->key+100));
3764 emitcode("mov","b,a");
3766 /* sign adjust left side */
3767 l = aopGet(AOP(left),0,FALSE,FALSE);
3770 lbl = newiTempLabel(NULL);
3771 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3772 emitcode("cpl","a");
3773 emitcode("inc","a");
3774 emitcode("","%05d_DS_:",(lbl->key+100));
3776 /* now the division */
3777 emitcode("div","ab");
3778 /* we are interested in the lower order
3780 emitcode("mov","b,a");
3781 lbl = newiTempLabel(NULL);
3782 emitcode("pop","acc");
3783 /* if there was an over flow we don't
3784 adjust the sign of the result */
3785 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3786 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3788 emitcode("clr","a");
3789 emitcode("subb","a,b");
3790 emitcode("mov","b,a");
3791 emitcode("","%05d_DS_:",(lbl->key+100));
3793 /* now we are done */
3794 aopPut(AOP(result),"b",0);
3796 emitcode("mov","c,b.7");
3797 emitcode("subb","a,acc");
3800 aopPut(AOP(result),"a",offset++);
3804 /*-----------------------------------------------------------------*/
3805 /* genDiv - generates code for division */
3806 /*-----------------------------------------------------------------*/
3807 static void genDiv (iCode *ic)
3809 operand *left = IC_LEFT(ic);
3810 operand *right = IC_RIGHT(ic);
3811 operand *result= IC_RESULT(ic);
3813 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3814 /* assign the amsops */
3815 aopOp (left,ic,FALSE);
3816 aopOp (right,ic,FALSE);
3817 aopOp (result,ic,TRUE);
3819 /* special cases first */
3821 if (AOP_TYPE(left) == AOP_CRY &&
3822 AOP_TYPE(right)== AOP_CRY) {
3823 genDivbits(left,right,result);
3827 /* if both are of size == 1 */
3828 if (AOP_SIZE(left) == 1 &&
3829 AOP_SIZE(right) == 1 ) {
3830 genDivOneByte(left,right,result);
3834 /* should have been converted to function call */
3837 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3838 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3839 freeAsmop(result,NULL,ic,TRUE);
3842 /*-----------------------------------------------------------------*/
3843 /* genModbits :- modulus of bits */
3844 /*-----------------------------------------------------------------*/
3845 static void genModbits (operand *left,
3852 /* the result must be bit */
3853 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3854 l = aopGet(AOP(left),0,FALSE,FALSE);
3858 emitcode("div","ab");
3859 emitcode("mov","a,b");
3860 emitcode("rrc","a");
3861 aopPut(AOP(result),"c",0);
3864 /*-----------------------------------------------------------------*/
3865 /* genModOneByte : 8 bit modulus */
3866 /*-----------------------------------------------------------------*/
3867 static void genModOneByte (operand *left,
3871 sym_link *opetype = operandType(result);
3875 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3876 /* signed or unsigned */
3877 if (SPEC_USIGN(opetype)) {
3878 /* unsigned is easy */
3879 emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3880 l = aopGet(AOP(left),0,FALSE,FALSE);
3882 emitcode("div","ab");
3883 aopPut(AOP(result),"b",0);
3887 /* signed is a little bit more difficult */
3889 /* save the signs of the operands */
3890 l = aopGet(AOP(left),0,FALSE,FALSE);
3893 emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3894 emitcode("push","acc"); /* save it on the stack */
3896 /* now sign adjust for both left & right */
3897 l = aopGet(AOP(right),0,FALSE,FALSE);
3900 lbl = newiTempLabel(NULL);
3901 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3902 emitcode("cpl","a");
3903 emitcode("inc","a");
3904 emitcode("","%05d_DS_:",(lbl->key+100));
3905 emitcode("mov","b,a");
3907 /* sign adjust left side */
3908 l = aopGet(AOP(left),0,FALSE,FALSE);
3911 lbl = newiTempLabel(NULL);
3912 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3913 emitcode("cpl","a");
3914 emitcode("inc","a");
3915 emitcode("","%05d_DS_:",(lbl->key+100));
3917 /* now the multiplication */
3918 emitcode("div","ab");
3919 /* we are interested in the lower order
3921 lbl = newiTempLabel(NULL);
3922 emitcode("pop","acc");
3923 /* if there was an over flow we don't
3924 adjust the sign of the result */
3925 emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3926 emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3928 emitcode("clr","a");
3929 emitcode("subb","a,b");
3930 emitcode("mov","b,a");
3931 emitcode("","%05d_DS_:",(lbl->key+100));
3933 /* now we are done */
3934 aopPut(AOP(result),"b",0);
3938 /*-----------------------------------------------------------------*/
3939 /* genMod - generates code for division */
3940 /*-----------------------------------------------------------------*/
3941 static void genMod (iCode *ic)
3943 operand *left = IC_LEFT(ic);
3944 operand *right = IC_RIGHT(ic);
3945 operand *result= IC_RESULT(ic);
3947 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3948 /* assign the amsops */
3949 aopOp (left,ic,FALSE);
3950 aopOp (right,ic,FALSE);
3951 aopOp (result,ic,TRUE);
3953 /* special cases first */
3955 if (AOP_TYPE(left) == AOP_CRY &&
3956 AOP_TYPE(right)== AOP_CRY) {
3957 genModbits(left,right,result);
3961 /* if both are of size == 1 */
3962 if (AOP_SIZE(left) == 1 &&
3963 AOP_SIZE(right) == 1 ) {
3964 genModOneByte(left,right,result);
3968 /* should have been converted to function call */
3972 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3973 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3974 freeAsmop(result,NULL,ic,TRUE);
3977 /*-----------------------------------------------------------------*/
3978 /* genIfxJump :- will create a jump depending on the ifx */
3979 /*-----------------------------------------------------------------*/
3980 static void genIfxJump (iCode *ic, char *jval)
3983 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
3984 /* if true label then we jump if condition
3986 if ( IC_TRUE(ic) ) {
3988 if(strcmp(jval,"a") == 0)
3990 else if (strcmp(jval,"c") == 0)
3993 //pCodeOp *p = popGetWithString(jval);
3995 //emitpcode(POC_BTFSC, p);
3996 emitpcode(POC_BTFSC, newpCodeOpBit(jval,0));
3997 //emitcode("btfsc","(%s >> 3),(%s & 7)",jval,jval);
4000 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
4001 emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4005 /* false label is present */
4006 if(strcmp(jval,"a") == 0)
4008 else if (strcmp(jval,"c") == 0)
4011 //pCodeOp *p = popGetWithString(jval);
4013 //emitpcode(POC_BTFSS, p);
4014 emitpcode(POC_BTFSS, newpCodeOpBit(jval,0));
4016 // emitcode("btfss","(%s >> 3),(%s & 7)",jval,jval);
4019 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
4020 emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4025 /* mark the icode as generated */
4029 /*-----------------------------------------------------------------*/
4031 /*-----------------------------------------------------------------*/
4032 static void genSkip(iCode *ifx,int status_bit)
4037 if ( IC_TRUE(ifx) ) {
4038 switch(status_bit) {
4048 emitcode("skpndc","");
4053 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4054 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4058 switch(status_bit) {
4069 emitcode("skpdc","");
4072 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4073 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4079 /*-----------------------------------------------------------------*/
4081 /*-----------------------------------------------------------------*/
4082 static void genSkipc(iCode *ifx, int condition)
4093 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4095 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4098 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4100 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4104 /*-----------------------------------------------------------------*/
4106 /*-----------------------------------------------------------------*/
4107 static void genSkipz(iCode *ifx, int condition)
4118 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4120 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4123 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4125 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4128 /*-----------------------------------------------------------------*/
4129 /* genCmp :- greater or less than comparison */
4130 /*-----------------------------------------------------------------*/
4131 static void genCmp (operand *left,operand *right,
4132 operand *result, iCode *ifx, int sign)
4134 int size, offset = 0 ;
4135 unsigned long lit = 0L,i = 0;
4137 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4138 /* if left & right are bit variables */
4139 if (AOP_TYPE(left) == AOP_CRY &&
4140 AOP_TYPE(right) == AOP_CRY ) {
4141 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4142 emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4144 /* subtract right from left if at the
4145 end the carry flag is set then we know that
4146 left is greater than right */
4147 size = max(AOP_SIZE(left),AOP_SIZE(right));
4149 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4150 if((size == 1) && !sign &&
4151 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
4152 symbol *lbl = newiTempLabel(NULL);
4153 emitcode("cjne","%s,%s,%05d_DS_",
4154 aopGet(AOP(left),offset,FALSE,FALSE),
4155 aopGet(AOP(right),offset,FALSE,FALSE),
4157 emitcode("","%05d_DS_:",lbl->key+100);
4160 if(AOP_TYPE(right) == AOP_LIT) {
4162 DEBUGemitcode(";right lit","%d",sign);
4164 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4167 i = (lit >> (size*8)) & 0xff;
4169 emitpcode(POC_MOVFW, popGet(AOP(left),size,FALSE,FALSE));
4170 emitcode("movf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4171 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4173 emitpcode(POC_MOVLW, popGetLit(i));
4174 emitpcode(POC_SUBFW, popGet(AOP(left),size,FALSE,FALSE));
4176 emitcode("movlw","0x%x",i);
4177 emitcode("subwf","%s,w",aopGet(AOP(left),size,FALSE,FALSE));
4178 genSkipc(ifx,IC_TRUE(ifx) == NULL);
4185 if(AOP_TYPE(left) == AOP_LIT) {
4187 DEBUGemitcode(";left lit","%d",sign);
4189 lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit))+1;
4193 i = (lit >> (size*8)) & 0xff;
4195 emitpcode(POC_MOVFW, popGet(AOP(right),size,FALSE,FALSE));
4196 emitcode("movf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4197 genSkipz(ifx,IC_TRUE(ifx) != NULL);
4198 } else if( i == 1 ) {
4199 emitpcode(POC_DECFW, popGet(AOP(right),size,FALSE,FALSE));
4200 emitcode("decf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4201 genSkipz(ifx,IC_TRUE(ifx) != NULL);
4204 emitpcode(POC_MOVLW, popGetLit(i));
4205 emitpcode(POC_SUBFW, popGet(AOP(right),size,FALSE,FALSE));
4207 emitcode("movlw","0x%x",i);
4208 emitcode("subwf","%s,w",aopGet(AOP(right),size,FALSE,FALSE));
4209 genSkipc(ifx,IC_TRUE(ifx) != NULL);
4218 DEBUGemitcode(";sign","%d",sign);
4220 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4221 emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));//++
4223 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
4224 emitpcode(POC_SUBFW, popGet(AOP(left),offset++,FALSE,FALSE));
4229 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
4231 emitpcode(POC_INCFSZW, popGet(AOP(right),offset,FALSE,FALSE));
4232 emitpcode(POC_SUBFW, popGet(AOP(left),offset,FALSE,FALSE));
4235 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4237 emitcode("incfsz","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4238 emitcode("subwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4246 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4249 /* if the result is used in the next
4250 ifx conditional branch then generate
4251 code a little differently */
4253 genIfxJump (ifx,"c");
4256 /* leave the result in acc */
4261 /*-----------------------------------------------------------------*/
4262 /* genCmpGt :- greater than comparison */
4263 /*-----------------------------------------------------------------*/
4264 static void genCmpGt (iCode *ic, iCode *ifx)
4266 operand *left, *right, *result;
4267 sym_link *letype , *retype;
4270 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4272 right= IC_RIGHT(ic);
4273 result = IC_RESULT(ic);
4275 letype = getSpec(operandType(left));
4276 retype =getSpec(operandType(right));
4277 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4278 /* assign the amsops */
4279 aopOp (left,ic,FALSE);
4280 aopOp (right,ic,FALSE);
4281 aopOp (result,ic,TRUE);
4283 genCmp(right, left, result, ifx, sign);
4285 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4286 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4287 freeAsmop(result,NULL,ic,TRUE);
4290 /*-----------------------------------------------------------------*/
4291 /* genCmpLt - less than comparisons */
4292 /*-----------------------------------------------------------------*/
4293 static void genCmpLt (iCode *ic, iCode *ifx)
4295 operand *left, *right, *result;
4296 sym_link *letype , *retype;
4299 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4301 right= IC_RIGHT(ic);
4302 result = IC_RESULT(ic);
4304 letype = getSpec(operandType(left));
4305 retype =getSpec(operandType(right));
4306 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4308 /* assign the amsops */
4309 aopOp (left,ic,FALSE);
4310 aopOp (right,ic,FALSE);
4311 aopOp (result,ic,TRUE);
4313 genCmp(left, right, result, ifx, sign);
4315 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4316 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4317 freeAsmop(result,NULL,ic,TRUE);
4320 /*-----------------------------------------------------------------*/
4321 /* gencjneshort - compare and jump if not equal */
4322 /*-----------------------------------------------------------------*/
4323 static void gencjneshort(operand *left, operand *right, symbol *lbl)
4325 int size = max(AOP_SIZE(left),AOP_SIZE(right));
4327 unsigned long lit = 0L;
4329 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4330 /* if the left side is a literal or
4331 if the right is in a pointer register and left
4333 if ((AOP_TYPE(left) == AOP_LIT) ||
4334 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4339 if(AOP_TYPE(right) == AOP_LIT)
4340 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4342 /* if the right side is a literal then anything goes */
4343 if (AOP_TYPE(right) == AOP_LIT &&
4344 AOP_TYPE(left) != AOP_DIR ) {
4347 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4348 emitcode("xorlw","0x%x",lit & 0xff);
4350 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4353 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4359 /* if the right side is in a register or in direct space or
4360 if the left is a pointer register & right is not */
4361 else if (AOP_TYPE(right) == AOP_REG ||
4362 AOP_TYPE(right) == AOP_DIR ||
4363 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4364 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4366 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4367 ( (lit & 0xff) != 0)) {
4368 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4369 emitcode("xorlw","0x%x",lit & 0xff);
4372 emitcode("movf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
4375 emitcode("goto","_%05d_DS_",lbl->key+100+labelOffset);
4378 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
4379 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
4380 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
4381 emitcode("jnz","%05d_DS_",lbl->key+100);
4383 emitcode("cjne","a,%s,%05d_DS_",
4384 aopGet(AOP(right),offset,FALSE,TRUE),
4390 /* right is a pointer reg need both a & b */
4392 char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4394 emitcode("mov","b,%s",l);
4395 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4396 emitcode("cjne","a,b,%05d_DS_",lbl->key+100);
4402 /*-----------------------------------------------------------------*/
4403 /* gencjne - compare and jump if not equal */
4404 /*-----------------------------------------------------------------*/
4405 static void gencjne(operand *left, operand *right, symbol *lbl)
4407 symbol *tlbl = newiTempLabel(NULL);
4409 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4410 gencjneshort(left, right, lbl);
4412 emitcode("mov","a,%s",one);
4413 emitcode("sjmp","%05d_DS_",tlbl->key+100);
4414 emitcode("","%05d_DS_:",lbl->key+100);
4415 emitcode("clr","a");
4416 emitcode("","%05d_DS_:",tlbl->key+100);
4420 /*-----------------------------------------------------------------*/
4421 /* genCmpEq - generates code for equal to */
4422 /*-----------------------------------------------------------------*/
4423 static void genCmpEq (iCode *ic, iCode *ifx)
4425 operand *left, *right, *result;
4426 unsigned long lit = 0L;
4429 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4431 DEBUGemitcode ("; ifx is non-null","");
4433 DEBUGemitcode ("; ifx is null","");
4435 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4436 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4437 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4439 size = max(AOP_SIZE(left),AOP_SIZE(right));
4441 /* if literal, literal on the right or
4442 if the right is in a pointer register and left
4444 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
4445 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4446 operand *t = IC_RIGHT(ic);
4447 IC_RIGHT(ic) = IC_LEFT(ic);
4451 if(ifx && !AOP_SIZE(result)){
4453 /* if they are both bit variables */
4454 if (AOP_TYPE(left) == AOP_CRY &&
4455 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4456 if(AOP_TYPE(right) == AOP_LIT){
4457 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4459 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4460 emitcode("cpl","c");
4461 } else if(lit == 1L) {
4462 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4464 emitcode("clr","c");
4466 /* AOP_TYPE(right) == AOP_CRY */
4468 symbol *lbl = newiTempLabel(NULL);
4469 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4470 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4471 emitcode("cpl","c");
4472 emitcode("","%05d_DS_:",(lbl->key+100));
4474 /* if true label then we jump if condition
4476 tlbl = newiTempLabel(NULL);
4477 if ( IC_TRUE(ifx) ) {
4478 emitcode("jnc","%05d_DS_",tlbl->key+100);
4479 emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4481 emitcode("jc","%05d_DS_",tlbl->key+100);
4482 emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4484 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4487 /* They're not both bit variables. Is the right a literal? */
4488 if(AOP_TYPE(right) == AOP_LIT) {
4490 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4495 int h = (lit>>8) & 0xff;
4498 /* Check special cases for integers */
4499 switch(lit & 0xffff) {
4501 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4502 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4503 //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4504 //emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4509 emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4510 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4511 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4512 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4517 emitpcode(POC_DECFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4518 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4519 emitcode("decf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4520 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4525 emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4526 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4527 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4528 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4533 emitpcode(POC_INCFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4534 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4535 emitcode("incf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4536 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4542 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4543 emitpcode(POC_XORLW,popGetLit(l));
4544 emitpcode(POC_IORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4546 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4547 emitcode("xorlw","0x%x",l);
4548 emitcode("iorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4551 } else if (l == 0) {
4552 emitpcode(POC_MOVFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4553 emitpcode(POC_XORLW,popGetLit(h));
4554 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4556 emitcode("movf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4557 emitcode("xorlw","0x%x",h);
4558 emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4562 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4563 emitpcode(POC_XORLW,popGetLit(l));
4564 emitpcode(POC_MOVLW,popGetLit(h));
4566 emitpcode(POC_XORFW,popGet(AOP(left),offset+1,FALSE,FALSE));
4568 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4569 emitcode("xorlw","0x%x",l);
4570 emitcode("movlw","0x%x",h);
4572 emitcode("xorwf","%s,w",aopGet(AOP(left),offset+1,FALSE,FALSE));
4589 switch(lit & 0xff) {
4591 if ( IC_TRUE(ifx) ) {
4593 emitcode("decf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4595 emitpcode(POC_DECFW,popGet(AOP(left),offset,FALSE,FALSE));
4597 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4599 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4601 emitpcode(POC_DECFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4602 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4604 emitcode("decfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4605 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4609 if ( IC_TRUE(ifx) ) {
4610 emitcode("incf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4612 emitpcode(POC_INCFW,popGet(AOP(left),offset,FALSE,FALSE));
4614 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4616 emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4618 emitpcode(POC_INCFSZW,popGet(AOP(left),offset,FALSE,FALSE));
4619 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4621 emitcode("incfsz","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4622 emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4626 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4627 //emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4629 emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4630 //emitcode("xorlw","0x%x",lit & 0xff);
4635 // emitcode("goto","_%05d_DS_",tlbl->key+100+labelOffset);
4636 //emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4641 } else if(AOP_TYPE(right) == AOP_CRY ) {
4642 /* we know the left is not a bit, but that the right is */
4643 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4644 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4645 popGet(AOP(right),offset,FALSE,FALSE));
4646 emitpcode(POC_XORLW,popGetLit(1));
4648 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4650 emitcode("btfsc","(%s >> 3), (%s & 7)",
4651 AOP(right)->aopu.aop_dir,
4652 AOP(right)->aopu.aop_dir);
4654 emitcode("btfss","(%s >> 3), (%s & 7)",
4655 AOP(right)->aopu.aop_dir,
4656 AOP(right)->aopu.aop_dir);
4658 emitcode("xorlw","1");
4660 /* if the two are equal, then W will be 0 and the Z bit is set
4661 * we could test Z now, or go ahead and check the high order bytes if
4662 * the variable we're comparing is larger than a byte. */
4665 emitpcode(POC_IORFW,popGet(AOP(left),offset,FALSE,FALSE));
4666 //emitcode("iorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4668 if ( IC_TRUE(ifx) ) {
4670 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4671 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4674 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4675 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4679 /* They're both variables that are larger than bits */
4682 tlbl = newiTempLabel(NULL);
4685 emitpcode(POC_MOVFW,popGet(AOP(left),offset,FALSE,FALSE));
4686 emitpcode(POC_XORFW,popGet(AOP(right),offset,FALSE,FALSE));
4688 emitcode("movf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
4689 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
4691 if ( IC_TRUE(ifx) ) {
4694 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4695 emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4698 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4699 emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4703 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4704 emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4708 if(s>1 && IC_TRUE(ifx)) {
4709 emitpLabel(tlbl->key+100+labelOffset);
4710 emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);
4714 /* mark the icode as generated */
4719 /* if they are both bit variables */
4720 if (AOP_TYPE(left) == AOP_CRY &&
4721 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4722 if(AOP_TYPE(right) == AOP_LIT){
4723 unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
4725 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4726 emitcode("cpl","c");
4727 } else if(lit == 1L) {
4728 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4730 emitcode("clr","c");
4732 /* AOP_TYPE(right) == AOP_CRY */
4734 symbol *lbl = newiTempLabel(NULL);
4735 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4736 emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4737 emitcode("cpl","c");
4738 emitcode("","%05d_DS_:",(lbl->key+100));
4741 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4746 genIfxJump (ifx,"c");
4749 /* if the result is used in an arithmetic operation
4750 then put the result in place */
4753 gencjne(left,right,newiTempLabel(NULL));
4754 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4755 aopPut(AOP(result),"a",0);
4759 genIfxJump (ifx,"a");
4762 /* if the result is used in an arithmetic operation
4763 then put the result in place */
4764 if (AOP_TYPE(result) != AOP_CRY)
4766 /* leave the result in acc */
4770 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4771 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4772 freeAsmop(result,NULL,ic,TRUE);
4775 /*-----------------------------------------------------------------*/
4776 /* ifxForOp - returns the icode containing the ifx for operand */
4777 /*-----------------------------------------------------------------*/
4778 static iCode *ifxForOp ( operand *op, iCode *ic )
4780 /* if true symbol then needs to be assigned */
4781 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4782 if (IS_TRUE_SYMOP(op))
4785 /* if this has register type condition and
4786 the next instruction is ifx with the same operand
4787 and live to of the operand is upto the ifx only then */
4789 ic->next->op == IFX &&
4790 IC_COND(ic->next)->key == op->key &&
4791 OP_SYMBOL(op)->liveTo <= ic->next->seq )
4796 /*-----------------------------------------------------------------*/
4797 /* genAndOp - for && operation */
4798 /*-----------------------------------------------------------------*/
4799 static void genAndOp (iCode *ic)
4801 operand *left,*right, *result;
4804 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4805 /* note here that && operations that are in an
4806 if statement are taken away by backPatchLabels
4807 only those used in arthmetic operations remain */
4808 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4809 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4810 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4812 /* if both are bit variables */
4813 if (AOP_TYPE(left) == AOP_CRY &&
4814 AOP_TYPE(right) == AOP_CRY ) {
4815 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4816 emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4819 tlbl = newiTempLabel(NULL);
4821 emitcode("jz","%05d_DS_",tlbl->key+100);
4823 emitcode("","%05d_DS_:",tlbl->key+100);
4827 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4828 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4829 freeAsmop(result,NULL,ic,TRUE);
4833 /*-----------------------------------------------------------------*/
4834 /* genOrOp - for || operation */
4835 /*-----------------------------------------------------------------*/
4838 modified this code, but it doesn't appear to ever get called
4841 static void genOrOp (iCode *ic)
4843 operand *left,*right, *result;
4846 /* note here that || operations that are in an
4847 if statement are taken away by backPatchLabels
4848 only those used in arthmetic operations remain */
4849 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4850 aopOp((left=IC_LEFT(ic)),ic,FALSE);
4851 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4852 aopOp((result=IC_RESULT(ic)),ic,FALSE);
4854 /* if both are bit variables */
4855 if (AOP_TYPE(left) == AOP_CRY &&
4856 AOP_TYPE(right) == AOP_CRY ) {
4857 emitcode("clrc","");
4858 emitcode("btfss","(%s >> 3), (%s & 7)",
4859 AOP(left)->aopu.aop_dir,
4860 AOP(left)->aopu.aop_dir);
4861 emitcode("btfsc","(%s >> 3), (%s & 7)",
4862 AOP(right)->aopu.aop_dir,
4863 AOP(right)->aopu.aop_dir);
4864 emitcode("setc","");
4867 tlbl = newiTempLabel(NULL);
4870 emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4872 emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4877 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4878 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4879 freeAsmop(result,NULL,ic,TRUE);
4882 /*-----------------------------------------------------------------*/
4883 /* isLiteralBit - test if lit == 2^n */
4884 /*-----------------------------------------------------------------*/
4885 static int isLiteralBit(unsigned long lit)
4887 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4888 0x100L,0x200L,0x400L,0x800L,
4889 0x1000L,0x2000L,0x4000L,0x8000L,
4890 0x10000L,0x20000L,0x40000L,0x80000L,
4891 0x100000L,0x200000L,0x400000L,0x800000L,
4892 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4893 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4896 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4897 for(idx = 0; idx < 32; idx++)
4903 /*-----------------------------------------------------------------*/
4904 /* continueIfTrue - */
4905 /*-----------------------------------------------------------------*/
4906 static void continueIfTrue (iCode *ic)
4908 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4910 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4914 /*-----------------------------------------------------------------*/
4916 /*-----------------------------------------------------------------*/
4917 static void jumpIfTrue (iCode *ic)
4919 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4921 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4925 /*-----------------------------------------------------------------*/
4926 /* jmpTrueOrFalse - */
4927 /*-----------------------------------------------------------------*/
4928 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4930 // ugly but optimized by peephole
4931 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4933 symbol *nlbl = newiTempLabel(NULL);
4934 emitcode("sjmp","%05d_DS_",nlbl->key+100);
4935 emitcode("","%05d_DS_:",tlbl->key+100);
4936 emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4937 emitcode("","%05d_DS_:",nlbl->key+100);
4940 emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4941 emitcode("","%05d_DS_:",tlbl->key+100);
4946 /*-----------------------------------------------------------------*/
4947 /* genAnd - code for and */
4948 /*-----------------------------------------------------------------*/
4949 static void genAnd (iCode *ic, iCode *ifx)
4951 operand *left, *right, *result;
4953 unsigned long lit = 0L;
4957 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
4958 aopOp((left = IC_LEFT(ic)),ic,FALSE);
4959 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
4960 aopOp((result=IC_RESULT(ic)),ic,TRUE);
4963 emitcode("","; Type res[%d] = l[%d]&r[%d]",
4965 AOP_TYPE(left), AOP_TYPE(right));
4966 emitcode("","; Size res[%d] = l[%d]&r[%d]",
4968 AOP_SIZE(left), AOP_SIZE(right));
4971 /* if left is a literal & right is not then exchange them */
4972 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
4973 AOP_NEEDSACC(left)) {
4974 operand *tmp = right ;
4979 /* if result = right then exchange them */
4980 if(sameRegs(AOP(result),AOP(right))){
4981 operand *tmp = right ;
4986 /* if right is bit then exchange them */
4987 if (AOP_TYPE(right) == AOP_CRY &&
4988 AOP_TYPE(left) != AOP_CRY){
4989 operand *tmp = right ;
4993 if(AOP_TYPE(right) == AOP_LIT)
4994 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
4996 size = AOP_SIZE(result);
4999 // result = bit & yy;
5000 if (AOP_TYPE(left) == AOP_CRY){
5001 // c = bit & literal;
5002 if(AOP_TYPE(right) == AOP_LIT){
5004 if(size && sameRegs(AOP(result),AOP(left)))
5007 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5010 if(size && (AOP_TYPE(result) == AOP_CRY)){
5011 emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5014 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5018 emitcode("clr","c");
5021 if (AOP_TYPE(right) == AOP_CRY){
5023 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5024 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5027 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5029 emitcode("rrc","a");
5030 emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5038 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5039 genIfxJump(ifx, "c");
5043 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5044 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5045 if((AOP_TYPE(right) == AOP_LIT) &&
5046 (AOP_TYPE(result) == AOP_CRY) &&
5047 (AOP_TYPE(left) != AOP_CRY)){
5048 int posbit = isLiteralBit(lit);
5052 MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5055 emitcode("mov","c,acc.%d",posbit&0x07);
5059 sprintf(buffer,"acc.%d",posbit&0x07);
5060 genIfxJump(ifx, buffer);
5065 symbol *tlbl = newiTempLabel(NULL);
5066 int sizel = AOP_SIZE(left);
5068 emitcode("setb","c");
5070 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5071 MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5073 if((posbit = isLiteralBit(bytelit)) != 0)
5074 emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5076 if(bytelit != 0x0FFL)
5077 emitcode("anl","a,%s",
5078 aopGet(AOP(right),offset,FALSE,TRUE));
5079 emitcode("jnz","%05d_DS_",tlbl->key+100);
5084 // bit = left & literal
5086 emitcode("clr","c");
5087 emitcode("","%05d_DS_:",tlbl->key+100);
5089 // if(left & literal)
5092 jmpTrueOrFalse(ifx, tlbl);
5100 /* if left is same as result */
5101 if(sameRegs(AOP(result),AOP(left))){
5102 for(;size--; offset++,lit>>=8) {
5103 if(AOP_TYPE(right) == AOP_LIT){
5104 switch(lit & 0xff) {
5106 /* and'ing with 0 has clears the result */
5107 emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5110 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5115 int p = my_powof2( (~lit) & 0xff );
5117 /* only one bit is set in the literal, so use a bcf instruction */
5118 emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5120 emitcode("movlw","0x%x", (lit & 0xff));
5121 emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5126 if (AOP_TYPE(left) == AOP_ACC)
5127 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5129 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5130 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5137 // left & result in different registers
5138 if(AOP_TYPE(result) == AOP_CRY){
5140 // if(size), result in bit
5141 // if(!size && ifx), conditional oper: if(left & right)
5142 symbol *tlbl = newiTempLabel(NULL);
5143 int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5145 emitcode("setb","c");
5147 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5148 emitcode("anl","a,%s",
5149 aopGet(AOP(left),offset,FALSE,FALSE));
5150 emitcode("jnz","%05d_DS_",tlbl->key+100);
5155 emitcode("","%05d_DS_:",tlbl->key+100);
5158 jmpTrueOrFalse(ifx, tlbl);
5160 for(;(size--);offset++) {
5162 // result = left & right
5163 if(AOP_TYPE(right) == AOP_LIT){
5164 int t = (lit >> (offset*8)) & 0x0FFL;
5167 emitcode("clrf","%s",
5168 aopGet(AOP(result),offset,FALSE,FALSE));
5171 emitcode("movf","%s,w",
5172 aopGet(AOP(left),offset,FALSE,FALSE));
5173 emitcode("movwf","%s",
5174 aopGet(AOP(result),offset,FALSE,FALSE));
5177 emitcode("movlw","0x%x",t);
5178 emitcode("andwf","%s,w",
5179 aopGet(AOP(left),offset,FALSE,FALSE));
5180 emitcode("movwf","%s",
5181 aopGet(AOP(result),offset,FALSE,FALSE));
5187 if (AOP_TYPE(left) == AOP_ACC)
5188 emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5190 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5191 emitcode("andwf","%s,w",
5192 aopGet(AOP(left),offset,FALSE,FALSE));
5194 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5200 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5201 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5202 freeAsmop(result,NULL,ic,TRUE);
5205 /*-----------------------------------------------------------------*/
5206 /* genOr - code for or */
5207 /*-----------------------------------------------------------------*/
5208 static void genOr (iCode *ic, iCode *ifx)
5210 operand *left, *right, *result;
5212 unsigned long lit = 0L;
5214 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5216 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5217 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5218 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5221 /* if left is a literal & right is not then exchange them */
5222 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5223 AOP_NEEDSACC(left)) {
5224 operand *tmp = right ;
5229 /* if result = right then exchange them */
5230 if(sameRegs(AOP(result),AOP(right))){
5231 operand *tmp = right ;
5236 /* if right is bit then exchange them */
5237 if (AOP_TYPE(right) == AOP_CRY &&
5238 AOP_TYPE(left) != AOP_CRY){
5239 operand *tmp = right ;
5244 if(AOP_TYPE(right) == AOP_LIT)
5245 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5247 size = AOP_SIZE(result);
5251 if (AOP_TYPE(left) == AOP_CRY){
5252 if(AOP_TYPE(right) == AOP_LIT){
5253 // c = bit & literal;
5255 // lit != 0 => result = 1
5256 if(AOP_TYPE(result) == AOP_CRY){
5258 emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5259 //emitcode("bsf","(%s >> 3), (%s & 7)",
5260 // AOP(result)->aopu.aop_dir,
5261 // AOP(result)->aopu.aop_dir);
5263 continueIfTrue(ifx);
5267 // lit == 0 => result = left
5268 if(size && sameRegs(AOP(result),AOP(left)))
5270 emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5273 if (AOP_TYPE(right) == AOP_CRY){
5274 if(sameRegs(AOP(result),AOP(left))){
5276 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
5277 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
5278 emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5280 emitcode("bcf","(%s >> 3), (%s & 7)",
5281 AOP(result)->aopu.aop_dir,
5282 AOP(result)->aopu.aop_dir);
5283 emitcode("btfsc","(%s >> 3), (%s & 7)",
5284 AOP(right)->aopu.aop_dir,
5285 AOP(right)->aopu.aop_dir);
5286 emitcode("bsf","(%s >> 3), (%s & 7)",
5287 AOP(result)->aopu.aop_dir,
5288 AOP(result)->aopu.aop_dir);
5291 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
5292 emitpcode(POC_BTFSS, popGet(AOP(right),0,FALSE,FALSE));
5293 emitpcode(POC_BTFSC, popGet(AOP(left),0,FALSE,FALSE));
5294 emitpcode(POC_BSF, popGet(AOP(result),0,FALSE,FALSE));
5296 emitcode("bcf","(%s >> 3), (%s & 7)",
5297 AOP(result)->aopu.aop_dir,
5298 AOP(result)->aopu.aop_dir);
5299 emitcode("btfss","(%s >> 3), (%s & 7)",
5300 AOP(right)->aopu.aop_dir,
5301 AOP(right)->aopu.aop_dir);
5302 emitcode("btfsc","(%s >> 3), (%s & 7)",
5303 AOP(left)->aopu.aop_dir,
5304 AOP(left)->aopu.aop_dir);
5305 emitcode("bsf","(%s >> 3), (%s & 7)",
5306 AOP(result)->aopu.aop_dir,
5307 AOP(result)->aopu.aop_dir);
5312 symbol *tlbl = newiTempLabel(NULL);
5313 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5314 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5315 emitcode(";XXX setb","c");
5316 emitcode(";XXX jb","%s,%05d_DS_",
5317 AOP(left)->aopu.aop_dir,tlbl->key+100);
5319 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5320 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5321 jmpTrueOrFalse(ifx, tlbl);
5325 emitcode("","%05d_DS_:",tlbl->key+100);
5334 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5335 genIfxJump(ifx, "c");
5339 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5340 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5341 if((AOP_TYPE(right) == AOP_LIT) &&
5342 (AOP_TYPE(result) == AOP_CRY) &&
5343 (AOP_TYPE(left) != AOP_CRY)){
5345 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5348 emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5350 continueIfTrue(ifx);
5353 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5354 // lit = 0, result = boolean(left)
5356 emitcode(";XXX setb","c");
5359 symbol *tlbl = newiTempLabel(NULL);
5360 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5362 emitcode("","%05d_DS_:",tlbl->key+100);
5364 genIfxJump (ifx,"a");
5372 /* if left is same as result */
5373 if(sameRegs(AOP(result),AOP(left))){
5374 for(;size--; offset++,lit>>=8) {
5375 if(AOP_TYPE(right) == AOP_LIT){
5376 if((lit & 0xff) == 0)
5377 /* or'ing with 0 has no effect */
5380 int p = my_powof2(lit & 0xff);
5382 /* only one bit is set in the literal, so use a bsf instruction */
5383 emitpcode(POC_BSF, popGet(AOP(left),offset,FALSE,FALSE));
5384 emitcode("bsf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5386 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5387 emitpcode(POC_IORWF, popGet(AOP(left),offset,FALSE,FALSE));
5389 emitcode("movlw","0x%x", (lit & 0xff));
5390 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE),p);
5395 if (AOP_TYPE(left) == AOP_ACC) {
5396 emitpcode(POC_IORFW, popGet(AOP(right),offset,FALSE,FALSE));
5397 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5399 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
5400 emitpcode(POC_IORWF, popGet(AOP(left),offset,FALSE,FALSE));
5402 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5403 emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5409 // left & result in different registers
5410 if(AOP_TYPE(result) == AOP_CRY){
5412 // if(size), result in bit
5413 // if(!size && ifx), conditional oper: if(left | right)
5414 symbol *tlbl = newiTempLabel(NULL);
5415 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5416 emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5419 emitcode(";XXX setb","c");
5421 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5422 emitcode(";XXX orl","a,%s",
5423 aopGet(AOP(left),offset,FALSE,FALSE));
5424 emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5429 emitcode("","%05d_DS_:",tlbl->key+100);
5432 jmpTrueOrFalse(ifx, tlbl);
5433 } else for(;(size--);offset++){
5435 // result = left & right
5436 if(AOP_TYPE(right) == AOP_LIT){
5437 int t = (lit >> (offset*8)) & 0x0FFL;
5440 emitpcode(POC_MOVFW, popGet(AOP(left),offset,FALSE,FALSE));
5441 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
5443 emitcode("movf","%s,w",
5444 aopGet(AOP(left),offset,FALSE,FALSE));
5445 emitcode("movwf","%s",
5446 aopGet(AOP(result),offset,FALSE,FALSE));
5449 emitpcode(POC_MOVLW, popGetLit(t));
5450 emitpcode(POC_IORFW, popGet(AOP(left),offset,FALSE,FALSE));
5451 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
5453 emitcode("movlw","0x%x",t);
5454 emitcode("iorwf","%s,w",
5455 aopGet(AOP(left),offset,FALSE,FALSE));
5456 emitcode("movwf","%s",
5457 aopGet(AOP(result),offset,FALSE,FALSE));
5463 // faster than result <- left, anl result,right
5464 // and better if result is SFR
5465 if (AOP_TYPE(left) == AOP_ACC) {
5466 emitpcode(POC_IORWF, popGet(AOP(right),offset,FALSE,FALSE));
5467 emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5469 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
5470 emitpcode(POC_IORFW, popGet(AOP(left),offset,FALSE,FALSE));
5472 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5473 emitcode("iorwf","%s,w",
5474 aopGet(AOP(left),offset,FALSE,FALSE));
5476 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
5477 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5482 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5483 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5484 freeAsmop(result,NULL,ic,TRUE);
5487 /*-----------------------------------------------------------------*/
5488 /* genXor - code for xclusive or */
5489 /*-----------------------------------------------------------------*/
5490 static void genXor (iCode *ic, iCode *ifx)
5492 operand *left, *right, *result;
5494 unsigned long lit = 0L;
5496 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5498 aopOp((left = IC_LEFT(ic)),ic,FALSE);
5499 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5500 aopOp((result=IC_RESULT(ic)),ic,TRUE);
5502 /* if left is a literal & right is not ||
5503 if left needs acc & right does not */
5504 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5505 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5506 operand *tmp = right ;
5511 /* if result = right then exchange them */
5512 if(sameRegs(AOP(result),AOP(right))){
5513 operand *tmp = right ;
5518 /* if right is bit then exchange them */
5519 if (AOP_TYPE(right) == AOP_CRY &&
5520 AOP_TYPE(left) != AOP_CRY){
5521 operand *tmp = right ;
5525 if(AOP_TYPE(right) == AOP_LIT)
5526 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5528 size = AOP_SIZE(result);
5532 if (AOP_TYPE(left) == AOP_CRY){
5533 if(AOP_TYPE(right) == AOP_LIT){
5534 // c = bit & literal;
5536 // lit>>1 != 0 => result = 1
5537 if(AOP_TYPE(result) == AOP_CRY){
5539 emitcode("setb","%s",AOP(result)->aopu.aop_dir);
5541 continueIfTrue(ifx);
5544 emitcode("setb","c");
5548 // lit == 0, result = left
5549 if(size && sameRegs(AOP(result),AOP(left)))
5551 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5553 // lit == 1, result = not(left)
5554 if(size && sameRegs(AOP(result),AOP(left))){
5555 emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5558 emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5559 emitcode("cpl","c");
5566 symbol *tlbl = newiTempLabel(NULL);
5567 if (AOP_TYPE(right) == AOP_CRY){
5569 emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5572 int sizer = AOP_SIZE(right);
5574 // if val>>1 != 0, result = 1
5575 emitcode("setb","c");
5577 MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5579 // test the msb of the lsb
5580 emitcode("anl","a,#0xfe");
5581 emitcode("jnz","%05d_DS_",tlbl->key+100);
5585 emitcode("rrc","a");
5587 emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5588 emitcode("cpl","c");
5589 emitcode("","%05d_DS_:",(tlbl->key+100));
5596 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5597 genIfxJump(ifx, "c");
5601 if(sameRegs(AOP(result),AOP(left))){
5602 /* if left is same as result */
5603 for(;size--; offset++) {
5604 if(AOP_TYPE(right) == AOP_LIT){
5605 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
5608 if (IS_AOP_PREG(left)) {
5609 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5610 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5611 aopPut(AOP(result),"a",offset);
5613 emitcode("xrl","%s,%s",
5614 aopGet(AOP(left),offset,FALSE,TRUE),
5615 aopGet(AOP(right),offset,FALSE,FALSE));
5617 if (AOP_TYPE(left) == AOP_ACC)
5618 emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5620 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5621 if (IS_AOP_PREG(left)) {
5622 emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5623 aopPut(AOP(result),"a",offset);
5625 emitcode("xrl","%s,a",
5626 aopGet(AOP(left),offset,FALSE,TRUE));
5631 // left & result in different registers
5632 if(AOP_TYPE(result) == AOP_CRY){
5634 // if(size), result in bit
5635 // if(!size && ifx), conditional oper: if(left ^ right)
5636 symbol *tlbl = newiTempLabel(NULL);
5637 int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5639 emitcode("setb","c");
5641 if((AOP_TYPE(right) == AOP_LIT) &&
5642 (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5643 MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5645 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5646 emitcode("xrl","a,%s",
5647 aopGet(AOP(left),offset,FALSE,FALSE));
5649 emitcode("jnz","%05d_DS_",tlbl->key+100);
5654 emitcode("","%05d_DS_:",tlbl->key+100);
5657 jmpTrueOrFalse(ifx, tlbl);
5658 } else for(;(size--);offset++){
5660 // result = left & right
5661 if(AOP_TYPE(right) == AOP_LIT){
5662 int t = (lit >> (offset*8)) & 0x0FFL;
5665 emitcode("movf","%s,w",
5666 aopGet(AOP(left),offset,FALSE,FALSE));
5667 emitcode("movwf","%s",
5668 aopGet(AOP(result),offset,FALSE,FALSE));
5671 emitcode("comf","%s,w",
5672 aopGet(AOP(left),offset,FALSE,FALSE));
5673 emitcode("movwf","%s",
5674 aopGet(AOP(result),offset,FALSE,FALSE));
5677 emitcode("movlw","0x%x",t);
5678 emitcode("xorwf","%s,w",
5679 aopGet(AOP(left),offset,FALSE,FALSE));
5680 emitcode("movwf","%s",
5681 aopGet(AOP(result),offset,FALSE,FALSE));
5687 // faster than result <- left, anl result,right
5688 // and better if result is SFR
5689 if (AOP_TYPE(left) == AOP_ACC)
5690 emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5692 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5693 emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5695 if ( AOP_TYPE(result) != AOP_ACC)
5696 emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5701 freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5702 freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5703 freeAsmop(result,NULL,ic,TRUE);
5706 /*-----------------------------------------------------------------*/
5707 /* genInline - write the inline code out */
5708 /*-----------------------------------------------------------------*/
5709 static void genInline (iCode *ic)
5711 char buffer[MAX_INLINEASM];
5715 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5717 _G.inLine += (!options.asmpeep);
5718 strcpy(buffer,IC_INLINE(ic));
5720 /* emit each line as a code */
5739 /* emitcode("",buffer); */
5740 _G.inLine -= (!options.asmpeep);
5743 /*-----------------------------------------------------------------*/
5744 /* genRRC - rotate right with carry */
5745 /*-----------------------------------------------------------------*/
5746 static void genRRC (iCode *ic)
5748 operand *left , *result ;
5749 int size, offset = 0;
5752 /* rotate right with carry */
5754 result=IC_RESULT(ic);
5755 aopOp (left,ic,FALSE);
5756 aopOp (result,ic,FALSE);
5758 /* move it to the result */
5759 size = AOP_SIZE(result);
5763 l = aopGet(AOP(left),offset,FALSE,FALSE);
5765 emitcode("rrc","a");
5766 if (AOP_SIZE(result) > 1)
5767 aopPut(AOP(result),"a",offset--);
5769 /* now we need to put the carry into the
5770 highest order byte of the result */
5771 if (AOP_SIZE(result) > 1) {
5772 l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
5775 emitcode("mov","acc.7,c");
5776 aopPut(AOP(result),"a",AOP_SIZE(result)-1);
5777 freeAsmop(left,NULL,ic,TRUE);
5778 freeAsmop(result,NULL,ic,TRUE);
5781 /*-----------------------------------------------------------------*/
5782 /* genRLC - generate code for rotate left with carry */
5783 /*-----------------------------------------------------------------*/
5784 static void genRLC (iCode *ic)
5786 operand *left , *result ;
5787 int size, offset = 0;
5790 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5791 /* rotate right with carry */
5793 result=IC_RESULT(ic);
5794 aopOp (left,ic,FALSE);
5795 aopOp (result,ic,FALSE);
5797 /* move it to the result */
5798 size = AOP_SIZE(result);
5801 l = aopGet(AOP(left),offset,FALSE,FALSE);
5803 emitcode("add","a,acc");
5804 if (AOP_SIZE(result) > 1)
5805 aopPut(AOP(result),"a",offset++);
5807 l = aopGet(AOP(left),offset,FALSE,FALSE);
5809 emitcode("rlc","a");
5810 if (AOP_SIZE(result) > 1)
5811 aopPut(AOP(result),"a",offset++);
5814 /* now we need to put the carry into the
5815 highest order byte of the result */
5816 if (AOP_SIZE(result) > 1) {
5817 l = aopGet(AOP(result),0,FALSE,FALSE);
5820 emitcode("mov","acc.0,c");
5821 aopPut(AOP(result),"a",0);
5822 freeAsmop(left,NULL,ic,TRUE);
5823 freeAsmop(result,NULL,ic,TRUE);
5826 /*-----------------------------------------------------------------*/
5827 /* genGetHbit - generates code get highest order bit */
5828 /*-----------------------------------------------------------------*/
5829 static void genGetHbit (iCode *ic)
5831 operand *left, *result;
5833 result=IC_RESULT(ic);
5834 aopOp (left,ic,FALSE);
5835 aopOp (result,ic,FALSE);
5837 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5838 /* get the highest order byte into a */
5839 MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5840 if(AOP_TYPE(result) == AOP_CRY){
5841 emitcode("rlc","a");
5846 emitcode("anl","a,#0x01");
5851 freeAsmop(left,NULL,ic,TRUE);
5852 freeAsmop(result,NULL,ic,TRUE);
5855 /*-----------------------------------------------------------------*/
5856 /* AccRol - rotate left accumulator by known count */
5857 /*-----------------------------------------------------------------*/
5858 static void AccRol (int shCount)
5860 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5861 shCount &= 0x0007; // shCount : 0..7
5873 emitcode("swap","a");
5877 emitcode("swap","a");
5880 emitcode("swap","a");
5893 /*-----------------------------------------------------------------*/
5894 /* AccLsh - left shift accumulator by known count */
5895 /*-----------------------------------------------------------------*/
5896 static void AccLsh (int shCount)
5898 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5901 emitcode("add","a,acc");
5904 emitcode("add","a,acc");
5905 emitcode("add","a,acc");
5907 /* rotate left accumulator */
5909 /* and kill the lower order bits */
5910 emitcode("anl","a,#0x%02x", SLMask[shCount]);
5915 /*-----------------------------------------------------------------*/
5916 /* AccRsh - right shift accumulator by known count */
5917 /*-----------------------------------------------------------------*/
5918 static void AccRsh (int shCount)
5920 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5924 emitcode("rrc","a");
5926 /* rotate right accumulator */
5927 AccRol(8 - shCount);
5928 /* and kill the higher order bits */
5929 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5934 /*-----------------------------------------------------------------*/
5935 /* AccSRsh - signed right shift accumulator by known count */
5936 /*-----------------------------------------------------------------*/
5937 static void AccSRsh (int shCount)
5940 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5943 emitcode("mov","c,acc.7");
5944 emitcode("rrc","a");
5945 } else if(shCount == 2){
5946 emitcode("mov","c,acc.7");
5947 emitcode("rrc","a");
5948 emitcode("mov","c,acc.7");
5949 emitcode("rrc","a");
5951 tlbl = newiTempLabel(NULL);
5952 /* rotate right accumulator */
5953 AccRol(8 - shCount);
5954 /* and kill the higher order bits */
5955 emitcode("anl","a,#0x%02x", SRMask[shCount]);
5956 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
5957 emitcode("orl","a,#0x%02x",
5958 (unsigned char)~SRMask[shCount]);
5959 emitcode("","%05d_DS_:",tlbl->key+100);
5964 /*-----------------------------------------------------------------*/
5965 /* shiftR1Left2Result - shift right one byte from left to result */
5966 /*-----------------------------------------------------------------*/
5967 static void shiftR1Left2Result (operand *left, int offl,
5968 operand *result, int offr,
5969 int shCount, int sign)
5971 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5972 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
5973 /* shift right accumulator */
5978 aopPut(AOP(result),"a",offr);
5981 /*-----------------------------------------------------------------*/
5982 /* shiftL1Left2Result - shift left one byte from left to result */
5983 /*-----------------------------------------------------------------*/
5984 static void shiftL1Left2Result (operand *left, int offl,
5985 operand *result, int offr, int shCount)
5988 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
5989 l = aopGet(AOP(left),offl,FALSE,FALSE);
5991 /* shift left accumulator */
5993 aopPut(AOP(result),"a",offr);
5996 /*-----------------------------------------------------------------*/
5997 /* movLeft2Result - move byte from left to result */
5998 /*-----------------------------------------------------------------*/
5999 static void movLeft2Result (operand *left, int offl,
6000 operand *result, int offr, int sign)
6003 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6004 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6005 l = aopGet(AOP(left),offl,FALSE,FALSE);
6007 if (*l == '@' && (IS_AOP_PREG(result))) {
6008 emitcode("mov","a,%s",l);
6009 aopPut(AOP(result),"a",offr);
6012 aopPut(AOP(result),l,offr);
6014 /* MSB sign in acc.7 ! */
6015 if(getDataSize(left) == offl+1){
6016 emitcode("mov","a,%s",l);
6017 aopPut(AOP(result),"a",offr);
6024 /*-----------------------------------------------------------------*/
6025 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6026 /*-----------------------------------------------------------------*/
6027 static void AccAXRrl1 (char *x)
6029 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6030 emitcode("rrc","a");
6031 emitcode("xch","a,%s", x);
6032 emitcode("rrc","a");
6033 emitcode("xch","a,%s", x);
6036 /*-----------------------------------------------------------------*/
6037 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6038 /*-----------------------------------------------------------------*/
6039 static void AccAXLrl1 (char *x)
6041 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6042 emitcode("xch","a,%s",x);
6043 emitcode("rlc","a");
6044 emitcode("xch","a,%s",x);
6045 emitcode("rlc","a");
6048 /*-----------------------------------------------------------------*/
6049 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6050 /*-----------------------------------------------------------------*/
6051 static void AccAXLsh1 (char *x)
6053 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6054 emitcode("xch","a,%s",x);
6055 emitcode("add","a,acc");
6056 emitcode("xch","a,%s",x);
6057 emitcode("rlc","a");
6060 /*-----------------------------------------------------------------*/
6061 /* AccAXLsh - left shift a:x by known count (0..7) */
6062 /*-----------------------------------------------------------------*/
6063 static void AccAXLsh (char *x, int shCount)
6065 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6078 case 5 : // AAAAABBB:CCCCCDDD
6079 AccRol(shCount); // BBBAAAAA:CCCCCDDD
6080 emitcode("anl","a,#0x%02x",
6081 SLMask[shCount]); // BBB00000:CCCCCDDD
6082 emitcode("xch","a,%s",x); // CCCCCDDD:BBB00000
6083 AccRol(shCount); // DDDCCCCC:BBB00000
6084 emitcode("xch","a,%s",x); // BBB00000:DDDCCCCC
6085 emitcode("xrl","a,%s",x); // (BBB^DDD)CCCCC:DDDCCCCC
6086 emitcode("xch","a,%s",x); // DDDCCCCC:(BBB^DDD)CCCCC
6087 emitcode("anl","a,#0x%02x",
6088 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6089 emitcode("xch","a,%s",x); // (BBB^DDD)CCCCC:DDD00000
6090 emitcode("xrl","a,%s",x); // BBBCCCCC:DDD00000
6092 case 6 : // AAAAAABB:CCCCCCDD
6093 emitcode("anl","a,#0x%02x",
6094 SRMask[shCount]); // 000000BB:CCCCCCDD
6095 emitcode("mov","c,acc.0"); // c = B
6096 emitcode("xch","a,%s",x); // CCCCCCDD:000000BB
6097 AccAXRrl1(x); // BCCCCCCD:D000000B
6098 AccAXRrl1(x); // BBCCCCCC:DD000000
6100 case 7 : // a:x <<= 7
6101 emitcode("anl","a,#0x%02x",
6102 SRMask[shCount]); // 0000000B:CCCCCCCD
6103 emitcode("mov","c,acc.0"); // c = B
6104 emitcode("xch","a,%s",x); // CCCCCCCD:0000000B
6105 AccAXRrl1(x); // BCCCCCCC:D0000000
6112 /*-----------------------------------------------------------------*/
6113 /* AccAXRsh - right shift a:x known count (0..7) */
6114 /*-----------------------------------------------------------------*/
6115 static void AccAXRsh (char *x, int shCount)
6117 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6123 AccAXRrl1(x); // 0->a:x
6127 AccAXRrl1(x); // 0->a:x
6129 AccAXRrl1(x); // 0->a:x
6133 case 5 : // AAAAABBB:CCCCCDDD = a:x
6134 AccRol(8 - shCount); // BBBAAAAA:DDDCCCCC
6135 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
6136 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
6137 emitcode("anl","a,#0x%02x",
6138 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6139 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
6140 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6141 emitcode("anl","a,#0x%02x",
6142 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6143 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
6144 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
6145 emitcode("xch","a,%s",x); // 000AAAAA:BBBCCCCC
6147 case 6 : // AABBBBBB:CCDDDDDD
6148 emitcode("mov","c,acc.7");
6149 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
6150 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
6151 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
6152 emitcode("anl","a,#0x%02x",
6153 SRMask[shCount]); // 000000AA:BBBBBBCC
6155 case 7 : // ABBBBBBB:CDDDDDDD
6156 emitcode("mov","c,acc.7"); // c = A
6157 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
6158 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
6159 emitcode("anl","a,#0x%02x",
6160 SRMask[shCount]); // 0000000A:BBBBBBBC
6167 /*-----------------------------------------------------------------*/
6168 /* AccAXRshS - right shift signed a:x known count (0..7) */
6169 /*-----------------------------------------------------------------*/
6170 static void AccAXRshS (char *x, int shCount)
6173 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6178 emitcode("mov","c,acc.7");
6179 AccAXRrl1(x); // s->a:x
6182 emitcode("mov","c,acc.7");
6183 AccAXRrl1(x); // s->a:x
6184 emitcode("mov","c,acc.7");
6185 AccAXRrl1(x); // s->a:x
6189 case 5 : // AAAAABBB:CCCCCDDD = a:x
6190 tlbl = newiTempLabel(NULL);
6191 AccRol(8 - shCount); // BBBAAAAA:CCCCCDDD
6192 emitcode("xch","a,%s",x); // CCCCCDDD:BBBAAAAA
6193 AccRol(8 - shCount); // DDDCCCCC:BBBAAAAA
6194 emitcode("anl","a,#0x%02x",
6195 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6196 emitcode("xrl","a,%s",x); // BBB(CCCCC^AAAAA):BBBAAAAA
6197 emitcode("xch","a,%s",x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6198 emitcode("anl","a,#0x%02x",
6199 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6200 emitcode("xch","a,%s",x); // BBB(CCCCC^AAAAA):000AAAAA
6201 emitcode("xrl","a,%s",x); // BBBCCCCC:000AAAAA
6202 emitcode("xch","a,%s",x); // 000SAAAA:BBBCCCCC
6203 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6204 emitcode("orl","a,#0x%02x",
6205 (unsigned char)~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6206 emitcode("","%05d_DS_:",tlbl->key+100);
6207 break; // SSSSAAAA:BBBCCCCC
6208 case 6 : // AABBBBBB:CCDDDDDD
6209 tlbl = newiTempLabel(NULL);
6210 emitcode("mov","c,acc.7");
6211 AccAXLrl1(x); // ABBBBBBC:CDDDDDDA
6212 AccAXLrl1(x); // BBBBBBCC:DDDDDDAA
6213 emitcode("xch","a,%s",x); // DDDDDDAA:BBBBBBCC
6214 emitcode("anl","a,#0x%02x",
6215 SRMask[shCount]); // 000000AA:BBBBBBCC
6216 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6217 emitcode("orl","a,#0x%02x",
6218 (unsigned char)~SRMask[shCount]); // 111111AA:BBBBBBCC
6219 emitcode("","%05d_DS_:",tlbl->key+100);
6221 case 7 : // ABBBBBBB:CDDDDDDD
6222 tlbl = newiTempLabel(NULL);
6223 emitcode("mov","c,acc.7"); // c = A
6224 AccAXLrl1(x); // BBBBBBBC:DDDDDDDA
6225 emitcode("xch","a,%s",x); // DDDDDDDA:BBBBBBCC
6226 emitcode("anl","a,#0x%02x",
6227 SRMask[shCount]); // 0000000A:BBBBBBBC
6228 emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6229 emitcode("orl","a,#0x%02x",
6230 (unsigned char)~SRMask[shCount]); // 1111111A:BBBBBBBC
6231 emitcode("","%05d_DS_:",tlbl->key+100);
6238 /*-----------------------------------------------------------------*/
6239 /* shiftL2Left2Result - shift left two bytes from left to result */
6240 /*-----------------------------------------------------------------*/
6241 static void shiftL2Left2Result (operand *left, int offl,
6242 operand *result, int offr, int shCount)
6244 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6245 if(sameRegs(AOP(result), AOP(left)) &&
6246 ((offl + MSB16) == offr)){
6247 /* don't crash result[offr] */
6248 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6249 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6251 movLeft2Result(left,offl, result, offr, 0);
6252 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6254 /* ax << shCount (x = lsb(result))*/
6255 AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6256 aopPut(AOP(result),"a",offr+MSB16);
6260 /*-----------------------------------------------------------------*/
6261 /* shiftR2Left2Result - shift right two bytes from left to result */
6262 /*-----------------------------------------------------------------*/
6263 static void shiftR2Left2Result (operand *left, int offl,
6264 operand *result, int offr,
6265 int shCount, int sign)
6267 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6268 if(sameRegs(AOP(result), AOP(left)) &&
6269 ((offl + MSB16) == offr)){
6270 /* don't crash result[offr] */
6271 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6272 emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6274 movLeft2Result(left,offl, result, offr, 0);
6275 MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6277 /* a:x >> shCount (x = lsb(result))*/
6279 AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6281 AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6282 if(getDataSize(result) > 1)
6283 aopPut(AOP(result),"a",offr+MSB16);
6286 /*-----------------------------------------------------------------*/
6287 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6288 /*-----------------------------------------------------------------*/
6289 static void shiftLLeftOrResult (operand *left, int offl,
6290 operand *result, int offr, int shCount)
6292 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6293 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6294 /* shift left accumulator */
6296 /* or with result */
6297 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6298 /* back to result */
6299 aopPut(AOP(result),"a",offr);
6302 /*-----------------------------------------------------------------*/
6303 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6304 /*-----------------------------------------------------------------*/
6305 static void shiftRLeftOrResult (operand *left, int offl,
6306 operand *result, int offr, int shCount)
6308 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6309 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6310 /* shift right accumulator */
6312 /* or with result */
6313 emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6314 /* back to result */
6315 aopPut(AOP(result),"a",offr);
6318 /*-----------------------------------------------------------------*/
6319 /* genlshOne - left shift a one byte quantity by known count */
6320 /*-----------------------------------------------------------------*/
6321 static void genlshOne (operand *result, operand *left, int shCount)
6323 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6324 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6327 /*-----------------------------------------------------------------*/
6328 /* genlshTwo - left shift two bytes by known amount != 0 */
6329 /*-----------------------------------------------------------------*/
6330 static void genlshTwo (operand *result,operand *left, int shCount)
6334 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6335 size = getDataSize(result);
6337 /* if shCount >= 8 */
6343 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6345 movLeft2Result(left, LSB, result, MSB16, 0);
6347 aopPut(AOP(result),zero,LSB);
6350 /* 1 <= shCount <= 7 */
6353 shiftL1Left2Result(left, LSB, result, LSB, shCount);
6355 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6359 /*-----------------------------------------------------------------*/
6360 /* shiftLLong - shift left one long from left to result */
6361 /* offl = LSB or MSB16 */
6362 /*-----------------------------------------------------------------*/
6363 static void shiftLLong (operand *left, operand *result, int offr )
6366 int size = AOP_SIZE(result);
6368 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6369 if(size >= LSB+offr){
6370 l = aopGet(AOP(left),LSB,FALSE,FALSE);
6372 emitcode("add","a,acc");
6373 if (sameRegs(AOP(left),AOP(result)) &&
6374 size >= MSB16+offr && offr != LSB )
6375 emitcode("xch","a,%s",
6376 aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6378 aopPut(AOP(result),"a",LSB+offr);
6381 if(size >= MSB16+offr){
6382 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6383 l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6386 emitcode("rlc","a");
6387 if (sameRegs(AOP(left),AOP(result)) &&
6388 size >= MSB24+offr && offr != LSB)
6389 emitcode("xch","a,%s",
6390 aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6392 aopPut(AOP(result),"a",MSB16+offr);
6395 if(size >= MSB24+offr){
6396 if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6397 l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6400 emitcode("rlc","a");
6401 if (sameRegs(AOP(left),AOP(result)) &&
6402 size >= MSB32+offr && offr != LSB )
6403 emitcode("xch","a,%s",
6404 aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6406 aopPut(AOP(result),"a",MSB24+offr);
6409 if(size > MSB32+offr){
6410 if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6411 l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6414 emitcode("rlc","a");
6415 aopPut(AOP(result),"a",MSB32+offr);
6418 aopPut(AOP(result),zero,LSB);
6421 /*-----------------------------------------------------------------*/
6422 /* genlshFour - shift four byte by a known amount != 0 */
6423 /*-----------------------------------------------------------------*/
6424 static void genlshFour (operand *result, operand *left, int shCount)
6428 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6429 size = AOP_SIZE(result);
6431 /* if shifting more that 3 bytes */
6432 if (shCount >= 24 ) {
6435 /* lowest order of left goes to the highest
6436 order of the destination */
6437 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6439 movLeft2Result(left, LSB, result, MSB32, 0);
6440 aopPut(AOP(result),zero,LSB);
6441 aopPut(AOP(result),zero,MSB16);
6442 aopPut(AOP(result),zero,MSB32);
6446 /* more than two bytes */
6447 else if ( shCount >= 16 ) {
6448 /* lower order two bytes goes to higher order two bytes */
6450 /* if some more remaining */
6452 shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6454 movLeft2Result(left, MSB16, result, MSB32, 0);
6455 movLeft2Result(left, LSB, result, MSB24, 0);
6457 aopPut(AOP(result),zero,MSB16);
6458 aopPut(AOP(result),zero,LSB);
6462 /* if more than 1 byte */
6463 else if ( shCount >= 8 ) {
6464 /* lower order three bytes goes to higher order three bytes */
6468 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6470 movLeft2Result(left, LSB, result, MSB16, 0);
6472 else{ /* size = 4 */
6474 movLeft2Result(left, MSB24, result, MSB32, 0);
6475 movLeft2Result(left, MSB16, result, MSB24, 0);
6476 movLeft2Result(left, LSB, result, MSB16, 0);
6477 aopPut(AOP(result),zero,LSB);
6479 else if(shCount == 1)
6480 shiftLLong(left, result, MSB16);
6482 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6483 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6484 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6485 aopPut(AOP(result),zero,LSB);
6490 /* 1 <= shCount <= 7 */
6491 else if(shCount <= 2){
6492 shiftLLong(left, result, LSB);
6494 shiftLLong(result, result, LSB);
6496 /* 3 <= shCount <= 7, optimize */
6498 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6499 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6500 shiftL2Left2Result(left, LSB, result, LSB, shCount);
6504 /*-----------------------------------------------------------------*/
6505 /* genLeftShiftLiteral - left shifting by known count */
6506 /*-----------------------------------------------------------------*/
6507 static void genLeftShiftLiteral (operand *left,
6512 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6515 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6516 freeAsmop(right,NULL,ic,TRUE);
6518 aopOp(left,ic,FALSE);
6519 aopOp(result,ic,FALSE);
6521 size = getSize(operandType(result));
6524 emitcode("; shift left ","result %d, left %d",size,
6528 /* I suppose that the left size >= result size */
6531 movLeft2Result(left, size, result, size, 0);
6535 else if(shCount >= (size * 8))
6537 aopPut(AOP(result),zero,size);
6541 genlshOne (result,left,shCount);
6546 genlshTwo (result,left,shCount);
6550 genlshFour (result,left,shCount);
6554 freeAsmop(left,NULL,ic,TRUE);
6555 freeAsmop(result,NULL,ic,TRUE);
6558 /*-----------------------------------------------------------------*/
6559 /* genLeftShift - generates code for left shifting */
6560 /*-----------------------------------------------------------------*/
6561 static void genLeftShift (iCode *ic)
6563 operand *left,*right, *result;
6566 symbol *tlbl , *tlbl1;
6568 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6570 right = IC_RIGHT(ic);
6572 result = IC_RESULT(ic);
6574 aopOp(right,ic,FALSE);
6576 /* if the shift count is known then do it
6577 as efficiently as possible */
6578 if (AOP_TYPE(right) == AOP_LIT) {
6579 genLeftShiftLiteral (left,right,result,ic);
6583 /* shift count is unknown then we have to form
6584 a loop get the loop count in B : Note: we take
6585 only the lower order byte since shifting
6586 more that 32 bits make no sense anyway, ( the
6587 largest size of an object can be only 32 bits ) */
6589 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6590 emitcode("inc","b");
6591 freeAsmop (right,NULL,ic,TRUE);
6592 aopOp(left,ic,FALSE);
6593 aopOp(result,ic,FALSE);
6595 /* now move the left to the result if they are not the
6597 if (!sameRegs(AOP(left),AOP(result)) &&
6598 AOP_SIZE(result) > 1) {
6600 size = AOP_SIZE(result);
6603 l = aopGet(AOP(left),offset,FALSE,TRUE);
6604 if (*l == '@' && (IS_AOP_PREG(result))) {
6606 emitcode("mov","a,%s",l);
6607 aopPut(AOP(result),"a",offset);
6609 aopPut(AOP(result),l,offset);
6614 tlbl = newiTempLabel(NULL);
6615 size = AOP_SIZE(result);
6617 tlbl1 = newiTempLabel(NULL);
6619 /* if it is only one byte then */
6621 symbol *tlbl1 = newiTempLabel(NULL);
6623 l = aopGet(AOP(left),0,FALSE,FALSE);
6625 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6626 emitcode("","%05d_DS_:",tlbl->key+100);
6627 emitcode("add","a,acc");
6628 emitcode("","%05d_DS_:",tlbl1->key+100);
6629 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6630 aopPut(AOP(result),"a",0);
6634 reAdjustPreg(AOP(result));
6636 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6637 emitcode("","%05d_DS_:",tlbl->key+100);
6638 l = aopGet(AOP(result),offset,FALSE,FALSE);
6640 emitcode("add","a,acc");
6641 aopPut(AOP(result),"a",offset++);
6643 l = aopGet(AOP(result),offset,FALSE,FALSE);
6645 emitcode("rlc","a");
6646 aopPut(AOP(result),"a",offset++);
6648 reAdjustPreg(AOP(result));
6650 emitcode("","%05d_DS_:",tlbl1->key+100);
6651 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6653 freeAsmop(left,NULL,ic,TRUE);
6654 freeAsmop(result,NULL,ic,TRUE);
6657 /*-----------------------------------------------------------------*/
6658 /* genrshOne - right shift a one byte quantity by known count */
6659 /*-----------------------------------------------------------------*/
6660 static void genrshOne (operand *result, operand *left,
6661 int shCount, int sign)
6663 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6664 shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
6667 /*-----------------------------------------------------------------*/
6668 /* genrshTwo - right shift two bytes by known amount != 0 */
6669 /*-----------------------------------------------------------------*/
6670 static void genrshTwo (operand *result,operand *left,
6671 int shCount, int sign)
6673 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6674 /* if shCount >= 8 */
6678 shiftR1Left2Result(left, MSB16, result, LSB,
6681 movLeft2Result(left, MSB16, result, LSB, sign);
6682 addSign(result, MSB16, sign);
6685 /* 1 <= shCount <= 7 */
6687 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
6690 /*-----------------------------------------------------------------*/
6691 /* shiftRLong - shift right one long from left to result */
6692 /* offl = LSB or MSB16 */
6693 /*-----------------------------------------------------------------*/
6694 static void shiftRLong (operand *left, int offl,
6695 operand *result, int sign)
6697 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6699 emitcode("clr","c");
6700 MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
6702 emitcode("mov","c,acc.7");
6703 emitcode("rrc","a");
6704 aopPut(AOP(result),"a",MSB32-offl);
6706 /* add sign of "a" */
6707 addSign(result, MSB32, sign);
6709 MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
6710 emitcode("rrc","a");
6711 aopPut(AOP(result),"a",MSB24-offl);
6713 MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
6714 emitcode("rrc","a");
6715 aopPut(AOP(result),"a",MSB16-offl);
6718 MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
6719 emitcode("rrc","a");
6720 aopPut(AOP(result),"a",LSB);
6724 /*-----------------------------------------------------------------*/
6725 /* genrshFour - shift four byte by a known amount != 0 */
6726 /*-----------------------------------------------------------------*/
6727 static void genrshFour (operand *result, operand *left,
6728 int shCount, int sign)
6730 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6731 /* if shifting more that 3 bytes */
6732 if(shCount >= 24 ) {
6735 shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
6737 movLeft2Result(left, MSB32, result, LSB, sign);
6738 addSign(result, MSB16, sign);
6740 else if(shCount >= 16){
6743 shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
6745 movLeft2Result(left, MSB24, result, LSB, 0);
6746 movLeft2Result(left, MSB32, result, MSB16, sign);
6748 addSign(result, MSB24, sign);
6750 else if(shCount >= 8){
6753 shiftRLong(left, MSB16, result, sign);
6754 else if(shCount == 0){
6755 movLeft2Result(left, MSB16, result, LSB, 0);
6756 movLeft2Result(left, MSB24, result, MSB16, 0);
6757 movLeft2Result(left, MSB32, result, MSB24, sign);
6758 addSign(result, MSB32, sign);
6761 shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
6762 shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
6763 /* the last shift is signed */
6764 shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
6765 addSign(result, MSB32, sign);
6768 else{ /* 1 <= shCount <= 7 */
6770 shiftRLong(left, LSB, result, sign);
6772 shiftRLong(result, LSB, result, sign);
6775 shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
6776 shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
6777 shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
6782 /*-----------------------------------------------------------------*/
6783 /* genRightShiftLiteral - right shifting by known count */
6784 /*-----------------------------------------------------------------*/
6785 static void genRightShiftLiteral (operand *left,
6791 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6794 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6795 freeAsmop(right,NULL,ic,TRUE);
6797 aopOp(left,ic,FALSE);
6798 aopOp(result,ic,FALSE);
6801 emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
6805 size = getDataSize(left);
6806 /* test the LEFT size !!! */
6808 /* I suppose that the left size >= result size */
6810 size = getDataSize(result);
6812 movLeft2Result(left, size, result, size, 0);
6815 else if(shCount >= (size * 8)){
6817 /* get sign in acc.7 */
6818 MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
6819 addSign(result, LSB, sign);
6823 genrshOne (result,left,shCount,sign);
6827 genrshTwo (result,left,shCount,sign);
6831 genrshFour (result,left,shCount,sign);
6837 freeAsmop(left,NULL,ic,TRUE);
6838 freeAsmop(result,NULL,ic,TRUE);
6842 /*-----------------------------------------------------------------*/
6843 /* genSignedRightShift - right shift of signed number */
6844 /*-----------------------------------------------------------------*/
6845 static void genSignedRightShift (iCode *ic)
6847 operand *right, *left, *result;
6850 symbol *tlbl, *tlbl1 ;
6852 /* we do it the hard way put the shift count in b
6853 and loop thru preserving the sign */
6854 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6856 right = IC_RIGHT(ic);
6858 result = IC_RESULT(ic);
6860 aopOp(right,ic,FALSE);
6863 if ( AOP_TYPE(right) == AOP_LIT) {
6864 genRightShiftLiteral (left,right,result,ic,1);
6867 /* shift count is unknown then we have to form
6868 a loop get the loop count in B : Note: we take
6869 only the lower order byte since shifting
6870 more that 32 bits make no sense anyway, ( the
6871 largest size of an object can be only 32 bits ) */
6873 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6874 emitcode("inc","b");
6875 freeAsmop (right,NULL,ic,TRUE);
6876 aopOp(left,ic,FALSE);
6877 aopOp(result,ic,FALSE);
6879 /* now move the left to the result if they are not the
6881 if (!sameRegs(AOP(left),AOP(result)) &&
6882 AOP_SIZE(result) > 1) {
6884 size = AOP_SIZE(result);
6887 l = aopGet(AOP(left),offset,FALSE,TRUE);
6888 if (*l == '@' && IS_AOP_PREG(result)) {
6890 emitcode("mov","a,%s",l);
6891 aopPut(AOP(result),"a",offset);
6893 aopPut(AOP(result),l,offset);
6898 /* mov the highest order bit to OVR */
6899 tlbl = newiTempLabel(NULL);
6900 tlbl1= newiTempLabel(NULL);
6902 size = AOP_SIZE(result);
6904 emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
6905 emitcode("rlc","a");
6906 emitcode("mov","ov,c");
6907 /* if it is only one byte then */
6909 l = aopGet(AOP(left),0,FALSE,FALSE);
6911 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6912 emitcode("","%05d_DS_:",tlbl->key+100);
6913 emitcode("mov","c,ov");
6914 emitcode("rrc","a");
6915 emitcode("","%05d_DS_:",tlbl1->key+100);
6916 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6917 aopPut(AOP(result),"a",0);
6921 reAdjustPreg(AOP(result));
6922 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
6923 emitcode("","%05d_DS_:",tlbl->key+100);
6924 emitcode("mov","c,ov");
6926 l = aopGet(AOP(result),offset,FALSE,FALSE);
6928 emitcode("rrc","a");
6929 aopPut(AOP(result),"a",offset--);
6931 reAdjustPreg(AOP(result));
6932 emitcode("","%05d_DS_:",tlbl1->key+100);
6933 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
6936 freeAsmop(left,NULL,ic,TRUE);
6937 freeAsmop(result,NULL,ic,TRUE);
6940 /*-----------------------------------------------------------------*/
6941 /* genRightShift - generate code for right shifting */
6942 /*-----------------------------------------------------------------*/
6943 static void genRightShift (iCode *ic)
6945 operand *right, *left, *result;
6949 symbol *tlbl, *tlbl1 ;
6951 /* if signed then we do it the hard way preserve the
6952 sign bit moving it inwards */
6953 retype = getSpec(operandType(IC_RESULT(ic)));
6954 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
6956 if (!SPEC_USIGN(retype)) {
6957 genSignedRightShift (ic);
6961 /* signed & unsigned types are treated the same : i.e. the
6962 signed is NOT propagated inwards : quoting from the
6963 ANSI - standard : "for E1 >> E2, is equivalent to division
6964 by 2**E2 if unsigned or if it has a non-negative value,
6965 otherwise the result is implementation defined ", MY definition
6966 is that the sign does not get propagated */
6968 right = IC_RIGHT(ic);
6970 result = IC_RESULT(ic);
6972 aopOp(right,ic,FALSE);
6974 /* if the shift count is known then do it
6975 as efficiently as possible */
6976 if (AOP_TYPE(right) == AOP_LIT) {
6977 genRightShiftLiteral (left,right,result,ic, 0);
6981 /* shift count is unknown then we have to form
6982 a loop get the loop count in B : Note: we take
6983 only the lower order byte since shifting
6984 more that 32 bits make no sense anyway, ( the
6985 largest size of an object can be only 32 bits ) */
6987 emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
6988 emitcode("inc","b");
6989 freeAsmop (right,NULL,ic,TRUE);
6990 aopOp(left,ic,FALSE);
6991 aopOp(result,ic,FALSE);
6993 /* now move the left to the result if they are not the
6995 if (!sameRegs(AOP(left),AOP(result)) &&
6996 AOP_SIZE(result) > 1) {
6998 size = AOP_SIZE(result);
7001 l = aopGet(AOP(left),offset,FALSE,TRUE);
7002 if (*l == '@' && IS_AOP_PREG(result)) {
7004 emitcode("mov","a,%s",l);
7005 aopPut(AOP(result),"a",offset);
7007 aopPut(AOP(result),l,offset);
7012 tlbl = newiTempLabel(NULL);
7013 tlbl1= newiTempLabel(NULL);
7014 size = AOP_SIZE(result);
7017 /* if it is only one byte then */
7019 l = aopGet(AOP(left),0,FALSE,FALSE);
7021 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7022 emitcode("","%05d_DS_:",tlbl->key+100);
7024 emitcode("rrc","a");
7025 emitcode("","%05d_DS_:",tlbl1->key+100);
7026 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7027 aopPut(AOP(result),"a",0);
7031 reAdjustPreg(AOP(result));
7032 emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7033 emitcode("","%05d_DS_:",tlbl->key+100);
7036 l = aopGet(AOP(result),offset,FALSE,FALSE);
7038 emitcode("rrc","a");
7039 aopPut(AOP(result),"a",offset--);
7041 reAdjustPreg(AOP(result));
7043 emitcode("","%05d_DS_:",tlbl1->key+100);
7044 emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7047 freeAsmop(left,NULL,ic,TRUE);
7048 freeAsmop(result,NULL,ic,TRUE);
7051 /*-----------------------------------------------------------------*/
7052 /* genUnpackBits - generates code for unpacking bits */
7053 /*-----------------------------------------------------------------*/
7054 static void genUnpackBits (operand *result, char *rname, int ptype)
7061 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7062 etype = getSpec(operandType(result));
7064 /* read the first byte */
7069 emitcode("mov","a,@%s",rname);
7073 emitcode("movx","a,@%s",rname);
7077 emitcode("movx","a,@dptr");
7081 emitcode("clr","a");
7082 emitcode("movc","a","@a+dptr");
7086 emitcode("lcall","__gptrget");
7090 /* if we have bitdisplacement then it fits */
7091 /* into this byte completely or if length is */
7092 /* less than a byte */
7093 if ((shCnt = SPEC_BSTR(etype)) ||
7094 (SPEC_BLEN(etype) <= 8)) {
7096 /* shift right acc */
7099 emitcode("anl","a,#0x%02x",
7100 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7101 aopPut(AOP(result),"a",offset);
7105 /* bit field did not fit in a byte */
7106 rlen = SPEC_BLEN(etype) - 8;
7107 aopPut(AOP(result),"a",offset++);
7114 emitcode("inc","%s",rname);
7115 emitcode("mov","a,@%s",rname);
7119 emitcode("inc","%s",rname);
7120 emitcode("movx","a,@%s",rname);
7124 emitcode("inc","dptr");
7125 emitcode("movx","a,@dptr");
7129 emitcode("clr","a");
7130 emitcode("inc","dptr");
7131 emitcode("movc","a","@a+dptr");
7135 emitcode("inc","dptr");
7136 emitcode("lcall","__gptrget");
7141 /* if we are done */
7145 aopPut(AOP(result),"a",offset++);
7150 emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7151 aopPut(AOP(result),"a",offset);
7158 /*-----------------------------------------------------------------*/
7159 /* genDataPointerGet - generates code when ptr offset is known */
7160 /*-----------------------------------------------------------------*/
7161 static void genDataPointerGet (operand *left,
7167 int size , offset = 0;
7168 aopOp(result,ic,TRUE);
7170 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7172 /* get the string representation of the name */
7173 l = aopGet(AOP(left),0,FALSE,TRUE);
7174 size = AOP_SIZE(result);
7175 // tsd, was l+1 - the underline `_' prefix was being stripped
7178 sprintf(buffer,"(%s + %d)",l,offset);
7180 sprintf(buffer,"%s",l);
7181 aopPut(AOP(result),buffer,offset++);
7184 freeAsmop(left,NULL,ic,TRUE);
7185 freeAsmop(result,NULL,ic,TRUE);
7188 /*-----------------------------------------------------------------*/
7189 /* genNearPointerGet - emitcode for near pointer fetch */
7190 /*-----------------------------------------------------------------*/
7191 static void genNearPointerGet (operand *left,
7198 sym_link *rtype, *retype;
7199 sym_link *ltype = operandType(left);
7202 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7204 rtype = operandType(result);
7205 retype= getSpec(rtype);
7207 aopOp(left,ic,FALSE);
7209 /* if left is rematerialisable and
7210 result is not bit variable type and
7211 the left is pointer to data space i.e
7212 lower 128 bytes of space */
7213 if (AOP_TYPE(left) == AOP_IMMD &&
7214 !IS_BITVAR(retype) &&
7215 DCL_TYPE(ltype) == POINTER) {
7216 genDataPointerGet (left,result,ic);
7220 /* if the value is already in a pointer register
7221 then don't need anything more */
7222 if (!AOP_INPREG(AOP(left))) {
7223 /* otherwise get a free pointer register */
7225 preg = getFreePtr(ic,&aop,FALSE);
7226 emitcode("mov","%s,%s",
7228 aopGet(AOP(left),0,FALSE,TRUE));
7229 rname = preg->name ;
7231 rname = aopGet(AOP(left),0,FALSE,FALSE);
7233 freeAsmop(left,NULL,ic,TRUE);
7234 aopOp (result,ic,FALSE);
7236 /* if bitfield then unpack the bits */
7237 if (IS_BITVAR(retype))
7238 genUnpackBits (result,rname,POINTER);
7240 /* we have can just get the values */
7241 int size = AOP_SIZE(result);
7245 if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7247 emitcode("mov","a,@%s",rname);
7248 aopPut(AOP(result),"a",offset);
7250 sprintf(buffer,"@%s",rname);
7251 aopPut(AOP(result),buffer,offset);
7255 emitcode("inc","%s",rname);
7259 /* now some housekeeping stuff */
7261 /* we had to allocate for this iCode */
7262 freeAsmop(NULL,aop,ic,TRUE);
7264 /* we did not allocate which means left
7265 already in a pointer register, then
7266 if size > 0 && this could be used again
7267 we have to point it back to where it
7269 if (AOP_SIZE(result) > 1 &&
7270 !OP_SYMBOL(left)->remat &&
7271 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7273 int size = AOP_SIZE(result) - 1;
7275 emitcode("dec","%s",rname);
7280 freeAsmop(result,NULL,ic,TRUE);
7284 /*-----------------------------------------------------------------*/
7285 /* genPagedPointerGet - emitcode for paged pointer fetch */
7286 /*-----------------------------------------------------------------*/
7287 static void genPagedPointerGet (operand *left,
7294 sym_link *rtype, *retype;
7296 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7298 rtype = operandType(result);
7299 retype= getSpec(rtype);
7301 aopOp(left,ic,FALSE);
7303 /* if the value is already in a pointer register
7304 then don't need anything more */
7305 if (!AOP_INPREG(AOP(left))) {
7306 /* otherwise get a free pointer register */
7308 preg = getFreePtr(ic,&aop,FALSE);
7309 emitcode("mov","%s,%s",
7311 aopGet(AOP(left),0,FALSE,TRUE));
7312 rname = preg->name ;
7314 rname = aopGet(AOP(left),0,FALSE,FALSE);
7316 freeAsmop(left,NULL,ic,TRUE);
7317 aopOp (result,ic,FALSE);
7319 /* if bitfield then unpack the bits */
7320 if (IS_BITVAR(retype))
7321 genUnpackBits (result,rname,PPOINTER);
7323 /* we have can just get the values */
7324 int size = AOP_SIZE(result);
7329 emitcode("movx","a,@%s",rname);
7330 aopPut(AOP(result),"a",offset);
7335 emitcode("inc","%s",rname);
7339 /* now some housekeeping stuff */
7341 /* we had to allocate for this iCode */
7342 freeAsmop(NULL,aop,ic,TRUE);
7344 /* we did not allocate which means left
7345 already in a pointer register, then
7346 if size > 0 && this could be used again
7347 we have to point it back to where it
7349 if (AOP_SIZE(result) > 1 &&
7350 !OP_SYMBOL(left)->remat &&
7351 ( OP_SYMBOL(left)->liveTo > ic->seq ||
7353 int size = AOP_SIZE(result) - 1;
7355 emitcode("dec","%s",rname);
7360 freeAsmop(result,NULL,ic,TRUE);
7365 /*-----------------------------------------------------------------*/
7366 /* genFarPointerGet - gget value from far space */
7367 /*-----------------------------------------------------------------*/
7368 static void genFarPointerGet (operand *left,
7369 operand *result, iCode *ic)
7372 sym_link *retype = getSpec(operandType(result));
7374 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7376 aopOp(left,ic,FALSE);
7378 /* if the operand is already in dptr
7379 then we do nothing else we move the value to dptr */
7380 if (AOP_TYPE(left) != AOP_STR) {
7381 /* if this is remateriazable */
7382 if (AOP_TYPE(left) == AOP_IMMD)
7383 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7384 else { /* we need to get it byte by byte */
7385 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7386 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7387 if (options.model == MODEL_FLAT24)
7389 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7393 /* so dptr know contains the address */
7394 freeAsmop(left,NULL,ic,TRUE);
7395 aopOp(result,ic,FALSE);
7397 /* if bit then unpack */
7398 if (IS_BITVAR(retype))
7399 genUnpackBits(result,"dptr",FPOINTER);
7401 size = AOP_SIZE(result);
7405 emitcode("movx","a,@dptr");
7406 aopPut(AOP(result),"a",offset++);
7408 emitcode("inc","dptr");
7412 freeAsmop(result,NULL,ic,TRUE);
7415 /*-----------------------------------------------------------------*/
7416 /* emitcodePointerGet - gget value from code space */
7417 /*-----------------------------------------------------------------*/
7418 static void emitcodePointerGet (operand *left,
7419 operand *result, iCode *ic)
7422 sym_link *retype = getSpec(operandType(result));
7424 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7426 aopOp(left,ic,FALSE);
7428 /* if the operand is already in dptr
7429 then we do nothing else we move the value to dptr */
7430 if (AOP_TYPE(left) != AOP_STR) {
7431 /* if this is remateriazable */
7432 if (AOP_TYPE(left) == AOP_IMMD)
7433 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7434 else { /* we need to get it byte by byte */
7435 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7436 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7437 if (options.model == MODEL_FLAT24)
7439 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7443 /* so dptr know contains the address */
7444 freeAsmop(left,NULL,ic,TRUE);
7445 aopOp(result,ic,FALSE);
7447 /* if bit then unpack */
7448 if (IS_BITVAR(retype))
7449 genUnpackBits(result,"dptr",CPOINTER);
7451 size = AOP_SIZE(result);
7455 emitcode("clr","a");
7456 emitcode("movc","a,@a+dptr");
7457 aopPut(AOP(result),"a",offset++);
7459 emitcode("inc","dptr");
7463 freeAsmop(result,NULL,ic,TRUE);
7466 /*-----------------------------------------------------------------*/
7467 /* genGenPointerGet - gget value from generic pointer space */
7468 /*-----------------------------------------------------------------*/
7469 static void genGenPointerGet (operand *left,
7470 operand *result, iCode *ic)
7473 sym_link *retype = getSpec(operandType(result));
7475 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7476 aopOp(left,ic,FALSE);
7478 /* if the operand is already in dptr
7479 then we do nothing else we move the value to dptr */
7480 if (AOP_TYPE(left) != AOP_STR) {
7481 /* if this is remateriazable */
7482 if (AOP_TYPE(left) == AOP_IMMD) {
7483 emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7484 emitcode("mov","b,#%d",pointerCode(retype));
7486 else { /* we need to get it byte by byte */
7488 emitpcode(POC_MOVFW,popGet(AOP(left),0,FALSE,FALSE));
7489 emitpcode(POC_MOVWF,popCopy(&pc_fsr));
7490 emitcode("movf","%s,w",aopGet(AOP(left),0,FALSE,FALSE));
7491 emitcode("movwf","FSR");
7493 emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7494 emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7495 if (options.model == MODEL_FLAT24)
7497 emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7498 emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
7502 emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
7507 /* so dptr know contains the address */
7508 freeAsmop(left,NULL,ic,TRUE);
7509 aopOp(result,ic,FALSE);
7511 /* if bit then unpack */
7512 if (IS_BITVAR(retype))
7513 genUnpackBits(result,"dptr",GPOINTER);
7515 size = AOP_SIZE(result);
7519 emitpcode(POC_MOVFW,popCopy(&pc_fsr));
7520 emitpcode(POC_MOVWF,popGet(AOP(result),offset++,FALSE,FALSE));
7522 emitpcode(POC_INCF,popCopy(&pc_fsr));
7524 emitcode("movf","indf,w");
7525 emitcode("movwf","%s",
7526 aopGet(AOP(result),offset++,FALSE,FALSE));
7528 emitcode("incf","fsr,f");
7533 freeAsmop(result,NULL,ic,TRUE);
7536 /*-----------------------------------------------------------------*/
7537 /* genPointerGet - generate code for pointer get */
7538 /*-----------------------------------------------------------------*/
7539 static void genPointerGet (iCode *ic)
7541 operand *left, *result ;
7542 sym_link *type, *etype;
7545 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7548 result = IC_RESULT(ic) ;
7550 /* depending on the type of pointer we need to
7551 move it to the correct pointer register */
7552 type = operandType(left);
7553 etype = getSpec(type);
7554 /* if left is of type of pointer then it is simple */
7555 if (IS_PTR(type) && !IS_FUNC(type->next))
7556 p_type = DCL_TYPE(type);
7558 /* we have to go by the storage class */
7559 p_type = PTR_TYPE(SPEC_OCLS(etype));
7561 /* if (SPEC_OCLS(etype)->codesp ) { */
7562 /* p_type = CPOINTER ; */
7565 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
7566 /* p_type = FPOINTER ; */
7568 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
7569 /* p_type = PPOINTER; */
7571 /* if (SPEC_OCLS(etype) == idata ) */
7572 /* p_type = IPOINTER; */
7574 /* p_type = POINTER ; */
7577 /* now that we have the pointer type we assign
7578 the pointer values */
7583 genNearPointerGet (left,result,ic);
7587 genPagedPointerGet(left,result,ic);
7591 genFarPointerGet (left,result,ic);
7595 emitcodePointerGet (left,result,ic);
7599 genGenPointerGet (left,result,ic);
7605 /*-----------------------------------------------------------------*/
7606 /* genPackBits - generates code for packed bit storage */
7607 /*-----------------------------------------------------------------*/
7608 static void genPackBits (sym_link *etype ,
7610 char *rname, int p_type)
7618 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7619 blen = SPEC_BLEN(etype);
7620 bstr = SPEC_BSTR(etype);
7622 l = aopGet(AOP(right),offset++,FALSE,FALSE);
7625 /* if the bit lenth is less than or */
7626 /* it exactly fits a byte then */
7627 if (SPEC_BLEN(etype) <= 8 ) {
7628 shCount = SPEC_BSTR(etype) ;
7630 /* shift left acc */
7633 if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
7638 emitcode ("mov","b,a");
7639 emitcode("mov","a,@%s",rname);
7643 emitcode ("mov","b,a");
7644 emitcode("movx","a,@dptr");
7648 emitcode ("push","b");
7649 emitcode ("push","acc");
7650 emitcode ("lcall","__gptrget");
7651 emitcode ("pop","b");
7655 emitcode ("anl","a,#0x%02x",(unsigned char)
7656 ((unsigned char)(0xFF << (blen+bstr)) |
7657 (unsigned char)(0xFF >> (8-bstr)) ) );
7658 emitcode ("orl","a,b");
7659 if (p_type == GPOINTER)
7660 emitcode("pop","b");
7666 emitcode("mov","@%s,a",rname);
7670 emitcode("movx","@dptr,a");
7674 DEBUGemitcode(";lcall","__gptrput");
7679 if ( SPEC_BLEN(etype) <= 8 )
7682 emitcode("inc","%s",rname);
7683 rLen = SPEC_BLEN(etype) ;
7685 /* now generate for lengths greater than one byte */
7688 l = aopGet(AOP(right),offset++,FALSE,TRUE);
7698 emitcode("mov","@%s,a",rname);
7700 emitcode("mov","@%s,%s",rname,l);
7705 emitcode("movx","@dptr,a");
7710 DEBUGemitcode(";lcall","__gptrput");
7713 emitcode ("inc","%s",rname);
7718 /* last last was not complete */
7720 /* save the byte & read byte */
7723 emitcode ("mov","b,a");
7724 emitcode("mov","a,@%s",rname);
7728 emitcode ("mov","b,a");
7729 emitcode("movx","a,@dptr");
7733 emitcode ("push","b");
7734 emitcode ("push","acc");
7735 emitcode ("lcall","__gptrget");
7736 emitcode ("pop","b");
7740 emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
7741 emitcode ("orl","a,b");
7744 if (p_type == GPOINTER)
7745 emitcode("pop","b");
7750 emitcode("mov","@%s,a",rname);
7754 emitcode("movx","@dptr,a");
7758 DEBUGemitcode(";lcall","__gptrput");
7762 /*-----------------------------------------------------------------*/
7763 /* genDataPointerSet - remat pointer to data space */
7764 /*-----------------------------------------------------------------*/
7765 static void genDataPointerSet(operand *right,
7769 int size, offset = 0 ;
7770 char *l, buffer[256];
7772 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7773 aopOp(right,ic,FALSE);
7775 l = aopGet(AOP(result),0,FALSE,TRUE);
7776 size = AOP_SIZE(right);
7777 // tsd, was l+1 - the underline `_' prefix was being stripped
7780 sprintf(buffer,"(%s + %d)",l,offset);
7782 sprintf(buffer,"%s",l);
7784 if (AOP_TYPE(right) == AOP_LIT) {
7785 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7786 lit = lit >> (8*offset);
7788 emitcode("movlw","%s",lit);
7789 emitcode("movwf","%s",buffer);
7791 emitcode("clrf","%s",buffer);
7793 emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
7794 emitcode("movwf","%s",buffer);
7800 freeAsmop(right,NULL,ic,TRUE);
7801 freeAsmop(result,NULL,ic,TRUE);
7804 /*-----------------------------------------------------------------*/
7805 /* genNearPointerSet - emitcode for near pointer put */
7806 /*-----------------------------------------------------------------*/
7807 static void genNearPointerSet (operand *right,
7814 sym_link *ptype = operandType(result);
7817 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7818 retype= getSpec(operandType(right));
7820 aopOp(result,ic,FALSE);
7822 /* if the result is rematerializable &
7823 in data space & not a bit variable */
7824 if (AOP_TYPE(result) == AOP_IMMD &&
7825 DCL_TYPE(ptype) == POINTER &&
7826 !IS_BITVAR(retype)) {
7827 genDataPointerSet (right,result,ic);
7831 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7833 /* if the value is already in a pointer register
7834 then don't need anything more */
7835 if (!AOP_INPREG(AOP(result))) {
7836 /* otherwise get a free pointer register */
7837 //aop = newAsmop(0);
7838 //preg = getFreePtr(ic,&aop,FALSE);
7839 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7840 //emitcode("mov","%s,%s",
7842 // aopGet(AOP(result),0,FALSE,TRUE));
7843 //rname = preg->name ;
7844 emitcode("movwf","fsr");
7846 // rname = aopGet(AOP(result),0,FALSE,FALSE);
7848 freeAsmop(result,NULL,ic,TRUE);
7849 aopOp (right,ic,FALSE);
7850 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7852 /* if bitfield then unpack the bits */
7853 if (IS_BITVAR(retype)) {
7854 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
7855 "The programmer is obviously confused");
7856 //genPackBits (retype,right,rname,POINTER);
7860 /* we have can just get the values */
7861 int size = AOP_SIZE(right);
7864 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7866 l = aopGet(AOP(right),offset,FALSE,TRUE);
7869 //emitcode("mov","@%s,a",rname);
7870 emitcode("movf","indf,w ;1");
7873 if (AOP_TYPE(right) == AOP_LIT) {
7874 unsigned int lit = floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
7876 emitcode("movlw","%s",l);
7877 emitcode("movwf","indf ;2");
7879 emitcode("clrf","indf");
7881 emitcode("movf","%s,w",l);
7882 emitcode("movwf","indf ;2");
7884 //emitcode("mov","@%s,%s",rname,l);
7887 emitcode("incf","fsr,f ;3");
7888 //emitcode("inc","%s",rname);
7893 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7894 /* now some housekeeping stuff */
7896 /* we had to allocate for this iCode */
7897 freeAsmop(NULL,aop,ic,TRUE);
7899 /* we did not allocate which means left
7900 already in a pointer register, then
7901 if size > 0 && this could be used again
7902 we have to point it back to where it
7904 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7905 if (AOP_SIZE(right) > 1 &&
7906 !OP_SYMBOL(result)->remat &&
7907 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7909 int size = AOP_SIZE(right) - 1;
7911 emitcode("decf","fsr,f");
7912 //emitcode("dec","%s",rname);
7916 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7918 freeAsmop(right,NULL,ic,TRUE);
7923 /*-----------------------------------------------------------------*/
7924 /* genPagedPointerSet - emitcode for Paged pointer put */
7925 /*-----------------------------------------------------------------*/
7926 static void genPagedPointerSet (operand *right,
7935 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
7937 retype= getSpec(operandType(right));
7939 aopOp(result,ic,FALSE);
7941 /* if the value is already in a pointer register
7942 then don't need anything more */
7943 if (!AOP_INPREG(AOP(result))) {
7944 /* otherwise get a free pointer register */
7946 preg = getFreePtr(ic,&aop,FALSE);
7947 emitcode("mov","%s,%s",
7949 aopGet(AOP(result),0,FALSE,TRUE));
7950 rname = preg->name ;
7952 rname = aopGet(AOP(result),0,FALSE,FALSE);
7954 freeAsmop(result,NULL,ic,TRUE);
7955 aopOp (right,ic,FALSE);
7957 /* if bitfield then unpack the bits */
7958 if (IS_BITVAR(retype))
7959 genPackBits (retype,right,rname,PPOINTER);
7961 /* we have can just get the values */
7962 int size = AOP_SIZE(right);
7966 l = aopGet(AOP(right),offset,FALSE,TRUE);
7969 emitcode("movx","@%s,a",rname);
7972 emitcode("inc","%s",rname);
7978 /* now some housekeeping stuff */
7980 /* we had to allocate for this iCode */
7981 freeAsmop(NULL,aop,ic,TRUE);
7983 /* we did not allocate which means left
7984 already in a pointer register, then
7985 if size > 0 && this could be used again
7986 we have to point it back to where it
7988 if (AOP_SIZE(right) > 1 &&
7989 !OP_SYMBOL(result)->remat &&
7990 ( OP_SYMBOL(result)->liveTo > ic->seq ||
7992 int size = AOP_SIZE(right) - 1;
7994 emitcode("dec","%s",rname);
7999 freeAsmop(right,NULL,ic,TRUE);
8004 /*-----------------------------------------------------------------*/
8005 /* genFarPointerSet - set value from far space */
8006 /*-----------------------------------------------------------------*/
8007 static void genFarPointerSet (operand *right,
8008 operand *result, iCode *ic)
8011 sym_link *retype = getSpec(operandType(right));
8013 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8014 aopOp(result,ic,FALSE);
8016 /* if the operand is already in dptr
8017 then we do nothing else we move the value to dptr */
8018 if (AOP_TYPE(result) != AOP_STR) {
8019 /* if this is remateriazable */
8020 if (AOP_TYPE(result) == AOP_IMMD)
8021 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8022 else { /* we need to get it byte by byte */
8023 emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8024 emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8025 if (options.model == MODEL_FLAT24)
8027 emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8031 /* so dptr know contains the address */
8032 freeAsmop(result,NULL,ic,TRUE);
8033 aopOp(right,ic,FALSE);
8035 /* if bit then unpack */
8036 if (IS_BITVAR(retype))
8037 genPackBits(retype,right,"dptr",FPOINTER);
8039 size = AOP_SIZE(right);
8043 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8045 emitcode("movx","@dptr,a");
8047 emitcode("inc","dptr");
8051 freeAsmop(right,NULL,ic,TRUE);
8054 /*-----------------------------------------------------------------*/
8055 /* genGenPointerSet - set value from generic pointer space */
8056 /*-----------------------------------------------------------------*/
8057 static void genGenPointerSet (operand *right,
8058 operand *result, iCode *ic)
8061 sym_link *retype = getSpec(operandType(right));
8063 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8065 aopOp(result,ic,FALSE);
8067 /* if the operand is already in dptr
8068 then we do nothing else we move the value to dptr */
8069 if (AOP_TYPE(result) != AOP_STR) {
8070 /* if this is remateriazable */
8071 if (AOP_TYPE(result) == AOP_IMMD) {
8072 emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8073 emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8075 else { /* we need to get it byte by byte */
8076 char *l = aopGet(AOP(result),0,FALSE,FALSE);
8079 emitpcode(POC_MOVLW ,popGet(AOP(result),0,FALSE,FALSE));
8080 emitpcode(POC_MOVWF,popCopy(&pc_indf));
8083 emitcode("movlw","%s",aopGet(AOP(result),0,FALSE,FALSE));
8085 emitcode("movwf","INDF");
8088 /* so dptr know contains the address */
8089 freeAsmop(result,NULL,ic,TRUE);
8090 aopOp(right,ic,FALSE);
8092 /* if bit then unpack */
8093 if (IS_BITVAR(retype))
8094 genPackBits(retype,right,"dptr",GPOINTER);
8096 size = AOP_SIZE(right);
8100 char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8102 emitcode("incf","fsr,f");
8103 emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8104 emitcode("movwf","indf");
8106 //DEBUGemitcode(";lcall","__gptrput");
8108 // emitcode("inc","dptr");
8112 freeAsmop(right,NULL,ic,TRUE);
8115 /*-----------------------------------------------------------------*/
8116 /* genPointerSet - stores the value into a pointer location */
8117 /*-----------------------------------------------------------------*/
8118 static void genPointerSet (iCode *ic)
8120 operand *right, *result ;
8121 sym_link *type, *etype;
8124 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8126 right = IC_RIGHT(ic);
8127 result = IC_RESULT(ic) ;
8129 /* depending on the type of pointer we need to
8130 move it to the correct pointer register */
8131 type = operandType(result);
8132 etype = getSpec(type);
8133 /* if left is of type of pointer then it is simple */
8134 if (IS_PTR(type) && !IS_FUNC(type->next)) {
8135 p_type = DCL_TYPE(type);
8138 /* we have to go by the storage class */
8139 p_type = PTR_TYPE(SPEC_OCLS(etype));
8141 /* if (SPEC_OCLS(etype)->codesp ) { */
8142 /* p_type = CPOINTER ; */
8145 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8146 /* p_type = FPOINTER ; */
8148 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8149 /* p_type = PPOINTER ; */
8151 /* if (SPEC_OCLS(etype) == idata ) */
8152 /* p_type = IPOINTER ; */
8154 /* p_type = POINTER ; */
8157 /* now that we have the pointer type we assign
8158 the pointer values */
8163 genNearPointerSet (right,result,ic);
8167 genPagedPointerSet (right,result,ic);
8171 genFarPointerSet (right,result,ic);
8175 genGenPointerSet (right,result,ic);
8181 /*-----------------------------------------------------------------*/
8182 /* genIfx - generate code for Ifx statement */
8183 /*-----------------------------------------------------------------*/
8184 static void genIfx (iCode *ic, iCode *popIc)
8186 operand *cond = IC_COND(ic);
8189 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8190 aopOp(cond,ic,FALSE);
8192 /* get the value into acc */
8193 if (AOP_TYPE(cond) != AOP_CRY)
8197 /* the result is now in the accumulator */
8198 freeAsmop(cond,NULL,ic,TRUE);
8200 /* if there was something to be popped then do it */
8204 /* if the condition is a bit variable */
8205 if (isbit && IS_ITEMP(cond) &&
8207 genIfxJump(ic,SPIL_LOC(cond)->rname);
8208 DEBUGemitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8212 if (isbit && !IS_ITEMP(cond))
8213 DEBUGemitcode ("; isbit OP_SYM","%s",OP_SYMBOL(cond)->rname);
8215 DEBUGemitcode ("; isbit","a");
8218 if (isbit && !IS_ITEMP(cond))
8219 genIfxJump(ic,OP_SYMBOL(cond)->rname);
8226 /*-----------------------------------------------------------------*/
8227 /* genAddrOf - generates code for address of */
8228 /*-----------------------------------------------------------------*/
8229 static void genAddrOf (iCode *ic)
8231 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8234 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8236 aopOp(IC_RESULT(ic),ic,FALSE);
8238 /* if the operand is on the stack then we
8239 need to get the stack offset of this
8242 /* if it has an offset then we need to compute
8245 emitcode("mov","a,_bp");
8246 emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
8247 aopPut(AOP(IC_RESULT(ic)),"a",0);
8249 /* we can just move _bp */
8250 aopPut(AOP(IC_RESULT(ic)),"_bp",0);
8252 /* fill the result with zero */
8253 size = AOP_SIZE(IC_RESULT(ic)) - 1;
8256 if (options.stack10bit && size < (FPTRSIZE - 1))
8259 "*** warning: pointer to stack var truncated.\n");
8266 if (options.stack10bit && offset == 2)
8268 aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
8272 aopPut(AOP(IC_RESULT(ic)),zero,offset++);
8279 /* object not on stack then we need the name */
8280 size = AOP_SIZE(IC_RESULT(ic));
8284 char s[SDCC_NAME_MAX];
8286 sprintf(s,"#(%s >> %d)",
8290 sprintf(s,"#%s",sym->rname);
8291 aopPut(AOP(IC_RESULT(ic)),s,offset++);
8295 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8300 /*-----------------------------------------------------------------*/
8301 /* genFarFarAssign - assignment when both are in far space */
8302 /*-----------------------------------------------------------------*/
8303 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8305 int size = AOP_SIZE(right);
8308 /* first push the right side on to the stack */
8310 l = aopGet(AOP(right),offset++,FALSE,FALSE);
8312 emitcode ("push","acc");
8315 freeAsmop(right,NULL,ic,FALSE);
8316 /* now assign DPTR to result */
8317 aopOp(result,ic,FALSE);
8318 size = AOP_SIZE(result);
8320 emitcode ("pop","acc");
8321 aopPut(AOP(result),"a",--offset);
8323 freeAsmop(result,NULL,ic,FALSE);
8328 /*-----------------------------------------------------------------*/
8329 /* genAssign - generate code for assignment */
8330 /*-----------------------------------------------------------------*/
8331 static void genAssign (iCode *ic)
8333 operand *result, *right;
8335 unsigned long lit = 0L;
8337 result = IC_RESULT(ic);
8338 right = IC_RIGHT(ic) ;
8340 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8342 /* if they are the same */
8343 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8346 aopOp(right,ic,FALSE);
8347 aopOp(result,ic,TRUE);
8349 /* if they are the same registers */
8350 if (sameRegs(AOP(right),AOP(result)))
8353 /* if the result is a bit */
8354 if (AOP_TYPE(result) == AOP_CRY) {
8356 /* if the right size is a literal then
8357 we know what the value is */
8358 if (AOP_TYPE(right) == AOP_LIT) {
8360 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8361 popGet(AOP(result),0,FALSE,FALSE));
8363 if (((int) operandLitValue(right)))
8364 emitcode("bsf","(%s >> 3),(%s & 7)",
8365 AOP(result)->aopu.aop_dir,
8366 AOP(result)->aopu.aop_dir);
8368 emitcode("bcf","(%s >> 3),(%s & 7)",
8369 AOP(result)->aopu.aop_dir,
8370 AOP(result)->aopu.aop_dir);
8374 /* the right is also a bit variable */
8375 if (AOP_TYPE(right) == AOP_CRY) {
8376 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
8377 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8378 emitpcode(POC_BCF, popGet(AOP(result),0,FALSE,FALSE));
8380 emitcode("bcf","(%s >> 3),(%s & 7)",
8381 AOP(result)->aopu.aop_dir,
8382 AOP(result)->aopu.aop_dir);
8383 emitcode("btfsc","(%s >> 3),(%s & 7)",
8384 AOP(right)->aopu.aop_dir,
8385 AOP(right)->aopu.aop_dir);
8386 emitcode("bsf","(%s >> 3),(%s & 7)",
8387 AOP(result)->aopu.aop_dir,
8388 AOP(result)->aopu.aop_dir);
8394 aopPut(AOP(result),"a",0);
8398 /* bit variables done */
8400 size = AOP_SIZE(result);
8402 if(AOP_TYPE(right) == AOP_LIT)
8403 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8404 if((AOP_TYPE(result) != AOP_REG) &&
8405 (AOP_TYPE(right) == AOP_LIT) &&
8406 !IS_FLOAT(operandType(right)) &&
8410 if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0) {
8411 //emitcode("clrf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8412 emitpcode(POC_CLRF,popGet(AOP(result),size,FALSE,FALSE));
8414 emitpcode(POC_MOVLW,popGet(AOP(right),size,FALSE,FALSE));
8415 emitpcode(POC_MOVWF,popGet(AOP(result),size,FALSE,FALSE));
8416 //emitcode("movlw","%s", aopGet(AOP(right),size,FALSE,FALSE));
8417 //emitcode("movwf","%s", aopGet(AOP(result),size,FALSE,FALSE));
8422 if(AOP_TYPE(right) == AOP_LIT)
8423 emitpcode(POC_MOVLW, popGet(AOP(right),offset,FALSE,FALSE));
8424 //emitcode("movlw","%s", aopGet(AOP(right),offset,FALSE,FALSE));
8426 emitpcode(POC_MOVFW, popGet(AOP(right),offset,FALSE,FALSE));
8427 //emitcode("movf","%s,w", aopGet(AOP(right),offset,FALSE,FALSE));
8429 emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
8430 //emitcode("movwf","%s", aopGet(AOP(result),offset,FALSE,FALSE));
8436 freeAsmop (right,NULL,ic,FALSE);
8437 freeAsmop (result,NULL,ic,TRUE);
8440 /*-----------------------------------------------------------------*/
8441 /* genJumpTab - genrates code for jump table */
8442 /*-----------------------------------------------------------------*/
8443 static void genJumpTab (iCode *ic)
8448 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8450 aopOp(IC_JTCOND(ic),ic,FALSE);
8451 /* get the condition into accumulator */
8452 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8454 /* multiply by three */
8455 emitcode("add","a,acc");
8456 emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8457 freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8459 jtab = newiTempLabel(NULL);
8460 emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8461 emitcode("jmp","@a+dptr");
8462 emitcode("","%05d_DS_:",jtab->key+100);
8463 /* now generate the jump labels */
8464 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8465 jtab = setNextItem(IC_JTLABELS(ic)))
8466 emitcode("ljmp","%05d_DS_",jtab->key+100);
8470 /*-----------------------------------------------------------------*/
8471 /* genMixedOperation - gen code for operators between mixed types */
8472 /*-----------------------------------------------------------------*/
8474 TSD - Written for the PIC port - but this unfortunately is buggy.
8475 This routine is good in that it is able to efficiently promote
8476 types to different (larger) sizes. Unfortunately, the temporary
8477 variables that are optimized out by this routine are sometimes
8478 used in other places. So until I know how to really parse the
8479 iCode tree, I'm going to not be using this routine :(.
8481 static int genMixedOperation (iCode *ic)
8484 operand *result = IC_RESULT(ic);
8485 sym_link *ctype = operandType(IC_LEFT(ic));
8486 operand *right = IC_RIGHT(ic);
8492 operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8494 emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8500 nextright = IC_RIGHT(nextic);
8501 nextleft = IC_LEFT(nextic);
8502 nextresult = IC_RESULT(nextic);
8504 aopOp(right,ic,FALSE);
8505 aopOp(result,ic,FALSE);
8506 aopOp(nextright, nextic, FALSE);
8507 aopOp(nextleft, nextic, FALSE);
8508 aopOp(nextresult, nextic, FALSE);
8510 if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8516 emitcode(";remove right +","");
8518 } else if (sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
8524 emitcode(";remove left +","");
8528 big = AOP_SIZE(nextleft);
8529 small = AOP_SIZE(nextright);
8531 switch(nextic->op) {
8534 emitcode(";optimize a +","");
8535 /* if unsigned or not an integral type */
8536 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
8537 emitcode(";add a bit to something","");
8540 emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
8542 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
8543 emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
8544 emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
8546 emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
8554 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8555 emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8556 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8559 emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8561 emitcode("btfsc","(%s >> 3), (%s & 7)",
8562 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
8563 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
8564 emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8565 emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
8568 emitcode("rlf","known_zero,w");
8575 if (!sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
8576 emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
8577 emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8579 emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
8589 freeAsmop(right,NULL,ic,TRUE);
8590 freeAsmop(result,NULL,ic,TRUE);
8591 freeAsmop(nextright,NULL,ic,TRUE);
8592 freeAsmop(nextleft,NULL,ic,TRUE);
8594 nextic->generated = 1;
8601 /*-----------------------------------------------------------------*/
8602 /* genCast - gen code for casting */
8603 /*-----------------------------------------------------------------*/
8604 static void genCast (iCode *ic)
8606 operand *result = IC_RESULT(ic);
8607 sym_link *ctype = operandType(IC_LEFT(ic));
8608 operand *right = IC_RIGHT(ic);
8611 DEBUGemitcode("; ***","%s %d",__FUNCTION__,__LINE__);
8612 /* if they are equivalent then do nothing */
8613 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
8616 aopOp(right,ic,FALSE) ;
8617 aopOp(result,ic,FALSE);
8619 /* if the result is a bit */
8620 if (AOP_TYPE(result) == AOP_CRY) {
8621 /* if the right size is a literal then
8622 we know what the value is */
8623 if (AOP_TYPE(right) == AOP_LIT) {
8625 emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8626 popGet(AOP(result),0,FALSE,FALSE));
8628 if (((int) operandLitValue(right)))
8629 emitcode("bsf","(%s >> 3), (%s & 7)",
8630 AOP(result)->aopu.aop_dir,
8631 AOP(result)->aopu.aop_dir);
8633 emitcode("bcf","(%s >> 3), (%s & 7)",
8634 AOP(result)->aopu.aop_dir,
8635 AOP(result)->aopu.aop_dir);
8640 /* the right is also a bit variable */
8641 if (AOP_TYPE(right) == AOP_CRY) {
8644 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8646 emitcode("clrc","");
8647 emitcode("btfsc","(%s >> 3), (%s & 7)",
8648 AOP(right)->aopu.aop_dir,
8649 AOP(right)->aopu.aop_dir);
8650 aopPut(AOP(result),"c",0);
8656 aopPut(AOP(result),"a",0);
8660 /* if they are the same size : or less */
8661 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
8663 /* if they are in the same place */
8664 if (sameRegs(AOP(right),AOP(result)))
8667 /* if they in different places then copy */
8668 size = AOP_SIZE(result);
8672 aopGet(AOP(right),offset,FALSE,FALSE),
8680 /* if the result is of type pointer */
8681 if (IS_PTR(ctype)) {
8684 sym_link *type = operandType(right);
8685 sym_link *etype = getSpec(type);
8687 /* pointer to generic pointer */
8688 if (IS_GENPTR(ctype)) {
8692 p_type = DCL_TYPE(type);
8694 /* we have to go by the storage class */
8695 p_type = PTR_TYPE(SPEC_OCLS(etype));
8697 /* if (SPEC_OCLS(etype)->codesp ) */
8698 /* p_type = CPOINTER ; */
8700 /* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8701 /* p_type = FPOINTER ; */
8703 /* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8704 /* p_type = PPOINTER; */
8706 /* if (SPEC_OCLS(etype) == idata ) */
8707 /* p_type = IPOINTER ; */
8709 /* p_type = POINTER ; */
8712 /* the first two bytes are known */
8713 size = GPTRSIZE - 1;
8717 aopGet(AOP(right),offset,FALSE,FALSE),
8721 /* the last byte depending on type */
8738 /* this should never happen */
8739 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8740 "got unknown pointer type");
8743 aopPut(AOP(result),l, GPTRSIZE - 1);
8747 /* just copy the pointers */
8748 size = AOP_SIZE(result);
8752 aopGet(AOP(right),offset,FALSE,FALSE),
8760 if (AOP_TYPE(right) == AOP_CRY) {
8762 size = AOP_SIZE(right);
8764 emitpcode(POC_CLRF, popGet(AOP(result),0,FALSE,FALSE));
8765 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8766 emitpcode(POC_INCF, popGet(AOP(result),0,FALSE,FALSE));
8768 emitcode("clrf","%s ; %d", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8769 emitcode("btfsc","(%s >> 3), (%s & 7)",
8770 AOP(right)->aopu.aop_dir,
8771 AOP(right)->aopu.aop_dir);
8772 emitcode("incf","%s,f", aopGet(AOP(result),0,FALSE,FALSE),__LINE__);
8774 emitcode("clrf","%s;%d", aopGet(AOP(result),offset,FALSE,FALSE),__LINE__);
8775 emitpcode(POC_CLRF, popGet(AOP(result),offset++,FALSE,FALSE));
8780 /* so we now know that the size of destination is greater
8781 than the size of the source.
8782 Now, if the next iCode is an operator then we might be
8783 able to optimize the operation without performing a cast.
8785 if(genMixedOperation(ic))
8789 /* we move to result for the size of source */
8790 size = AOP_SIZE(right);
8793 emitcode(";","%d",__LINE__);
8795 aopGet(AOP(right),offset,FALSE,FALSE),
8800 /* now depending on the sign of the destination */
8801 size = AOP_SIZE(result) - AOP_SIZE(right);
8802 /* if unsigned or not an integral type */
8803 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
8805 emitpcode(POC_CLRF, popGet(AOP(result),offset++,FALSE,FALSE));
8806 emitcode("clrf","%s ;%d",aopGet(AOP(result),offset++,FALSE,FALSE),__LINE__);
8809 /* we need to extend the sign :{ */
8810 //char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,FALSE,FALSE);
8813 emitpcode(POC_CLRW, NULL);
8814 emitpcode(POC_BTFSC, popGet(AOP(right),0,FALSE,FALSE));
8815 emitpcode(POC_MOVLW, popGetLit(0xff));
8817 emitcode("clrw","");
8818 emitcode("btfsc","(%s >> 3), (%s & 7)",
8819 AOP(right)->aopu.aop_dir,
8820 AOP(right)->aopu.aop_dir);
8821 emitcode("movlw","0xff");
8823 emitpcode(POC_MOVWF, popGet(AOP(result),offset++,FALSE,FALSE));
8824 emitcode("movwf","%s",aopGet(AOP(result),offset++,FALSE,FALSE));
8825 // aopPut(AOP(result),"a",offset++);
8830 /* we are done hurray !!!! */
8833 freeAsmop(right,NULL,ic,TRUE);
8834 freeAsmop(result,NULL,ic,TRUE);
8838 /*-----------------------------------------------------------------*/
8839 /* genDjnz - generate decrement & jump if not zero instrucion */
8840 /*-----------------------------------------------------------------*/
8841 static int genDjnz (iCode *ic, iCode *ifx)
8844 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8849 /* if the if condition has a false label
8850 then we cannot save */
8854 /* if the minus is not of the form
8856 if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
8857 !IS_OP_LITERAL(IC_RIGHT(ic)))
8860 if (operandLitValue(IC_RIGHT(ic)) != 1)
8863 /* if the size of this greater than one then no
8865 if (getSize(operandType(IC_RESULT(ic))) > 1)
8868 /* otherwise we can save BIG */
8869 lbl = newiTempLabel(NULL);
8870 lbl1= newiTempLabel(NULL);
8872 aopOp(IC_RESULT(ic),ic,FALSE);
8874 if (IS_AOP_PREG(IC_RESULT(ic))) {
8875 emitcode("dec","%s",
8876 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8877 emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8878 emitcode("jnz","%05d_DS_",lbl->key+100);
8882 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8883 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
8885 emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
8886 emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
8889 /* emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
8890 /* emitcode ("","%05d_DS_:",lbl->key+100); */
8891 /* emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
8892 /* emitcode ("","%05d_DS_:",lbl1->key+100); */
8895 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8900 /*-----------------------------------------------------------------*/
8901 /* genReceive - generate code for a receive iCode */
8902 /*-----------------------------------------------------------------*/
8903 static void genReceive (iCode *ic)
8905 DEBUGemitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
8907 if (isOperandInFarSpace(IC_RESULT(ic)) &&
8908 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
8909 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
8911 int size = getSize(operandType(IC_RESULT(ic)));
8912 int offset = fReturnSizePic - size;
8914 emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
8915 fReturn[fReturnSizePic - offset - 1] : "acc"));
8918 aopOp(IC_RESULT(ic),ic,FALSE);
8919 size = AOP_SIZE(IC_RESULT(ic));
8922 emitcode ("pop","acc");
8923 aopPut (AOP(IC_RESULT(ic)),"a",offset++);
8928 aopOp(IC_RESULT(ic),ic,FALSE);
8930 assignResultValue(IC_RESULT(ic));
8933 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8936 /*-----------------------------------------------------------------*/
8937 /* genpic14Code - generate code for pic14 based controllers */
8938 /*-----------------------------------------------------------------*/
8940 * At this point, ralloc.c has gone through the iCode and attempted
8941 * to optimize in a way suitable for a PIC. Now we've got to generate
8942 * PIC instructions that correspond to the iCode.
8944 * Once the instructions are generated, we'll pass through both the
8945 * peep hole optimizer and the pCode optimizer.
8946 *-----------------------------------------------------------------*/
8948 void genpic14Code (iCode *lic)
8953 lineHead = lineCurr = NULL;
8955 pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
8958 /* if debug information required */
8959 /* if (options.debug && currFunc) { */
8961 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
8963 if (IS_STATIC(currFunc->etype)) {
8964 emitcode("",";F%s$%s$0$0 %d",moduleName,currFunc->name,__LINE__);
8965 //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
8967 emitcode("",";G$%s$0$0 %d",currFunc->name,__LINE__);
8968 //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
8974 for (ic = lic ; ic ; ic = ic->next ) {
8976 DEBUGemitcode(";ic","");
8977 if ( cln != ic->lineno ) {
8978 if ( options.debug ) {
8980 emitcode("",";C$%s$%d$%d$%d ==.",
8981 FileBaseName(ic->filename),ic->lineno,
8982 ic->level,ic->block);
8985 emitcode(";","%s %d",FileBaseName(ic->filename),ic->lineno);
8988 /* if the result is marked as
8989 spilt and rematerializable or code for
8990 this has already been generated then
8992 if (resultRemat(ic) || ic->generated )
8995 /* depending on the operation */
9014 /* IPOP happens only when trying to restore a
9015 spilt live range, if there is an ifx statement
9016 following this pop then the if statement might
9017 be using some of the registers being popped which
9018 would destory the contents of the register so
9019 we need to check for this condition and handle it */
9021 ic->next->op == IFX &&
9022 regsInCommon(IC_LEFT(ic),IC_COND(ic->next)))
9023 genIfx (ic->next,ic);
9041 genEndFunction (ic);
9061 if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9078 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
9082 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9089 /* note these two are xlated by algebraic equivalence
9090 during parsing SDCC.y */
9091 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9092 "got '>=' or '<=' shouldn't have come here");
9096 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9108 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9112 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9116 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9143 case GET_VALUE_AT_ADDRESS:
9148 if (POINTER_SET(ic))
9175 addSet(&_G.sendSet,ic);
9180 /* piCode(ic,stdout); */
9186 /* now we are ready to call the
9187 peep hole optimizer */
9188 if (!options.nopeep) {
9189 printf("peep hole optimizing\n");
9190 peepHole (&lineHead);
9192 /* now do the actual printing */
9193 printLine (lineHead,codeOutFile);
9195 printf("printing pBlock\n\n");
9196 printpBlock(stdout,pb);