X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic16%2Fgen.c;h=aa811c3e1cc039aa21da410bf4178ab86e0f4ddc;hb=4fa52c899d3553b51d56db35d035f17b7e22e66b;hp=b69ba63d7b2364a05f53cb4270f980607b81e226;hpb=b6770819b6ac8c1b5669d4368a935f7aff96df27;p=fw%2Fsdcc diff --git a/src/pic16/gen.c b/src/pic16/gen.c index b69ba63d..aa811c3e 100644 --- a/src/pic16/gen.c +++ b/src/pic16/gen.c @@ -1,4 +1,4 @@ -/*------------------------------------------------------------------------- + /*------------------------------------------------------------------------- gen.c - source file for code generation for pic16 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) @@ -6,7 +6,8 @@ Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a) PIC port - Scott Dattalo scott@dattalo.com (2000) PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002) - - Vangelis Rokas vrokas@otenet.gr (2003,2004) + - Vangelis Rokas vrokas@otenet.gr (2003,2004,2005) + Bug Fixes - Raphael Neider (2004,2005) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -47,6 +48,32 @@ #include "device.h" #include "main.h" +/* Set the following to 1 to enable the slower/bigger + * but more robust generic shifting routine (which also + * operates correctly with negative shift values). */ +#define USE_GENERIC_SIGNED_SHIFT 1 + +/* Set the following to 1 to enable the new + * stripped down genCmp version. + * This version should be easier to understand, + * more reliable and (sigh) slighly slower. */ +#define USE_SIMPLE_GENCMP 1 + +/* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */ +#define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x)) +#define PIC_IS_FARPTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x)) +#define PIC_IS_TAGGED(x) (IS_GENPTR(x) || IS_CODEPTR(x)) +#define IS_DIRECT(op) ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR)) + +/* If you change these, you also have to update the library files + * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */ +#define GPTR_TAG_DATA 0x80 +#define GPTR_TAG_EEPROM 0x40 +#define GPTR_TAG_CODE 0x00 /* must be 0 becaue of UPPER(sym)==0 */ + +/* Wrapper to execute `code' at most once. */ +#define PERFORM_ONCE(id,code) do { static char id = 0; if (!id) { id = 1; code } } while (0) + extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *); extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *); void pic16_genMult8X8_8 (operand *, operand *,operand *); @@ -57,7 +84,6 @@ extern void pic16_printpBlock(FILE *of, pBlock *pb); static asmop *newAsmop (short type); static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op); extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...); -static void mov2f(asmop *dst, asmop *src, int offset); static void mov2fp(pCodeOp *dst, asmop *src, int offset); static pCodeOp *pic16_popRegFromIdx(int rIdx); @@ -65,7 +91,9 @@ static pCodeOp *pic16_popRegFromIdx(int rIdx); int pic16_labelOffset=0; extern int pic16_debug_verbose; +#if !(USE_GENERIC_SIGNED_SHIFT) static int optimized_for_speed = 0; +#endif /* hack hack @@ -122,6 +150,7 @@ static char *one = "#0x01"; char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" }; +int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L }; unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */ static char **fReturn = fReturnpic16; @@ -140,24 +169,15 @@ static struct { short ipushRegs; set *sendSet; set *stackRegSet; - int interruptvector; int usefastretfie; - bitVect *fregsUsed; + bitVect *fregsUsed; /* registers used in function */ + bitVect *sregsAlloc; + set *sregsAllocSet; /* registers used to store stack variables */ int stack_lat; /* stack offset latency */ int resDirect; int useWreg; /* flag when WREG is used to pass function parameter */ } _G; -/* Resolved ifx structure. This structure stores information - about an iCode ifx that makes it easier to generate code. -*/ -typedef struct resolvedIfx { - symbol *lbl; /* pointer to a label */ - int condition; /* true or false ifx */ - int generated; /* set true when the code associated with the ifx - * is generated */ -} resolvedIfx; - extern int pic16_ptrRegReq ; extern int pic16_nRegs; extern FILE *codeOutFile; @@ -229,7 +249,7 @@ void pic16_emitpcomment (char *fmt, ...) { va_list ap; char lb[INITIAL_INLINEASM]; - char *lbp = lb; + unsigned char *lbp = (unsigned char *)lb; va_start(ap,fmt); @@ -255,7 +275,7 @@ void DEBUGpic16_emitcode (char *inst,char *fmt, ...) { va_list ap; char lb[INITIAL_INLINEASM]; - char *lbp = lb; + unsigned char *lbp = (unsigned char *)lb; if(!pic16_debug_verbose) return; @@ -298,7 +318,9 @@ void pic16_emitpLabelFORCE(int key) pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset)); } -void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop) +/* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand + * NEVER call pic16_emitpcode_real directly, please... */ +void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop) { if(pcop) @@ -333,7 +355,7 @@ void pic16_emitcode (char *inst,char *fmt, ...) { va_list ap; char lb[INITIAL_INLINEASM]; - char *lbp = lb; + unsigned char *lbp = lb; va_start(ap,fmt); @@ -388,7 +410,7 @@ static regs *getFreePtr (iCode *ic, asmop **aopp, bool result) bool fsr0iu = FALSE, fsr0ou; bool fsr2iu = FALSE, fsr2ou; - fprintf(stderr, "%s:%d: getting free ptr from ic = %c result: %d\n", __FUNCTION__, __LINE__, ic->op, result); + //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__, __FUNCTION__, __LINE__, ic->op, result); fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2); @@ -406,7 +428,7 @@ static regs *getFreePtr (iCode *ic, asmop **aopp, bool result) ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0); (*aopp)->type = AOP_FSR0; - fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__); + //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__); return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0)); } @@ -635,11 +657,29 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) } #endif + +#if 0 + if(sym->iaccess) { + if(space->paged) { + fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name); + + sym->aop = aop = newAsmop (AOP_PAGED); + aop->aopu.aop_dir = sym->rname ; + aop->size = getSize(sym->type); + DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size); + pic16_allocDirReg( IC_LEFT(ic) ); + return aop; + } + assert( 0 ); + } +#endif + #if 1 /* assign depending on the storage class */ /* if it is on the stack or indirectly addressable */ /* space we need to assign either r0 or r1 to it */ - if (sym->onStack || sym->iaccess) { + if (sym->onStack) // || sym->iaccess) + { pCodeOp *pcop[4]; int i; @@ -653,26 +693,35 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) aop->size = getSize(sym->type); - DEBUGpic16_emitcode("; +++", "%s:%d", __FILE__, __LINE__); - if((ic->op == '=') && IC_RESULT(ic) && AOP( IC_RESULT(ic) ) - && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG) ) { - pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) )); + DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op)); + if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) ) + && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) { +// pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) )); for(i=0;isize;i++) aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx); _G.resDirect = 1; /* notify that result will be loaded directly from aopForSym */ } else + if(1 && ic->op == SEND) { + + /* if SEND do the send here */ + _G.resDirect = 1; + } else { for(i=0;isize;i++) { - aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond( _G.fregsUsed, 0 ); - _G.fregsUsed = bitVectSetBit(_G.fregsUsed, PCOR(pcop[i])->r->rIdx); + aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 ); + _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx); } + } // fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size); #if 1 DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack); - + + // we do not need to load the value if it is to be defined... + if (result) return aop; + if(_G.accInUse) { pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) ); } @@ -680,7 +729,7 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) for(i=0;isize;i++) { /* initialise for stack access via frame pointer */ - // operands on stack are accessible via "FSR2 + index" with index + // operands on stack are accessible via "{FRAME POINTER} + index" with index // starting at 2 for arguments and growing from 0 downwards for // local variables (index == 0 is not assigned so we add one here) { @@ -689,9 +738,17 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) assert (soffs < 0); soffs++; } // if - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/)); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p( - pic16_popCopyReg(&pic16_pc_plusw2), pcop[i])); + + if(1 && ic->op == SEND) { + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg( pic16_frame_plusw ), + pic16_popCopyReg(pic16_stack_postdec ))); + } else { + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg( pic16_frame_plusw ), pcop[i])); + } } } @@ -767,7 +824,7 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) } #endif -#if 0 +#if 1 /* special case for a function */ if (IS_FUNC(sym->type)) { sym->aop = aop = newAsmop(AOP_PCODE); @@ -794,14 +851,21 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) } /* if it is in direct space */ if (IN_DIRSPACE(space)) { - sym->aop = aop = newAsmop (AOP_DIR); - aop->aopu.aop_dir = sym->rname ; - aop->size = getSize(sym->type); - DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size); - pic16_allocDirReg( IC_LEFT(ic) ); - return aop; - } - + if(!strcmp(sym->rname, "_WREG")) { + sym->aop = aop = newAsmop (AOP_ACC); + aop->size = getSize(sym->type); /* should always be 1 */ + assert(aop->size == 1); + DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size); + return (aop); + } else { + sym->aop = aop = newAsmop (AOP_DIR); + aop->aopu.aop_dir = sym->rname ; + aop->size = getSize(sym->type); + DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size); + pic16_allocDirReg( IC_LEFT(ic) ); + return (aop); + } + } if (IN_FARSPACE(space) && !IN_CODESPACE(space)) { sym->aop = aop = newAsmop (AOP_DIR); @@ -839,11 +903,15 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) aop->size = PTRSIZE; else if(IN_CODESPACE( space ) || IN_FARSPACE( space )) aop->size = FPTRSIZE; - else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) ); - else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) ); + else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) ); + else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) ); else if(sym->onStack) { aop->size = PTRSIZE; } else { + if(SPEC_SCLS(sym->etype) == S_PDATA) { + fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__); + aop->size = FPTRSIZE; + } else assert( 0 ); } @@ -859,7 +927,7 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) /*-----------------------------------------------------------------*/ /* aopForRemat - rematerialzes an object */ /*-----------------------------------------------------------------*/ -static asmop *aopForRemat (operand *op) // x symbol *sym) +static asmop *aopForRemat (operand *op, bool result) // x symbol *sym) { symbol *sym = OP_SYMBOL(op); operand *refop; @@ -877,6 +945,7 @@ static asmop *aopForRemat (operand *op) // x symbol *sym) DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__); } +// if(!result) /* fixme-vr */ for (;;) { oldic = ic; @@ -1056,10 +1125,12 @@ bool pic16_sameRegs (asmop *aop1, asmop *aop2 ) aop2->type != AOP_REG ) return FALSE ; + /* This is a bit too restrictive if one is a subset of the other... if (aop1->size != aop2->size ) return FALSE ; + */ - for (i = 0 ; i < aop1->size ; i++ ) { + for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) { // if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE; // if(aop1->aopu.aop_reg[i]->type == AOP_REG) @@ -1157,11 +1228,12 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) b) has a spill location */ if (sym->isspilt || sym->nRegs == 0) { +// debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs); DEBUGpic16_emitcode(";","%d",__LINE__); /* rematerialize it NOW */ if (sym->remat) { - sym->aop = op->aop = aop = aopForRemat (op); + sym->aop = op->aop = aop = aopForRemat (op, result); // aop->size = getSize(sym->type); // DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd); return; @@ -1183,7 +1255,7 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) #endif #if 1 - if (sym->ruonly ) { + if (sym->ruonly) { /* sym->aop = op->aop = aop = newAsmop(AOP_PCODE); aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset); @@ -1193,10 +1265,10 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) unsigned i; - aop = op->aop = sym->aop = newAsmop(AOP_STR); + aop = op->aop = sym->aop = newAsmop(AOP_REG); aop->size = getSize(sym->type); for ( i = 0 ; i < pic16_fReturnSizePic ; i++ ) - aop->aopu.aop_str[i] = fReturn[i]; + aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r; DEBUGpic16_emitcode(";","%d",__LINE__); return; @@ -1217,9 +1289,16 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) sym->aop = op->aop = aop = newAsmop(AOP_PCODE); //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset); - aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, - getSize(sym->type), - sym->usl.spillLoc->offset, op); + if (sym->usl.spillLoc && sym->usl.spillLoc->rname) { + aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, + getSize(sym->type), + sym->usl.spillLoc->offset, op); + } else { + fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__); + pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__); + assert (getSize(sym->type) <= 1); + aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg); + } aop->size = getSize(sym->type); return; @@ -1322,15 +1401,20 @@ void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop) /* initialise for stack access via frame pointer */ pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/)); pic16_emitpcode(POC_MOVFF, pic16_popGet2p( - aop->aopu.stk.pop[i], pic16_popCopyReg(&pic16_pc_plusw2))); + aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw))); } if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) ); } if(!_G.resDirect) { - for(i=0;isize;i++) + for(i=0;isize;i++) { PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1; + + if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) + bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx); + } + } _G.resDirect = 0; } @@ -1478,13 +1562,9 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname) return rs; case AOP_REG: - //if (dname) - // return aop->aopu.aop_reg[offset]->dname; - //else - return aop->aopu.aop_reg[offset]->name; + return aop->aopu.aop_reg[offset]->name; case AOP_CRY: - //pic16_emitcode(";","%d",__LINE__); return aop->aopu.aop_dir; case AOP_ACC: @@ -1496,16 +1576,21 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname) return (rs); case AOP_LIT: - sprintf(s,"0X%02x", pic16aopLiteral (aop->aopu.aop_lit,offset)); + sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset)); rs = Safe_calloc(1,strlen(s)+1); strcpy(rs,s); return rs; case AOP_STR: aop->coff = offset ; - if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && - dname) - return "acc"; + +// if (strcmp(aop->aopu.aop_str[offset],"a") == 0 && +// dname) +// return "acc"; + if(!strcmp(aop->aopu.aop_str[offset], "WREG")) { + aop->type = AOP_ACC; + return Safe_strdup("_WREG"); + } DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]); return aop->aopu.aop_str[offset]; @@ -1518,10 +1603,9 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname) DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset); //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset); if (offset) { - pic16_emitpcomment ("; =!= %s:%d: changed from %s to (%s + %d)", __FUNCTION__, __LINE__, pcop->name, pcop->name, offset); - sprintf(s,"(%s + %d)", pcop->name, offset); + sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset); } else { - sprintf(s,"%s", pcop->name); + sprintf(s,"%s", pic16_get_op (pcop, NULL, 0)); } } else sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset); @@ -1531,6 +1615,21 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname) strcpy(rs,s); return rs; +#if 0 + case AOP_PAGED: + DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s); + if (offset) { + sprintf(s,"(%s + %d)", + aop->aopu.aop_dir, + offset); + } else + sprintf(s,"%s",aop->aopu.aop_dir); + DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s); + rs = Safe_calloc(1,strlen(s)+1); + strcpy(rs,s); + return rs; +#endif + case AOP_STA: rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name); return (rs); @@ -1567,7 +1666,7 @@ int _TempReg_lock = 0; /*-----------------------------------------------------------------*/ pCodeOp *pic16_popGetTempReg(int lock) { - pCodeOp *pcop; + pCodeOp *pcop=NULL; symbol *cfunc; // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); @@ -1580,6 +1679,34 @@ pCodeOp *pic16_popGetTempReg(int lock) cfunc = currFunc; currFunc = NULL; +#if 0 + { + regs *rr; + int i; + + /* this code might seem better but it does the *same* job with + * the old code, it all depends on ralloc.c to get a free/unused + * register */ + + i=0; + while(i < pic16_nRegs) { + rr = pic16_typeRegWithIdx(i, REG_GPR, 0); + fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr); + if((!rr || (rr && rr->isFree)) + && !bitVectBitValue(cfunc->regsUsed, i)) { + pcop = pic16_newpCodeOpReg( i ); + PCOR(pcop)->r->wasUsed = 1; + PCOR(pcop)->r->isFree = 0; + break; + } + i++; + } + + if(pcop) { + pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) ); + } + } +#else pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP); if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) { PCOR(pcop)->r->wasUsed=1; @@ -1588,6 +1715,7 @@ pCodeOp *pic16_popGetTempReg(int lock) /* push value on stack */ pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) ); } +#endif currFunc = cfunc; @@ -1595,13 +1723,15 @@ pCodeOp *pic16_popGetTempReg(int lock) } /*-----------------------------------------------------------------*/ -/* pic16_popGetTempRegCond - create a new temporary pCodeOp, but */ -/* don't save if inside v */ +/* pic16_popGetTempRegCond - create a new temporary pCodeOp which */ +/* is not part of f, but don't save if */ +/* inside v */ /*-----------------------------------------------------------------*/ -pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock) +pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock) { - pCodeOp *pcop; + pCodeOp *pcop=NULL; symbol *cfunc; + int i; // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); @@ -1614,15 +1744,58 @@ pCodeOp *pic16_popGetTempRegCond(bitVect *v, int lock) cfunc = currFunc; currFunc = NULL; - pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP); - if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) { - PCOR(pcop)->r->wasUsed=1; - PCOR(pcop)->r->isFree=0; + i = bitVectFirstBit(f); + while(i < 128) { - if(!bitVectBitValue(v, PCOR(pcop)->r->rIdx)) { - /* push value on stack */ - pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) ); + /* bypass registers that are used by function */ + if(!bitVectBitValue(f, i)) { + + /* bypass registers that are already allocated for stack access */ + if(!bitVectBitValue(v, i)) { + +// debugf("getting register rIdx = %d\n", i); + /* ok, get the operand */ + pcop = pic16_newpCodeOpReg( i ); + + /* should never by NULL */ + assert( pcop != NULL ); + + + /* sanity check */ + if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) { + int found=0; + + PCOR(pcop)->r->wasUsed=1; + PCOR(pcop)->r->isFree=0; + + + { + regs *sr; + + for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) { + + if(sr->rIdx == PCOR(pcop)->r->rIdx) { + /* already used in previous steps, break */ + found=1; + break; + } + } + } + + /* caller takes care of the following */ +// bitVectSetBit(v, i); + + if(!found) { + /* push value on stack */ + pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) ); + addSet(&_G.sregsAllocSet, PCOR(pcop)->r); + } + + break; + } + } } + i++; } currFunc = cfunc; @@ -1642,13 +1815,14 @@ void pic16_popReleaseTempReg(pCodeOp *pcop, int lock) if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) { PCOR(pcop)->r->isFree = 1; + pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) ); } } /*-----------------------------------------------------------------*/ /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL */ /*-----------------------------------------------------------------*/ -pCodeOp *pic16_popGetLabel(unsigned int key) +pCodeOp *pic16_popGetLabel(int key) { DEBUGpic16_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset); @@ -1667,17 +1841,20 @@ pCodeOp *pic16_popCopyReg(pCodeOpReg *pc) pCodeOpReg *pcor; pcor = Safe_calloc(1,sizeof(pCodeOpReg) ); - pcor->pcop.type = pc->pcop.type; + memcpy (pcor, pc, sizeof (pCodeOpReg)); + pcor->r->wasUsed = 1; + + //pcor->pcop.type = pc->pcop.type; if(pc->pcop.name) { if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name))) fprintf(stderr,"oops %s %d",__FILE__,__LINE__); } else pcor->pcop.name = NULL; - pcor->r = pc->r; - pcor->rIdx = pc->rIdx; - pcor->r->wasUsed=1; - pcor->instance = pc->instance; + //pcor->r = pc->r; + //pcor->rIdx = pc->rIdx; + //pcor->r->wasUsed=1; + //pcor->instance = pc->instance; // DEBUGpic16_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx); @@ -1692,6 +1869,12 @@ pCodeOp *pic16_popGetLit(int lit) return pic16_newpCodeOpLit(lit); } +/* Allow for 12 bit literals (LFSR x, ). */ +pCodeOp *pic16_popGetLit12(int lit) +{ + return pic16_newpCodeOpLit12(lit); +} + /*-----------------------------------------------------------------*/ /* pic16_popGetLit2 - asm operator to pcode operator conversion */ /*-----------------------------------------------------------------*/ @@ -1749,6 +1932,7 @@ static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING")); PCOR(pcop)->r = pic16_dirregWithName(pcop->name); +// PCOR(pcop)->r->wasUsed = 1; /* make sure that register doesn't exist, * and operand isn't NULL @@ -1760,7 +1944,7 @@ static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand // __FUNCTION__, __LINE__, str, size, offset); PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op); - fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str); + //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str); } PCOR(pcop)->instance = offset; @@ -1773,11 +1957,14 @@ static pCodeOp *pic16_popRegFromIdx(int rIdx) pCodeOp *pcop; // DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx); - +// fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx); + pcop = Safe_calloc(1,sizeof(pCodeOpReg) ); PCOR(pcop)->rIdx = rIdx; PCOR(pcop)->r = pic16_regWithIdx(rIdx); - + if(!PCOR(pcop)->r) + PCOR(pcop)->r = pic16_allocWithIdx(rIdx); + PCOR(pcop)->r->isFree = 0; PCOR(pcop)->r->wasUsed = 1; @@ -1850,13 +2037,13 @@ pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc) /*-----------------------------------------------------------------*/ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) { - //char *s = buffer ; - char *rs; +// char *s = buffer ; +// char *rs; pCodeOp *pcop; - FENTRY2; - /* offset is greater than - size then zero */ + FENTRY2; + /* offset is greater than + * size then zero */ // if (offset > (aop->size - 1) && // aop->type != AOP_LIT) @@ -1864,71 +2051,73 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) /* depending on type */ switch (aop->type) { - - case AOP_R0: - case AOP_R1: - case AOP_DPTR: - case AOP_DPTR2: - DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type)); - fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type)); - assert( 0 ); - return NULL; - - - case AOP_FSR0: - case AOP_FSR2: - pcop = Safe_calloc(1, sizeof(pCodeOpReg)); - PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */ - PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx ); - PCOR(pcop)->r->wasUsed = 1; - PCOR(pcop)->r->isFree = 0; + case AOP_R0: + case AOP_R1: + case AOP_DPTR: + case AOP_DPTR2: + DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type)); + fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type)); + assert( 0 ); + return NULL; + + case AOP_FSR0: + case AOP_FSR2: + pcop = Safe_calloc(1, sizeof(pCodeOpReg)); + PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */ + PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx ); + PCOR(pcop)->r->wasUsed = 1; + PCOR(pcop)->r->isFree = 0; - PCOR(pcop)->instance = offset; - pcop->type = PCOR(pcop)->r->pc_type; - return (pcop); - - case AOP_IMMD: - DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__); - return pic16_popGetImmd(aop->aopu.aop_immd,offset,0); - - case AOP_STA: - /* pCodeOp is already allocated from aopForSym */ - DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset); - pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]); - - return (pcop); + PCOR(pcop)->instance = offset; + pcop->type = PCOR(pcop)->r->pc_type; + return (pcop); + + case AOP_IMMD: + DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__); + return pic16_popGetImmd(aop->aopu.aop_immd,offset,0); + + case AOP_STA: + /* pCodeOp is already allocated from aopForSym */ + DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset); + pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]); + return (pcop); - case AOP_ACC: - { - int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx; + case AOP_ACC: + { + int rIdx = IDX_WREG; //aop->aopu.aop_reg[offset]->rIdx; - fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]); + fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]); - DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__); + DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__); - pcop = Safe_calloc(1,sizeof(pCodeOpReg) ); - PCOR(pcop)->rIdx = rIdx; - PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx); - PCOR(pcop)->r->wasUsed=1; - PCOR(pcop)->r->isFree=0; + pcop = Safe_calloc(1,sizeof(pCodeOpReg) ); + PCOR(pcop)->rIdx = rIdx; + PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx); + PCOR(pcop)->r->wasUsed=1; + PCOR(pcop)->r->isFree=0; - PCOR(pcop)->instance = offset; - pcop->type = PCOR(pcop)->r->pc_type; -// rs = aop->aopu.aop_reg[offset]->name; -// DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs); - return pcop; + PCOR(pcop)->instance = offset; + pcop->type = PCOR(pcop)->r->pc_type; +// DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs); + return pcop; // return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset); // return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]); // assert( 0 ); - } + } case AOP_DIR: - DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__); + DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir); return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL); +#if 0 + case AOP_PAGED: + DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__); + return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL); +#endif + case AOP_REG: { int rIdx; @@ -1940,16 +2129,16 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) pcop = Safe_calloc(1,sizeof(pCodeOpReg) ); // pcop->type = PO_GPR_REGISTER; PCOR(pcop)->rIdx = rIdx; - PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx); + PCOR(pcop)->r = pic16_allocWithIdx( rIdx ); //pic16_regWithIdx(rIdx); PCOR(pcop)->r->wasUsed=1; PCOR(pcop)->r->isFree=0; PCOR(pcop)->instance = offset; pcop->type = PCOR(pcop)->r->pc_type; - DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s\n", __LINE__, dumpPicOptype(pcop->type)); - rs = aop->aopu.aop_reg[offset]->name; - DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs); + DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type)); +// rs = aop->aopu.aop_reg[offset]->name; +// DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs); return pcop; } @@ -1986,16 +2175,16 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) __LINE__, ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset); pcop = pic16_pCodeOpCopy(aop->aopu.pcop); -#if 1 - switch( aop->aopu.pcop->type ) { - case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8 - case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break; - default: - assert( 0 ); /* should never reach here */; - } -#else - PCOI(pcop)->offset = offset; -#endif + switch( aop->aopu.pcop->type ) { + case PO_DIR: PCOR(pcop)->instance += offset; break; + case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break; + case PO_WREG: + assert (offset==0); + break; + default: + fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type); + assert( 0 ); /* should never reach here */; + } return pcop; } @@ -2250,7 +2439,7 @@ void pic16_mov2w (asmop *aop, int offset) pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset)); } -static void mov2f(asmop *dst, asmop *src, int offset) +void pic16_mov2f(asmop *dst, asmop *src, int offset) { if(is_LitAOp(src)) { pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset)); @@ -2262,6 +2451,20 @@ static void mov2f(asmop *dst, asmop *src, int offset) } } +static void pic16_movLit2f(pCodeOp *pc, int lit) +{ + if (0 == (lit & 0x00ff)) + { + pic16_emitpcode (POC_CLRF, pc); + } else if (0xff == (lit & 0x00ff)) + { + pic16_emitpcode (POC_SETF, pc); + } else { + pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff)); + if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc); + } +} + static void mov2fp(pCodeOp *dst, asmop *src, int offset) { if(is_LitAOp(src)) { @@ -2274,7 +2477,7 @@ static void mov2fp(pCodeOp *dst, asmop *src, int offset) void pic16_testStackOverflow(void) { -#define GSTACK_TEST_NAME "__gstack_test" +#define GSTACK_TEST_NAME "_gstack_test" pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME )); @@ -2282,7 +2485,8 @@ void pic16_testStackOverflow(void) symbol *sym; sym = newSymbol( GSTACK_TEST_NAME , 0 ); - strcpy(sym->rname, GSTACK_TEST_NAME); + sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME); +// strcpy(sym->rname, GSTACK_TEST_NAME); checkAddSym(&externs, sym); } @@ -2292,7 +2496,7 @@ void pic16_testStackOverflow(void) void pic16_pushpCodeOp(pCodeOp *pcop) { // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1))); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); if(pic16_options.gstack) pic16_testStackOverflow(); @@ -2301,7 +2505,7 @@ void pic16_pushpCodeOp(pCodeOp *pcop) /* pop pcop from stack */ void pic16_poppCodeOp(pCodeOp *pcop) { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop)); if(pic16_options.gstack) pic16_testStackOverflow(); } @@ -2313,7 +2517,7 @@ void pic16_poppCodeOp(pCodeOp *pcop) void pushw(void) { DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); if(pic16_options.gstack) pic16_testStackOverflow(); } @@ -2326,15 +2530,16 @@ void pushaop(asmop *aop, int offset) { DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + if(_G.resDirect)return; + if(is_LitAOp(aop)) { pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset)); - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); } else { pic16_emitpcode(POC_MOVFF, - pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg(&pic16_pc_postdec1))); + pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec ))); } -// pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0)); if(pic16_options.gstack) pic16_testStackOverflow(); } @@ -2345,7 +2550,7 @@ void pushaop(asmop *aop, int offset) void popaop(asmop *aop, int offset) { DEBUGpic16_emitcode("; ***", "%s %d", __FUNCTION__, __LINE__); - pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0)); + pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0)); if(pic16_options.gstack) pic16_testStackOverflow(); } @@ -2359,11 +2564,12 @@ void popaopidx(asmop *aop, int offset, int index) if(STACK_MODEL_LARGE)ofs++; pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs)); - pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0)); + pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0)); if(pic16_options.gstack) pic16_testStackOverflow(); } +#if !(USE_GENERIC_SIGNED_SHIFT) /*-----------------------------------------------------------------*/ /* reAdjustPreg - points a register back to where it should */ /*-----------------------------------------------------------------*/ @@ -2402,7 +2608,7 @@ static void reAdjustPreg (asmop *aop) } } - +#endif #if 0 /*-----------------------------------------------------------------*/ @@ -2542,108 +2748,6 @@ void pic16_toBoolean(operand *oper) } } - -#if !defined(GEN_Not) -/*-----------------------------------------------------------------*/ -/* genNot - generate code for ! operation */ -/*-----------------------------------------------------------------*/ -static void pic16_genNot (iCode *ic) -{ - symbol *tlbl; - int size; - - FENTRY; - /* assign asmOps to operand & result */ - pic16_aopOp (IC_LEFT(ic),ic,FALSE); - pic16_aopOp (IC_RESULT(ic),ic,TRUE); - - DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic)); - /* if in bit space then a special case */ - if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) { - if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) { - pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0)); - pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0)); - } else { - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0)); - pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0)); - pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0)); - } - goto release; - } - - size = AOP_SIZE(IC_LEFT(ic)); - if(size == 1) { - pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0)); - pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0)); - goto release; - } - pic16_toBoolean(IC_LEFT(ic)); - - tlbl = newiTempLabel(NULL); - pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100); - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - pic16_outBitC(IC_RESULT(ic)); - - release: - /* release the aops */ - pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1)); - pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); -} -#endif - - -#if !defined(GEN_Cpl) -/*-----------------------------------------------------------------*/ -/* genCpl - generate code for complement */ -/*-----------------------------------------------------------------*/ -static void pic16_genCpl (iCode *ic) -{ - int offset = 0; - int size ; - - FENTRY; - /* assign asmOps to operand & result */ - pic16_aopOp (IC_LEFT(ic),ic,FALSE); - pic16_aopOp (IC_RESULT(ic),ic,TRUE); - - /* if both are in bit space then - a special case */ - if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY && - AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { - - pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); - pic16_emitcode("cpl","c"); - pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); - goto release; - } - - size = AOP_SIZE(IC_RESULT(ic)); - while (size--) { -/* - char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE); - MOVA(l); - pic16_emitcode("cpl","a"); - pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++); -*/ - if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) { - pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_LEFT(ic)), offset)); - } else { - pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - } - offset++; - - } - - -release: - /* release the aops */ - pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1)); - pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); -} -#endif - /*-----------------------------------------------------------------*/ /* genUminusFloat - unary minus for floating points */ /*-----------------------------------------------------------------*/ @@ -2655,9 +2759,10 @@ static void genUminusFloat(operand *op,operand *result) /* for this we just need to flip the first it then copy the rest in place */ size = AOP_SIZE(op); + assert( size == AOP_SIZE(result) ); while(size--) { - mov2f(AOP(result), AOP(op), offset); + pic16_mov2f(AOP(result), AOP(op), offset); offset++; } @@ -2672,6 +2777,8 @@ static void genUminus (iCode *ic) { int size, i; sym_link *optype, *rtype; + symbol *label; + int needLabel=0; FENTRY; @@ -2692,29 +2799,46 @@ static void genUminus (iCode *ic) optype = operandType(IC_LEFT(ic)); rtype = operandType(IC_RESULT(ic)); + /* if float then do float stuff */ - if (IS_FLOAT(optype)) { - genUminusFloat(IC_LEFT(ic),IC_RESULT(ic)); - goto release; + if (IS_FLOAT(optype) || IS_FIXED(optype)) { + if(IS_FIXED(optype)) + debugf("implement fixed16x16 type\n", 0); + + genUminusFloat(IC_LEFT(ic),IC_RESULT(ic)); + goto release; } /* otherwise subtract from zero by taking the 2's complement */ size = AOP_SIZE(IC_LEFT(ic)); - - for(i=0; i 0; i--) { + pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i)); + } // for + pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0)); + for (i=1; i < size; i++) { + if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; } + pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i)); + } // for + } else { + for (i=size-1; i >= 0; i--) { + pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i)); + pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i)); + } // for + if (size > 1) { + for (i=0; i < size-2; i++) { + pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i)); + pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; + } // for + pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2)); + } // if + pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1)); + } + if (needLabel) + pic16_emitpLabel (label->key); release: /* release the aops */ @@ -2849,7 +2973,7 @@ static void pushSide(operand * oper, int size) void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src) { - if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) { + if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) { pic16_emitpcode(POC_MOVFW, src); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset)); } else { @@ -2912,10 +3036,10 @@ static void assignResultValue(operand * oper, int rescall) /* fix stack */ pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) )); - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l )); + pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l )); if(STACK_MODEL_LARGE) { emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h )); + pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h )); } } } else { @@ -3164,7 +3288,7 @@ static void genCall (iCode *ic) // stackParms = psuedoStkPtr; // fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes); fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name; - inwparam = inWparamList(OP_SYMBOL(IC_LEFT(ic))->name); + inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic)))); #if 0 gpsimDebug_StackDump(__FILE__, __LINE__, fname ); @@ -3229,8 +3353,10 @@ static void genCall (iCode *ic) DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1); // pushaop(AOP(IC_LEFT(sic)), size); - pic16_mov2w (AOP(IC_LEFT(sic)), size); - pushw(); + pic16_mov2w( AOP(IC_LEFT(sic)), size ); + + if(!_G.resDirect) + pushw(); } } @@ -3280,14 +3406,14 @@ static void genCall (iCode *ic) if(stackParms>0) { if(stackParms == 1) { - pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1l)); + pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo )); //&pic16_pc_fsr1l)); } else { pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms)); - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l )); + pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l )); } if(STACK_MODEL_LARGE) { emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h )); + pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h )); } } @@ -3317,14 +3443,13 @@ static void genCall (iCode *ic) /*-----------------------------------------------------------------*/ static void genPcall (iCode *ic) { - sym_link *ftype, *fntype; + sym_link *fntype; int stackParms=0; symbol *retlbl = newiTempLabel(NULL); pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key); FENTRY; - ftype = OP_SYM_TYPE(IC_LEFT(ic)); fntype = operandType( IC_LEFT(ic) )->next; /* if send set is not empty the assign */ @@ -3368,6 +3493,11 @@ static void genPcall (iCode *ic) // push return address // push $ on return stack, then replace with retlbl + /* Thanks to Thorsten Klose for pointing out that the following + * snippet should be interrupt safe */ + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1))); + pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7)); + pic16_emitpcodeNULLop(POC_PUSH); pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0)); @@ -3377,12 +3507,17 @@ static void genPcall (iCode *ic) pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0)); pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu)); + + /* restore interrupt control register */ + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon)); + /* make the call by writing the pointer into pc */ - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath))); + mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2); + mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1); // note: MOVFF to PCL not allowed - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0)); + pic16_mov2w(AOP(IC_LEFT(ic)), 0); pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl)); @@ -3414,11 +3549,10 @@ static void genPcall (iCode *ic) if(stackParms>0) { pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms)); - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l )); + pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); if(STACK_MODEL_LARGE) { - /* this implies that stackParms < 256 !!! -- VR */ emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h )); + pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); } } } @@ -3496,38 +3630,33 @@ static void genFunction (iCode *ic) char asymname[128]; pBlock *apb; - { - int i, found=-1; - - sym = OP_SYMBOL( IC_LEFT(ic)); - for(i=0;i<=2;i++) { - if(interrupts[i]->name - && !STRCASECMP(interrupts[i]->name, sym->name)) { - found = i; - break; - } - } - - if(found == -1) { - fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n", - __FILE__, __LINE__, sym->name); - assert( 0 ); - } - _G.interruptvector = found; - } - - sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name); - asym = newSymbol(asymname, 0); - - apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section")); - pic16_addpBlock( apb ); +// debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type)); - pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------")); - pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name)); - pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname ))); + if(FUNC_INTNO(sym->type) == INTNO_UNSPEC) + sprintf(asymname, "ivec_%s", sym->name); + else + sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name); + + /* when an interrupt is declared as naked, do not emit the special + * wrapper segment at vector address. The user should take care for + * this instead. -- VR */ + + if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) { + asym = newSymbol(asymname, 0); + apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section")); + pic16_addpBlock( apb ); + + pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------")); + pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name)); + //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname ))); + //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0))); + pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */ - /* mark the end of this tiny function */ - pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL)); + /* mark the end of this tiny function */ + pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL)); + } else { + sprintf(asymname, "%s", sym->rname); + } { absSym *abSym; @@ -3535,14 +3664,19 @@ static void genFunction (iCode *ic) abSym = Safe_calloc(1, sizeof(absSym)); strcpy(abSym->name, asymname); - switch( _G.interruptvector ) { + switch( FUNC_INTNO(sym->type) ) { case 0: abSym->address = 0x000000; break; case 1: abSym->address = 0x000008; break; case 2: abSym->address = 0x000018; break; + + default: +// fprintf(stderr, "no interrupt number is given\n"); + abSym->address = -1; break; } /* relocate interrupt vectors if needed */ - abSym->address += pic16_options.ivt_loc; + if(abSym->address != -1) + abSym->address += pic16_options.ivt_loc; addSet(&absSymSet, abSym); } @@ -3556,7 +3690,6 @@ static void genFunction (iCode *ic) pic16_emitcode("","%s:",sym->rname); pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname)); - { absSym *ab; @@ -3568,7 +3701,6 @@ static void genFunction (iCode *ic) } } - if(IFFUNC_ISNAKED(ftype)) { DEBUGpic16_emitcode("; ***", "_naked function, no prologue"); return; @@ -3579,7 +3711,10 @@ static void genFunction (iCode *ic) //pic16_emitcode("clr","ea"); } + currFunc = sym; /* update the currFunc symbol */ _G.fregsUsed = sym->regsUsed; + _G.sregsAlloc = newBitVect(128); + /* if this is an interrupt service routine then * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */ @@ -3587,7 +3722,7 @@ static void genFunction (iCode *ic) _G.usefastretfie = 1; /* use shadow registers by default */ /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */ - if(!(_G.interruptvector == 1)) { + if(!FUNC_ISSHADOWREGS(sym->type)) { /* do not save WREG,STATUS,BSR for high priority interrupts * because they are stored in the hardware shadow registers already */ _G.usefastretfie = 0; @@ -3604,23 +3739,27 @@ static void genFunction (iCode *ic) pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h )); // pic16_pBlockConvert2ISR(pb); - } /* emit code to setup stack frame if user enabled, * and function is not main() */ - - //fprintf(stderr, "function name: %s\n", sym->name); + +// debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type)); if(strcmp(sym->name, "main")) { - if(1 /*!options.ommitFramePtr || sym->regsUsed*/) { + if(0 + || !options.ommitFramePtr +// || sym->regsUsed + || IFFUNC_ARGS(sym->type) + || FUNC_HASSTACKPARM(sym->etype) + ) { /* setup the stack frame */ if(STACK_MODEL_LARGE) - pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2h)); - pic16_pushpCodeOp(pic16_popCopyReg(&pic16_pc_fsr2l)); -// pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0)); - pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0)); + pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi)); + pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo)); + + pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0)); if(STACK_MODEL_LARGE) - pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0)); + pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0)); } } @@ -3630,12 +3769,12 @@ static void genFunction (iCode *ic) if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name); pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack)); - pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_fsr1l)); + pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo )); //&pic16_pc_fsr1l)); emitSKPC; - pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_fsr1h)); + pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi )); //&pic16_pc_fsr1h)); } - if(inWparamList(sym->name)) { + if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) { if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type)) _G.useWreg = 0; else @@ -3646,27 +3785,46 @@ static void genFunction (iCode *ic) /* if callee-save to be used for this function * then save the registers being used in this function */ // if (IFFUNC_CALLEESAVES(sym->type)) - { + if(strcmp(sym->name, "main")) { int i; /* if any registers used */ if (sym->regsUsed) { - /* save the registers used */ - DEBUGpic16_emitcode("; **", "Saving used registers in stack"); - pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN)); - for ( i = 0 ; i < sym->regsUsed->size ; i++) { - if (bitVectBitValue(sym->regsUsed,i)) { - pic16_pushpCodeOp( pic16_popRegFromIdx(i) ); - _G.nRegsSaved++; - - if(!pic16_regWithIdx(i)->wasUsed) { - fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n", - __FILE__, __LINE__, pic16_regWithIdx(i)->name); - pic16_regWithIdx(i)->wasUsed = 1; + pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN)); + + if(!xinst) { + /* save the registers used */ + DEBUGpic16_emitcode("; **", "Saving used registers in stack"); + for ( i = 0 ; i < sym->regsUsed->size ; i++) { + if (bitVectBitValue(sym->regsUsed,i)) { +#if 0 + fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i); +#endif + pic16_pushpCodeOp( pic16_popRegFromIdx(i) ); + _G.nRegsSaved++; + + if(!pic16_regWithIdx(i)->wasUsed) { + fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n", + __FILE__, __LINE__, pic16_regWithIdx(i)->name); + pic16_regWithIdx(i)->wasUsed = 1; + } + } + } + } else { + + /* xinst */ + DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers"); + for(i=0;iregsUsed->size;i++) { + if(bitVectBitValue(sym->regsUsed, i)) { + _G.nRegsSaved++; } } + +// pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved))); } + pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END)); + } } @@ -3701,7 +3859,18 @@ static void genEndFunction (iCode *ic) /* now we need to restore the registers */ /* if any registers used */ - if (sym->regsUsed) { + + /* first restore registers that might be used for stack access */ + if(_G.sregsAllocSet) { + regs *sr; + + _G.sregsAllocSet = reverseSet( _G.sregsAllocSet ); + for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) { + pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) ); + } + } + + if (strcmp(sym->name, "main") && sym->regsUsed) { int i; pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN)); @@ -3714,34 +3883,38 @@ static void genEndFunction (iCode *ic) } } pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END)); - } + + if ((IFFUNC_ISREENT(sym->type) || options.stackAuto) && sym->stack) { if (sym->stack == 1) { - pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg(&pic16_pc_fsr1l)); - pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h)); + pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo )); + pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); } else { // we have to add more than one... - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc1)); // this holds a return value! + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc )); // this holds a return value! pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1)); - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(&pic16_pc_fsr1l)); + pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo )); emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_fsr1h)); + pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi )); pic16_emitpcode(POC_COMF, pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)! - pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_plusw1)); // this holds a retrun value! + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value! } } if(strcmp(sym->name, "main")) { - if(1/*!options.ommitFramePtr ||*/ /*sym->regsUsed*/) { + if(0 + || !options.ommitFramePtr +// || sym->regsUsed + || IFFUNC_ARGS(sym->type) + || FUNC_HASSTACKPARM(sym->etype) + ) { /* restore stack frame */ if(STACK_MODEL_LARGE) - pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2h )); -// pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0)); - pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr2l )); -// pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0)); + pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi )); + pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo )); } } @@ -3753,14 +3926,14 @@ static void genEndFunction (iCode *ic) pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh )); pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl )); - if(!(_G.interruptvector == 1)) { + if(!FUNC_ISSHADOWREGS(sym->type)) { /* do not restore interrupt vector for WREG,STATUS,BSR * for high priority interrupt, see genFunction */ pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr )); pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status )); pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg )); } - _G.interruptvector = 0; /* sanity check */ +// _G.interruptvector = 0; /* sanity check */ /* if debug then send end of function */ @@ -3800,19 +3973,34 @@ static void genEndFunction (iCode *ic) } -void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest) +void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest) { - if(is_LitOp(op)) { - unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit); - if(lit == 0) { - pic16_emitpcode(POC_CLRF, dest); + unsigned long lit=1; + operand *op; + + op = IC_LEFT(ic); + + // this fails for is_LitOp(op) (if op is an AOP_PCODE) + if(AOP_TYPE(op) == AOP_LIT) { + if(!IS_FLOAT(operandType( op ))) { + lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit); } else { - pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); - if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest); + union { + unsigned long lit_int; + float lit_float; + } info; + + /* take care if literal is a float */ + info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit); + lit = info.lit_int; } - } else { - if(dest->type == PO_WREG && (offset == 0)) { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset)); + } + + if(is_LitOp(op)) { + pic16_movLit2f(dest, lit); + } else { + if(dest->type == PO_WREG && (offset == 0)) { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset)); return; } pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest)); @@ -3840,27 +4028,16 @@ static void genRet (iCode *ic) size = AOP_SIZE(IC_LEFT(ic)); if(size <= 4) { - if(size>3) { - pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l)); -// pic16_emitpcode(POC_MOVFF, -// pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l))); - } - if(size>2) { - pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh)); -// pic16_emitpcode(POC_MOVFF, -// pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh))); - } - if(size>1) { - pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl)); -// pic16_emitpcode(POC_MOVFF, -// pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl))); - } - -// pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0)); // patch 12 + if(size>3) + pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l)); + + if(size>2) + pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh)); - pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg)); // patch 12 -// pic16_emitpcode(POC_MOVFF, -// pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg))); + if(size>1) + pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl)); + + pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg)); } else { /* >32-bits, setup stack and FSR0 */ @@ -3876,13 +4053,13 @@ static void genRet (iCode *ic) /* setup FSR0 */ pic16_emitpcode(POC_MOVFF, pic16_popGet2p( - pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l))); + pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l))); if(STACK_MODEL_LARGE) { pic16_emitpcode(POC_MOVFF, pic16_popGet2p( - pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h))); + pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h))); } else { - pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) ); + pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi )); } } @@ -4533,7 +4710,7 @@ static void genIfxJump (iCode *ic, char *jval) if(strcmp(jval,"a") == 0) emitSKPZ; else if (strcmp(jval,"c") == 0) - emitSKPC; + emitSKPNC; else { DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER)); @@ -4548,7 +4725,7 @@ static void genIfxJump (iCode *ic, char *jval) if(strcmp(jval,"a") == 0) emitSKPNZ; else if (strcmp(jval,"c") == 0) - emitSKPNC; + emitSKPC; else { DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER)); @@ -4564,6 +4741,33 @@ static void genIfxJump (iCode *ic, char *jval) ic->generated = 1; } +static void genIfxpCOpJump (iCode *ic, pCodeOp *jop) +{ + FENTRY; + + /* if true label then we jump if condition + supplied is true */ + if ( IC_TRUE(ic) ) { + DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__); + pic16_emitpcode(POC_BTFSC, jop); + + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key)); + pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset); + + } else { + /* false label is present */ + DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__); + pic16_emitpcode(POC_BTFSS, jop); + + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key)); + pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset); + } + + + /* mark the icode as generated */ + ic->generated = 1; +} + #if 0 // not needed ATM @@ -4630,14 +4834,15 @@ static void genSkipc(resolvedIfx *rifx) return; if(rifx->condition) - emitSKPC; - else emitSKPNC; + else + emitSKPC; pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key)); rifx->generated = 1; } +#if !(USE_SIMPLE_GENCMP) /*-----------------------------------------------------------------*/ /* genSkipz2 */ /*-----------------------------------------------------------------*/ @@ -4656,6 +4861,7 @@ static void genSkipz2(resolvedIfx *rifx, int invert_condition) pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key)); rifx->generated = 1; } +#endif #if 0 /*-----------------------------------------------------------------*/ @@ -4684,6 +4890,7 @@ static void genSkipz(iCode *ifx, int condition) } #endif +#if !(USE_SIMPLE_GENCMP) /*-----------------------------------------------------------------*/ /* genSkipCond */ /*-----------------------------------------------------------------*/ @@ -4701,6 +4908,7 @@ static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit) pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key)); rifx->generated = 1; } +#endif #if 0 /*-----------------------------------------------------------------*/ @@ -4731,10 +4939,243 @@ static int genChkZeroes(operand *op, int lit, int size) } #endif + +/*-----------------------------------------------------------------*/ +/* mov2w_regOrLit :- move to WREG either the offset's byte from */ +/* aop (if it's NOT a literal) or from lit (if */ +/* aop is a literal) */ +/*-----------------------------------------------------------------*/ +void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) { + if (aop->type == AOP_LIT) { + pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8))); + } else { + pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset)); + } +} + /*-----------------------------------------------------------------*/ /* genCmp :- greater or less than comparison */ /*-----------------------------------------------------------------*/ -#if 1 + +#if USE_SIMPLE_GENCMP /* { */ + +/* genCmp performs a left < right comparison, stores + * the outcome in result (if != NULL) and generates + * control flow code for the ifx (if != NULL). + * + * This version leaves in sequences like + * "B[CS]F STATUS,0; BTFS[CS] STATUS,0" + * which should be optmized by the peephole + * optimizer - RN 2005-01-01 */ +static void genCmp (operand *left,operand *right, + operand *result, iCode *ifx, int sign) +{ + resolvedIfx rIfx; + int size; + int offs; + symbol *templbl; + operand *dummy; + unsigned long lit; + unsigned long mask; + int performedLt; + + FENTRY; + + assert (left && right); + assert (AOP_SIZE(left) == AOP_SIZE(right)); + + size = AOP_SIZE(right) - 1; + mask = (0x100UL << (size*8)) - 1; + // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0) + performedLt = 1; + templbl = NULL; + lit = 0; + + resolveIfx (&rIfx, ifx); + + /* handle for special cases */ + if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign)) + return; + + /********************************************************************** + * handle bits - bit compares are promoted to int compares seemingly! * + **********************************************************************/ +#if 0 + // THIS IS COMPLETELY UNTESTED! + if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) { + pCodeOp *pcleft = pic16_popGet(AOP(left), 0); + pCodeOp *pcright = pic16_popGet(AOP(right), 0); + assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT); + + emitSETC; + // 1 < {0,1} is false --> clear C by skipping the next instruction + //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit); + pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0)); + // {0,1} < 0 is false --> clear C by NOT skipping the next instruction + pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit)); + emitCLRC; // only skipped for left=0 && right=1 + + goto correct_result_in_carry; + } // if +#endif + + /************************************************* + * make sure that left is register (or the like) * + *************************************************/ + if (!isAOP_REGlike(left)) { + DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right)); + assert (isAOP_LIT(left)); + assert (isAOP_REGlike(right)); + // swap left and right + // left < right <==> right > left <==> (right >= left + 1) + lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit); + + if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) { + // MAXVALUE < right? always false + if (performedLt) emitCLRC; else emitSETC; + goto correct_result_in_carry; + } // if + + // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed), + // that's why we handled it above. + lit++; + + dummy = left; + left = right; + right = dummy; + + performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1" + } else if (isAOP_LIT(right)) { + lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); + } // if + + assert (isAOP_REGlike(left)); // left must be register or the like + assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal + + /************************************************* + * special cases go here * + *************************************************/ + + if (isAOP_LIT(right)) { + if (!sign) { + // unsigned comparison to a literal + DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1); + if (lit == 0) { + // unsigned left < 0? always false + if (performedLt) emitCLRC; else emitSETC; + goto correct_result_in_carry; + } + } else { + // signed comparison to a literal + DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask); + if ((lit & mask) == ((0x80 << (size*8)) & mask)) { + // signed left < 0x80000000? always false + if (performedLt) emitCLRC; else emitSETC; + goto correct_result_in_carry; + } else if (lit == 0) { + // compare left < 0; set CARRY if SIGNBIT(left) is set + if (performedLt) emitSETC; else emitCLRC; + pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7)); + if (performedLt) emitCLRC; else emitSETC; + goto correct_result_in_carry; + } + } // if (!sign) + } // right is literal + + /************************************************* + * perform a general case comparison * + * make sure we get CARRY==1 <==> left >= right * + *************************************************/ + // compare most significant bytes + //DEBUGpc ("comparing bytes at offset %d", size); + if (!sign) { + // unsigned comparison + mov2w_regOrLit (AOP(right), lit, size); + pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size)); + } else { + // signed comparison + // (add 2^n to both operands then perform an unsigned comparison) + if (isAOP_LIT(right)) { + // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0) + unsigned char litbyte = (lit >> (8*size)) & 0xFF; + + if (litbyte == 0x80) { + // left >= 0x80 -- always true, but more bytes to come + pic16_mov2w (AOP(left), size); + pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag + emitSETC; + } else { + // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100 + pic16_mov2w (AOP(left), size); + pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80)); + pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF)); + } // if + } else { + /* using PRODL as a temporary register here */ + pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl); + //pCodeOp *pctemp = pic16_popGetTempReg(1); + pic16_mov2w (AOP(left), size); + pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80)); + pic16_emitpcode (POC_MOVWF, pctemp); + pic16_mov2w (AOP(right), size); + pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80)); + pic16_emitpcode (POC_SUBFW, pctemp); + //pic16_popReleaseTempReg(pctemp, 1); + } + } // if (!sign) + + // compare remaining bytes (treat as unsigned case from above) + templbl = newiTempLabel ( NULL ); + offs = size; + while (offs--) { + //DEBUGpc ("comparing bytes at offset %d", offs); + pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key)); + mov2w_regOrLit (AOP(right), lit, offs); + pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs)); + } // while (offs) + pic16_emitpLabel (templbl->key); + goto result_in_carry; + +result_in_carry: + + /**************************************************** + * now CARRY contains the result of the comparison: * + * SUBWF sets CARRY iff * + * F-W >= 0 <==> F >= W <==> !(F < W) * + * (F=left, W=right) * + ****************************************************/ + + if (performedLt) { + if (result && AOP_TYPE(result) != AOP_CRY) { + // value will be stored + emitTOGC; + } else { + // value wil only be used in the following genSkipc() + rIfx.condition ^= 1; + } + } // if + +correct_result_in_carry: + + // assign result to variable (if neccessary) + if (result && AOP_TYPE(result) != AOP_CRY) { + //DEBUGpc ("assign result"); + size = AOP_SIZE(result); + while (size--) { + pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size)); + } // while + pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0)); + } // if (result) + + // perform conditional jump + if (ifx) { + //DEBUGpc ("generate control flow"); + genSkipc (&rIfx); + ifx->generated = 1; + } // if +} + +#elif 1 /* } */ /* { */ /* original code */ static void genCmp (operand *left,operand *right, @@ -5367,7 +5808,7 @@ static void genCmp (operand *left,operand *right, pctemp = pic16_popGetTempReg(1); pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size)); - pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr)); + pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr)); pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80)); pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr)); pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size)); @@ -5457,7 +5898,7 @@ check_carry: } -#else /* old version of genCmp() */ /* } else { */ +#elif 0 /* VR version of genCmp() */ /* } else { */ /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */ static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx, @@ -5567,10 +6008,6 @@ static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl, } } - - - -#if 1 /* { */ static void genCmp (operand *left, operand *right, operand *result, iCode *ifx, int sign) { @@ -5629,6 +6066,7 @@ static void genCmp (operand *left, operand *right, /* signed compare */ DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__); + /* using PRODL:PRODH as a temporary register here */ pct = pic16_popCopyReg(&pic16_pc_prodl); pct2 = pic16_popCopyReg(&pic16_pc_prodh); tlbl = newiTempLabel( NULL ); @@ -5709,7 +6147,6 @@ static void genCmp (operand *left, operand *right, // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl); // compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl); } -// } if(ifx)ifx->generated = 1; @@ -5722,7 +6159,6 @@ static void genCmp (operand *left, operand *right, } } else { - /* unsigned compare */ DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__); @@ -5733,10 +6169,8 @@ static void genCmp (operand *left, operand *right, compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL); } - if(ifx)ifx->generated = 1; - if(AOP_SIZE(result)) { pic16_emitpLabel(falselbl->key); pic16_outBitC( result ); @@ -5821,561 +6255,104 @@ static void genCmp (operand *left, operand *right, } } -#else /* } else { */ +#endif /* } */ -/* new version of genCmp -- VR 20041012 */ -static void genCmp (operand *left,operand *right, - operand *result, iCode *ifx, int sign) + + +/*-----------------------------------------------------------------*/ +/* genCmpGt :- greater than comparison */ +/*-----------------------------------------------------------------*/ +static void genCmpGt (iCode *ic, iCode *ifx) { - int size; //, offset = 0 ; - unsigned long lit = 0L,i = 0; - resolvedIfx rFalseIfx; - int willCheckCarry=0; - // resolvedIfx rTrueIfx; - symbol *truelbl; + operand *left, *right, *result; + sym_link *letype , *retype; + int sign ; FENTRY; - - /* General concept: - * subtract right from left if at the end the carry flag is set then we - * know that left is greater than right */ - - resolveIfx(&rFalseIfx,ifx); - truelbl = newiTempLabel(NULL); - size = max(AOP_SIZE(left),AOP_SIZE(right)); + + left = IC_LEFT(ic); + right= IC_RIGHT(ic); + result = IC_RESULT(ic); - DEBUGpic16_pic16_AopType(__LINE__,left,right,result); + letype = getSpec(operandType(left)); + retype =getSpec(operandType(right)); + sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype)); + /* assign the amsops */ + pic16_aopOp (left,ic,FALSE); + pic16_aopOp (right,ic,FALSE); + pic16_aopOp (result,ic,TRUE); - /* POC_CPFSGT compare f, wreg, skip if f greater than wreg - * POC_CPFSLT compare f, wreg, skip if f less then wreg */ - + genCmp(right, left, result, ifx, sign); - /* if literal is on the right then swap with left */ - if ((AOP_TYPE(right) == AOP_LIT)) { - operand *tmp = right ; - unsigned long mask = (0x100 << (8*(size-1))) - 1; + pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(result,NULL,ic,TRUE); +} - lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); +/*-----------------------------------------------------------------*/ +/* genCmpLt - less than comparisons */ +/*-----------------------------------------------------------------*/ +static void genCmpLt (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + sym_link *letype , *retype; + int sign ; -// lit = (lit - 1) & mask; - right = left; - left = tmp; - rFalseIfx.condition ^= 1; /* reverse compare */ - } else - if ((AOP_TYPE(left) == AOP_LIT)) { - /* float compares are handled by support functions */ - lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit); - } + FENTRY; + left = IC_LEFT(ic); + right= IC_RIGHT(ic); + result = IC_RESULT(ic); - //if(IC_TRUE(ifx) == NULL) - /* if left & right are bit variables */ - if (AOP_TYPE(left) == AOP_CRY && - AOP_TYPE(right) == AOP_CRY ) { + letype = getSpec(operandType(left)); + retype =getSpec(operandType(right)); + sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype)); - pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); - pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir); + /* assign the amsops */ + pic16_aopOp (left,ic,FALSE); + pic16_aopOp (right,ic,FALSE); + pic16_aopOp (result,ic,TRUE); - } else { - symbol *lbl = newiTempLabel(NULL); + genCmp(left, right, result, ifx, sign); - if(AOP_TYPE(left) == AOP_LIT) { - DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign); + pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(result,NULL,ic,TRUE); +} - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) - willCheckCarry = 1; - else willCheckCarry = 0; +#if 0 +// not needed ATM +// FIXME reenable literal optimisation when the pic16 port is stable - /* Special cases */ - if((lit == 0) && (sign == 0)) { - /* unsigned compare to 0 */ - DEBUGpic16_emitcode("; unsigned compare to 0","lit = 0x%x, sign=%d",lit,sign); - - size--; - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - while(size) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size)); +/*-----------------------------------------------------------------*/ +/* genc16bit2lit - compare a 16 bit value to a literal */ +/*-----------------------------------------------------------------*/ +static void genc16bit2lit(operand *op, int lit, int offset) +{ + int i; - genSkipz2(&rFalseIfx,0); - if(ifx)ifx->generated = 1; - return; - } + DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit); + if( (lit&0xff) == 0) + i=1; + else + i=0; - if(size==1) { - /* Special cases */ - lit &= 0xff; - if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) { - /* degenerate compare can never be true */ - if(rFalseIfx.condition == 0) - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key)); + switch( BYTEofLONG(lit,i)) { + case 0: + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i)); + break; + case 1: + pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i)); + break; + case 0xff: + pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i)); + break; + default: + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i)); + pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i))); + } - if(ifx) ifx->generated = 1; - return; - } - - if(sign) { - /* signed comparisons to a literal byte */ - DEBUGpic16_emitcode(";signed compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign); - - int lp1 = (lit+1) & 0xff; - - DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x condition = %d lp1 = %i",__LINE__,lit, rFalseIfx.condition, lp1); - switch (lp1) { - case 0: - rFalseIfx.condition ^= 1; - genSkipCond(&rFalseIfx,right,0,7); - break; - case 0x7f: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f)); - genSkipz2(&rFalseIfx,1); - break; - default: - pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit )); - - if(rFalseIfx.condition) - pic16_emitpcode(POC_CPFSLT, pic16_popGet(AOP(right), 0)); - else - pic16_emitpcode(POC_CPFSGT, pic16_popGet(AOP(right), 0)); - - if(willCheckCarry) { - if(!rFalseIfx.condition) { emitCLRC; emitSETC; } - else { emitSETC; emitCLRC; } - - } else { - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - } - -/* pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80)); - rFalseIfx.condition ^= 1; - genSkipc(&rFalseIfx); -*/ - break; - } - } else { - /* unsigned comparisons to a literal byte */ - DEBUGpic16_emitcode("; unsigned compare to literal","%d: lit = 0x%x, sign=%d",__LINE__, lit,sign); - - switch(lit & 0xff ) { - /* special cases */ - case 0: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - genSkipz2(&rFalseIfx,0); - break; - case 0x7f: - rFalseIfx.condition ^= 1; - genSkipCond(&rFalseIfx,right,0,7); - break; - default: - pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0)); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - rFalseIfx.condition ^= 1; - if (AOP_TYPE(result) == AOP_CRY) - genSkipc(&rFalseIfx); - else { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0)); - } - break; - } - } - - if(ifx) ifx->generated = 1; - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) - goto check_carry; - return; - - } else { - - /* Size is greater than 1 */ - - if(sign) { - int lp1 = lit+1; - - size--; - - if(lp1 == 0) { - /* this means lit = 0xffffffff, or -1 */ - - - DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__); - rFalseIfx.condition ^= 1; - genSkipCond(&rFalseIfx,right,size,7); - if(ifx) ifx->generated = 1; - return; - } - - if(lit == 0) { - int s = size; - - if(rFalseIfx.condition) { - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - } - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - while(size--) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size)); - - - emitSKPZ; - if(rFalseIfx.condition) { - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - pic16_emitpLabel(truelbl->key); - }else { - rFalseIfx.condition ^= 1; - genSkipCond(&rFalseIfx,right,s,7); - } - - if(ifx) ifx->generated = 1; - return; - } - - if((size == 1) && (0 == (lp1&0xff))) { - /* lower byte of signed word is zero */ - DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit); - i = ((lp1 >> 8) & 0xff) ^0x80; - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i)); - rFalseIfx.condition ^= 1; - genSkipc(&rFalseIfx); - - - if(ifx) ifx->generated = 1; - return; - } - - if(lit & (0x80 << (size*8))) { - /* Lit is less than zero */ - DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit); - //rFalseIfx.condition ^= 1; - //genSkipCond(&rFalseIfx,left,size,7); - //rFalseIfx.condition ^= 1; - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - - if(rFalseIfx.condition) - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - else - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - - - } else { - /* Lit is greater than or equal to zero */ - DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit); - //rFalseIfx.condition ^= 1; - //genSkipCond(&rFalseIfx,right,size,7); - //rFalseIfx.condition ^= 1; - - //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0)); - //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - if(rFalseIfx.condition) - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - else - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - - } - - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size)); - - while(size--) { - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff)); - emitSKPNZ; - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size)); - } - rFalseIfx.condition ^= 1; - //rFalseIfx.condition = 1; - genSkipc(&rFalseIfx); - - pic16_emitpLabel(truelbl->key); - - if(ifx) ifx->generated = 1; - return; - // end of if (sign) - } else { - - /* compare word or long to an unsigned literal on the right.*/ - - - size--; - if(lit < 0xff) { - DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit); - switch (lit) { - case 0: - break; /* handled above */ -/* - case 0xff: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - while(size--) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size)); - genSkipz2(&rFalseIfx,0); - break; -*/ - default: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - while(--size) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size)); - - emitSKPZ; - if(rFalseIfx.condition) - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - else - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0)); - - rFalseIfx.condition ^= 1; - genSkipc(&rFalseIfx); - } - - pic16_emitpLabel(truelbl->key); - - if(ifx) ifx->generated = 1; - return; - } - - - lit++; - DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit); - i = (lit >> (size*8)) & 0xff; - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size)); - - while(size--) { - i = (lit >> (size*8)) & 0xff; - - if(i) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i)); - emitSKPNZ; - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size)); - } else { - /* this byte of the lit is zero, - * if it's not the last then OR in the variable */ - if(size) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size)); - } - } - - - pic16_emitpLabel(lbl->key); - - rFalseIfx.condition ^= 1; - - genSkipc(&rFalseIfx); - } - - if(sign) - pic16_emitpLabel(truelbl->key); - if(ifx) ifx->generated = 1; - return; - } - } - /* Compare two variables */ - - DEBUGpic16_emitcode(";sign","%d",sign); - - size--; - if(sign) { - /* Sigh. thus sucks... */ - if(size) { - pCodeOp *pctemp; - - pctemp = pic16_popGetTempReg(1); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size)); - pic16_emitpcode(POC_MOVWF, pctemp); //pic16_pic16_popRegFromIdx(pic16_Gstack_base_addr)); - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80)); - pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr)); - pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size)); - pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr)); - pic16_popReleaseTempReg(pctemp, 1); - } else { - /* Signed char comparison */ - /* Special thanks to Nikolai Golovchenko for this snippet */ - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */ - pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - genSkipc(&rFalseIfx); - - if(ifx) ifx->generated = 1; - return; - } - - } else { - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size)); - } - - - /* The rest of the bytes of a multi-byte compare */ - while (size) { - - emitSKPZ; - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key)); - size--; - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size)); - - - } - - pic16_emitpLabel(lbl->key); - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || - (AOP_TYPE(result) == AOP_REG)) { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0)); - } else { - genSkipc(&rFalseIfx); - } - //genSkipc(&rFalseIfx); - if(ifx) ifx->generated = 1; - - return; - - } - -check_carry: - if ((AOP_TYPE(result) != AOP_CRY) - && AOP_SIZE(result)) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key ); - - pic16_outBitC(result); - } else { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* if the result is used in the next - ifx conditional branch then generate - code a little differently */ - if (ifx ) - genIfxJump (ifx,"c"); - else - pic16_outBitC(result); - /* leave the result in acc */ - } - -} -#endif /* } */ - - -#endif /* } */ - - - -/*-----------------------------------------------------------------*/ -/* genCmpGt :- greater than comparison */ -/*-----------------------------------------------------------------*/ -static void genCmpGt (iCode *ic, iCode *ifx) -{ - operand *left, *right, *result; - sym_link *letype , *retype; - int sign ; - - FENTRY; - - left = IC_LEFT(ic); - right= IC_RIGHT(ic); - result = IC_RESULT(ic); - - letype = getSpec(operandType(left)); - retype =getSpec(operandType(right)); - sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype)); - /* assign the amsops */ - pic16_aopOp (left,ic,FALSE); - pic16_aopOp (right,ic,FALSE); - pic16_aopOp (result,ic,TRUE); - - genCmp(right, left, result, ifx, sign); - - pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(result,NULL,ic,TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genCmpLt - less than comparisons */ -/*-----------------------------------------------------------------*/ -static void genCmpLt (iCode *ic, iCode *ifx) -{ - operand *left, *right, *result; - sym_link *letype , *retype; - int sign ; - - FENTRY; - - left = IC_LEFT(ic); - right= IC_RIGHT(ic); - result = IC_RESULT(ic); - - letype = getSpec(operandType(left)); - retype =getSpec(operandType(right)); - sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype)); - - /* assign the amsops */ - pic16_aopOp (left,ic,FALSE); - pic16_aopOp (right,ic,FALSE); - pic16_aopOp (result,ic,TRUE); - - genCmp(left, right, result, ifx, sign); - - pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(result,NULL,ic,TRUE); -} - -#if 0 -// not needed ATM -// FIXME reenable literal optimisation when the pic16 port is stable - -/*-----------------------------------------------------------------*/ -/* genc16bit2lit - compare a 16 bit value to a literal */ -/*-----------------------------------------------------------------*/ -static void genc16bit2lit(operand *op, int lit, int offset) -{ - int i; - - DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit); - if( (lit&0xff) == 0) - i=1; - else - i=0; - - switch( BYTEofLONG(lit,i)) { - case 0: - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i)); - break; - case 1: - pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i)); - break; - case 0xff: - pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i)); - break; - default: - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i)); - pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i))); - } - - i ^= 1; + i ^= 1; switch( BYTEofLONG(lit,i)) { case 0: @@ -6690,6 +6667,7 @@ static void genCmpEq (iCode *ic, iCode *ifx) int preserve_result = 0; int generate_result = 0; int i=0; + unsigned long lit = -1; FENTRY; @@ -6714,6 +6692,10 @@ static void genCmpEq (iCode *ic, iCode *ifx) left = tmp; } + if (AOP_TYPE(right) == AOP_LIT) { + lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit); + } + if ( regsInCommon(left, result) || regsInCommon(right, result) ) preserve_result = 1; @@ -6726,6 +6708,7 @@ static void genCmpEq (iCode *ic, iCode *ifx) pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i)); } + assert( AOP_SIZE(left) == AOP_SIZE(right) ); for(i=0; i < AOP_SIZE(left); i++) { if(AOP_TYPE(left) != AOP_ACC) @@ -6735,9 +6718,11 @@ static void genCmpEq (iCode *ic, iCode *ifx) else pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i)); } - if(is_LitOp(right)) - pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); - else + if(is_LitOp(right)) { + if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) { + pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); + } + } else pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key)); @@ -7204,7 +7189,7 @@ static void genAndOp (iCode *ic) only those used in arthmetic operations remain */ pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE); pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE); - pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE); + pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); DEBUGpic16_pic16_AopType(__LINE__,left,right,result); @@ -7253,7 +7238,7 @@ static void genOrOp (iCode *ic) only those used in arthmetic operations remain */ pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE); pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE); - pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE); + pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); DEBUGpic16_pic16_AopType(__LINE__,left,right,result); @@ -7476,7 +7461,7 @@ static void genAnd (iCode *ic, iCode *ifx) bp -= 8; ofs++; } - + pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS), pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER)); @@ -7896,13 +7881,13 @@ static void genOr (iCode *ic, iCode *ifx) } else { if (AOP_TYPE(left) == AOP_ACC) { pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset)); - pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); +// pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); } else { pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset)); pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset)); - pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE)); +// pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); +// pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE)); } } @@ -7943,21 +7928,21 @@ static void genOr (iCode *ic, iCode *ifx) pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - pic16_emitcode("movf","%s,w", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - pic16_emitcode("movwf","%s", - pic16_aopGet(AOP(result),offset,FALSE,FALSE)); +// pic16_emitcode("movf","%s,w", +// pic16_aopGet(AOP(left),offset,FALSE,FALSE)); +// pic16_emitcode("movwf","%s", +// pic16_aopGet(AOP(result),offset,FALSE,FALSE)); break; default: pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t)); pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - pic16_emitcode("movlw","0x%x",t); - pic16_emitcode("iorwf","%s,w", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - pic16_emitcode("movwf","%s", - pic16_aopGet(AOP(result),offset,FALSE,FALSE)); +// pic16_emitcode("movlw","0x%x",t); +// pic16_emitcode("iorwf","%s,w", +// pic16_aopGet(AOP(left),offset,FALSE,FALSE)); +// pic16_emitcode("movwf","%s", +// pic16_aopGet(AOP(result),offset,FALSE,FALSE)); } continue; @@ -7967,17 +7952,17 @@ static void genOr (iCode *ic, iCode *ifx) // and better if result is SFR if (AOP_TYPE(left) == AOP_ACC) { pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset)); - pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); +// pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); } else { pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset)); pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset)); - pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - pic16_emitcode("iorwf","%s,w", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); +// pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); +// pic16_emitcode("iorwf","%s,w", +// pic16_aopGet(AOP(left),offset,FALSE,FALSE)); } pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE)); +// pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE)); } } @@ -8241,8 +8226,69 @@ static void genInline (iCode *ic) buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1); strcpy(buffer,IC_INLINE(ic)); + + while((bp1=strstr(bp, "\\n"))) { + *bp1++ = '\n'; + *bp1++ = ' '; + bp = bp1; + } + bp = bp1 = buffer; -// fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer); +#if 0 + /* This is an experimental code for #pragma inline + and is temporarily disabled for 2.5.0 release */ + if(asmInlineMap) + { + symbol *sym; + char *s; + char *cbuf; + int cblen; + + cbuf = Safe_strdup(buffer); + cblen = strlen(buffer)+1; + memset(cbuf, 0, cblen); + + bp = buffer; + bp1 = cbuf; + while(*bp) { + if(*bp != '%')*bp1++ = *bp++; + else { + int i; + + bp++; + i = *bp - '0'; + if(i>elementsInSet(asmInlineMap))break; + + bp++; + s = indexSet(asmInlineMap, i); + DEBUGpc("searching symbol s = `%s'", s); + sym = findSym(SymbolTab, NULL, s); + + if(sym->reqv) { + strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name); + } else { + strcat(bp1, sym->rname); + } + + while(*bp1)bp1++; + } + + if(strlen(bp1) > cblen - 16) { + int i = strlen(cbuf); + cblen += 50; + cbuf = realloc(cbuf, cblen); + memset(cbuf+i, 0, 50); + bp1 = cbuf + i; + } + } + + free(buffer); + buffer = Safe_strdup( cbuf ); + free(cbuf); + + bp = bp1 = buffer; + } +#endif /* 0 */ /* emit each line as a code */ while (*bp) { @@ -8262,6 +8308,11 @@ static void genInline (iCode *ic) * to denote that the argument should not be indented with tab */ pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process bp1 = bp; + } if (*bp == ';') { + /* advance to end of line (prevent splitting of comments at ':' */ + while (*bp && *bp != '\n') { + bp++; + } // while } else bp++; } @@ -8290,7 +8341,7 @@ static void genRRC (iCode *ic) left = IC_LEFT(ic); result=IC_RESULT(ic); pic16_aopOp (left,ic,FALSE); - pic16_aopOp (result,ic,FALSE); + pic16_aopOp (result,ic,TRUE); DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); @@ -8335,7 +8386,7 @@ static void genRLC (iCode *ic) left = IC_LEFT(ic); result=IC_RESULT(ic); pic16_aopOp (left,ic,FALSE); - pic16_aopOp (result,ic,FALSE); + pic16_aopOp (result,ic,TRUE); DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); @@ -8442,7 +8493,7 @@ static void AccRol (int shCount) /*-----------------------------------------------------------------*/ /* AccLsh - left shift accumulator by known count */ /*-----------------------------------------------------------------*/ -static void AccLsh (int shCount) +static void AccLsh (int shCount, int doMask) { DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); switch(shCount){ @@ -8475,8 +8526,10 @@ static void AccLsh (int shCount) pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); break; } - - pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount])); + if (doMask) { + /* no masking is required in genPackBits */ + pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount])); + } } /*-----------------------------------------------------------------*/ @@ -8641,7 +8694,7 @@ static void shiftR1Left2ResultSigned (operand *left, int offl, } else { pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr)); pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr)); pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER)); } @@ -8656,7 +8709,7 @@ static void shiftR1Left2ResultSigned (operand *left, int offl, } else { pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr)); pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr)); } default: @@ -8773,7 +8826,7 @@ static void shiftL1Left2Result (operand *left, int offl, // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE); // MOVA(l); /* shift left accumulator */ - //AccLsh(shCount); // don't comment out just yet... + //AccLsh(shCount, 1); // don't comment out just yet... // pic16_aopPut(AOP(result),"a",offr); switch(shCount) { @@ -9144,7 +9197,7 @@ static void shiftLLeftOrResult (operand *left, int offl, pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl)); /* shift left accumulator */ - AccLsh(shCount); + AccLsh(shCount, 1); /* or with result */ /* back to result */ pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr)); @@ -9362,7 +9415,7 @@ void pic16_genLeftShiftLiteral (operand *left, operand *result, iCode *ic) { - int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit); + int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit)); int size; FENTRY; @@ -9370,7 +9423,7 @@ void pic16_genLeftShiftLiteral (operand *left, pic16_freeAsmop(right,NULL,ic,TRUE); pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,FALSE); + pic16_aopOp(result,ic,TRUE); size = getSize(operandType(result)); @@ -9437,6 +9490,8 @@ static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian) } } + +#if !(USE_GENERIC_SIGNED_SHIFT) /*-----------------------------------------------------------------*/ /* genLeftShift - generates code for left shifting */ /*-----------------------------------------------------------------*/ @@ -9494,7 +9549,7 @@ static void genLeftShift (iCode *ic) #endif { /* we don't know if left is a literal or a register, take care -- VR */ - mov2f(AOP(result), AOP(left), offset); + pic16_mov2f(AOP(result), AOP(left), offset); } offset++; } @@ -9526,7 +9581,7 @@ static void genLeftShift (iCode *ic) #if 1 /* this is already done, why change it? */ if (!pic16_sameRegs(AOP(left),AOP(result))) { - mov2f(AOP(result), AOP(left), 0); + pic16_mov2f(AOP(result), AOP(left), 0); } #endif @@ -9618,7 +9673,7 @@ static void genLeftShift (iCode *ic) pic16_freeAsmop(left,NULL,ic,TRUE); pic16_freeAsmop(result,NULL,ic,TRUE); } - +#endif #if 0 @@ -9677,7 +9732,7 @@ static void genLeftShift (iCode *ic) } else { /* we don't know if left is a literal or a register, take care -- VR */ - mov2f(AOP(result), AOP(left), offset); + pic16_mov2f(AOP(result), AOP(left), offset); } offset++; } @@ -9706,7 +9761,7 @@ static void genLeftShift (iCode *ic) tlbl = newiTempLabel(NULL); if (!pic16_sameRegs(AOP(left),AOP(result))) { - mov2f(AOP(result), AOP(left), 0); + pic16_mov2f(AOP(result), AOP(left), 0); // pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); // pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); @@ -9828,12 +9883,7 @@ static void genrshTwo (operand *result,operand *left, else movLeft2Result(left, MSB16, result, LSB); - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16)); - - if(sign) { - pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16)); - } + pic16_addSign (result, 1, sign); } /* 1 <= shCount <= 7 */ @@ -9970,13 +10020,13 @@ static void genRightShiftLiteral (operand *left, iCode *ic, int sign) { - int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit); + int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit)); int lsize,res_size; pic16_freeAsmop(right,NULL,ic,TRUE); pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,FALSE); + pic16_aopOp(result,ic,TRUE); DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left)); @@ -9991,8 +10041,10 @@ static void genRightShiftLiteral (operand *left, /* I suppose that the left size >= result size */ if(shCount == 0){ - while(res_size--) - movLeft2Result(left, lsize, result, res_size); + assert (res_size <= lsize); + while (res_size--) { + pic16_mov2f (AOP(result), AOP(left), res_size); + } // for } else if(shCount >= (lsize * 8)){ @@ -10001,7 +10053,7 @@ static void genRightShiftLiteral (operand *left, pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB)); if(sign) { pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB)); + pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB)); } } else { @@ -10042,6 +10094,7 @@ static void genRightShiftLiteral (operand *left, pic16_freeAsmop(result,NULL,ic,TRUE); } +#if !(USE_GENERIC_SIGNED_SHIFT) /*-----------------------------------------------------------------*/ /* genSignedRightShift - right shift of signed number */ /*-----------------------------------------------------------------*/ @@ -10182,7 +10235,10 @@ static void genSignedRightShift (iCode *ic) pic16_freeAsmop(result,NULL,ic,TRUE); pic16_freeAsmop(right,NULL,ic,TRUE); } +#endif +#if !(USE_GENERIC_SIGNED_SHIFT) +#warning This implementation of genRightShift() is incomplete! /*-----------------------------------------------------------------*/ /* genRightShift - generate code for right shifting */ /*-----------------------------------------------------------------*/ @@ -10299,11 +10355,247 @@ release: pic16_freeAsmop (right,NULL,ic,TRUE); pic16_freeAsmop(result,NULL,ic,TRUE); } +#endif + +#if (USE_GENERIC_SIGNED_SHIFT) +/*-----------------------------------------------------------------*/ +/* genGenericShift - generates code for left or right shifting */ +/*-----------------------------------------------------------------*/ +static void genGenericShift (iCode *ic, int isShiftLeft) { + operand *left,*right, *result; + int offset; + int sign, signedCount; + symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative; + PIC_OPCODE pos_shift, neg_shift; + + FENTRY; + + right = IC_RIGHT(ic); + left = IC_LEFT(ic); + result = IC_RESULT(ic); + + pic16_aopOp(right,ic,FALSE); + pic16_aopOp(left,ic,FALSE); + pic16_aopOp(result,ic,TRUE); + + sign = !SPEC_USIGN(operandType (left)); + signedCount = !SPEC_USIGN(operandType (right)); + + /* if the shift count is known then do it + as efficiently as possible */ + if (AOP_TYPE(right) == AOP_LIT) { + long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit); + if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; } + // we should modify right->aopu.aop_lit here! + // Instead we use abs(shCount) in genXXXShiftLiteral()... + // lit > 8*size is handled in pic16_genXXXShiftLiteral() + if (isShiftLeft) + pic16_genLeftShiftLiteral (left,right,result,ic); + else + genRightShiftLiteral (left,right,result,ic, sign); + + goto release; + } // if (right is literal) + + /* shift count is unknown then we have to form a loop. + * Note: we take only the lower order byte since shifting + * more than 32 bits make no sense anyway, ( the + * largest size of an object can be only 32 bits ) + * Note: we perform arithmetic shifts if the left operand is + * signed and we do an (effective) right shift, i. e. we + * shift in the sign bit from the left. */ + + label_complete = newiTempLabel ( NULL ); + label_loop_pos = newiTempLabel ( NULL ); + label_loop_neg = NULL; + label_negative = NULL; + pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF; + neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF; + + if (signedCount) { + // additional labels needed + label_loop_neg = newiTempLabel ( NULL ); + label_negative = newiTempLabel ( NULL ); + } // if + + // copy source to result -- this will effectively truncate the left operand to the size of result! + // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20) + // This is fine, as it only occurs for left shifting with negative count which is not standardized! + for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) { + pic16_mov2f (AOP(result),AOP(left), offset); + } // for + + // if result is longer than left, fill with zeros (or sign) + if (AOP_SIZE(left) < AOP_SIZE(result)) { + if (sign && AOP_SIZE(left) > 0) { + // shift signed operand -- fill with sign + pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg)); + pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7)); + pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF)); + for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) { + pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset)); + } // for + } else { + // shift unsigned operand -- fill result with zeros + for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) { + pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset)); + } // for + } + } // if (size mismatch) + + pic16_mov2w (AOP(right), 0); + pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key)); + if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key)); + +#if 0 + // perform a shift by one (shift count is positive) + // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0: + // 2n+[2,3]+({1,3}+n+3)c-2+[0,2]=({4,6}+n)c+2n+[0,3] ({5,7}c+[2,5] / {6,8}c+[4, 7] / {8,10}c+[ 8,11]) + pic16_emitpLabel (label_loop_pos->key); + emitCLRC; + if (sign && (pos_shift == POC_RRCF)) { + pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7)); + emitSETC; + } // if + genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF); + pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg)); + pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key)); +#else + // perform a shift by one (shift count is positive) + // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0: + // 2n+[2,3]+2+({0,2}+n+3)c-1+[0,2]=({3,5}+n)c+2n+[3,6] ({4,6}c+[5,8] / {5,7}c+[7,10] / {7, 9}c+[11,14]) + // This variant is slower for 0key); + if (sign && (pos_shift == POC_RRCF)) { + pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7)); + emitSETC; + } // if + genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF); + //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this... + pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01)); + pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key)); +#endif + + if (signedCount) { + pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key)); + + pic16_emitpLabel (label_negative->key); + // perform a shift by -1 (shift count is negative) + // 2n+4+1+({0,2}+n+3)*c-1=({3,5}+n)c+2n+4 ({4,6}c+6 / {5,7}c+8 / {7,9}c+12) + emitCLRC; + pic16_emitpLabel (label_loop_neg->key); + if (sign && (neg_shift == POC_RRCF)) { + pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7)); + emitSETC; + } // if + genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF); + //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this... + pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01)); + pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key)); + } // if (signedCount) + + pic16_emitpLabel (label_complete->key); + +release: + pic16_freeAsmop (right,NULL,ic,TRUE); + pic16_freeAsmop(left,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); +} + +static void genLeftShift (iCode *ic) { + genGenericShift (ic, 1); +} + +static void genRightShift (iCode *ic) { + genGenericShift (ic, 0); +} +#endif + +/* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */ +void pic16_loadFSR0(operand *op, int lit) +{ + if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) { + if (AOP_TYPE(op) == AOP_LIT) { + /* handle 12 bit integers correctly */ + unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit); + if ((val & 0x0fff) != val) { + fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n", + val, (val & 0x0fff) ); + val &= 0x0fff; + } + pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val))); + } else { + pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0))); + } + } else { + assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat); + // set up FSR0 with address of result + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l))); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h))); + } +} -void pic16_loadFSR0(operand *op) +/*----------------------------------------------------------------*/ +/* pic16_derefPtr - move one byte from the location ptr points to */ +/* to WREG (doWrite == 0) or one byte from WREG */ +/* to the location ptr points to (doWrite != 0) */ +/*----------------------------------------------------------------*/ +static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup) { - pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0))); + if (!IS_PTR(operandType(ptr))) + { + if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0)); + else pic16_mov2w (AOP(ptr), 0); + return; + } + + //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr)))); + /* We might determine pointer type right here: */ + p_type = DCL_TYPE(operandType(ptr)); + + switch (p_type) { + case FPOINTER: + case POINTER: + if (!fsr0_setup || !*fsr0_setup) + { + pic16_loadFSR0( ptr, 0 ); + if (fsr0_setup) *fsr0_setup = 1; + } + if (doWrite) + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0)); + else + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); + break; + + case GPOINTER: + if (AOP(ptr)->aopu.aop_reg[2]) { + if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec)); + // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?) + mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0); + mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1); + pic16_mov2w(AOP(ptr), 2); + pic16_callGenericPointerRW(doWrite, 1); + } else { + // data pointer (just 2 byte given) + if (!fsr0_setup || !*fsr0_setup) + { + pic16_loadFSR0( ptr, 0 ); + if (fsr0_setup) *fsr0_setup = 1; + } + if (doWrite) + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0)); + else + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); + } + break; + + default: + assert (0 && "invalid pointer type specified"); + break; + } } /*-----------------------------------------------------------------*/ @@ -10312,182 +10604,124 @@ void pic16_loadFSR0(operand *op) static void genUnpackBits (operand *result, operand *left, char *rname, int ptype) { int shCnt ; - int rlen = 0 ; sym_link *etype, *letype; int blen=0, bstr=0; int lbstr; - int offset = 0 ; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - etype = getSpec(operandType(result)); - letype = getSpec(operandType(left)); - -// if(IS_BITFIELD(etype)) { - blen = SPEC_BLEN(etype); - bstr = SPEC_BSTR(etype); -// } - - lbstr = SPEC_BSTR( letype ); + int same; + pCodeOp *op; -#if 1 - if((blen == 1) && (bstr < 8)) { - /* it is a single bit, so use the appropriate bit instructions */ - DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + etype = getSpec(operandType(result)); + letype = getSpec(operandType(left)); - pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg)); - - if((ptype == POINTER) && (result)) { - /* workaround to reduce the extra lfsr instruction */ - pic16_emitpcode(POC_BTFSC, - pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr)); - } else { - pic16_emitpcode(POC_BTFSC, - pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr)); - } - - pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg)); + // if(IS_BITFIELD(etype)) { + blen = SPEC_BLEN(etype); + bstr = SPEC_BSTR(etype); + // } - pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 )); - return; - } + lbstr = SPEC_BSTR( letype ); -#endif + DEBUGpic16_emitcode ("; ***","%s %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__, + SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed"); - /* the following call to pic16_loadFSR0 is temporary until - * optimization to handle single bit assignments is added - * to the function. Until then use the old safe way! -- VR */ - pic16_loadFSR0( left ); - - /* read the first byte */ - switch (ptype) { - case POINTER: - case IPOINTER: - case PPOINTER: - case FPOINTER: - case GPOINTER: - pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); - break; - case CPOINTER: - pic16_emitcode("clr","a"); - pic16_emitcode("movc","a","@a+dptr"); - break; - } - +#if 1 + if((blen == 1) && (bstr < 8) + && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) { + /* it is a single bit, so use the appropriate bit instructions */ + DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__); + + same = pic16_sameRegs(AOP(left),AOP(result)); + op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0)); + pic16_emitpcode(POC_CLRF, op); + + if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) { + /* workaround to reduce the extra lfsr instruction */ + pic16_emitpcode(POC_BTFSC, + pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr)); + } else { + assert (PIC_IS_DATA_PTR (operandType(left))); + pic16_loadFSR0 (left, 0); + pic16_emitpcode(POC_BTFSC, + pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr)); + } - /* if we have bitdisplacement then it fits */ - /* into this byte completely or if length is */ - /* less than a byte */ - if ((shCnt = SPEC_BSTR(etype)) || - (SPEC_BLEN(etype) <= 8)) { + if (SPEC_USIGN(OP_SYM_ETYPE(left))) { + /* unsigned bitfields result in either 0 or 1 */ + pic16_emitpcode(POC_INCF, op); + } else { + /* signed bitfields result in either 0 or -1 */ + pic16_emitpcode(POC_DECF, op); + } + if (same) { + pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 )); + } - /* shift right acc */ - AccRsh(shCnt, 0); + pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result))); + return; + } - pic16_emitpcode(POC_ANDLW, pic16_popGetLit( - (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ])); +#endif -/* VR -- normally I would use the following, but since we use the hack, - * to avoid the masking from AccRsh, why not mask it right now? */ + if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) { + // access symbol directly + pic16_mov2w (AOP(left), 0); + } else { + pic16_derefPtr (left, ptype, 0, NULL); + } -/* - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype)))); -*/ + /* if we have bitdisplacement then it fits */ + /* into this byte completely or if length is */ + /* less than a byte */ + if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8)) { - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); - return ; - } + /* shift right acc */ + AccRsh(shCnt, 0); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit( + (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ])); + /* VR -- normally I would use the following, but since we use the hack, + * to avoid the masking from AccRsh, why not mask it right now? */ - fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n"); - fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n"); - exit(-1); + /* + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype)))); + */ - /* bit field did not fit in a byte */ - rlen = SPEC_BLEN(etype) - 8; - pic16_aopPut(AOP(result),"a",offset++); + /* extend signed bitfields to 8 bits */ + if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8)) + { + assert (blen + bstr > 0); + pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1)); + pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen))); + } - while (1) { + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); - switch (ptype) { - case POINTER: - case IPOINTER: - pic16_emitcode("inc","%s",rname); - pic16_emitcode("mov","a,@%s",rname); - break; - - case PPOINTER: - pic16_emitcode("inc","%s",rname); - pic16_emitcode("movx","a,@%s",rname); - break; + pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result))); + return ; + } - case FPOINTER: - pic16_emitcode("inc","dptr"); - pic16_emitcode("movx","a,@dptr"); - break; - - case CPOINTER: - pic16_emitcode("clr","a"); - pic16_emitcode("inc","dptr"); - pic16_emitcode("movc","a","@a+dptr"); - break; - - case GPOINTER: - pic16_emitcode("inc","dptr"); - pic16_emitcode("lcall","__gptrget"); - break; - } + fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n"); + fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n"); + exit(-1); - rlen -= 8; - /* if we are done */ - if ( rlen <= 0 ) - break ; - - pic16_aopPut(AOP(result),"a",offset++); - - } - - if (rlen) { - pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen)); - pic16_aopPut(AOP(result),"a",offset); - } - - return ; + return ; } -static void genDataPointerGet(operand *left, - operand *result, - iCode *ic) +static void genDataPointerGet(operand *left, operand *result, iCode *ic) { int size, offset = 0, leoffset=0 ; DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_aopOp(result, ic, FALSE); + pic16_aopOp(result, ic, TRUE); + + FENTRY; size = AOP_SIZE(result); // fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size); -#if 0 - /* The following tests may save a redudant movff instruction when - * accessing unions */ - - /* if they are the same */ - if (operandsEqu (left, result)) { - DEBUGpic16_emitcode("; ***", "left and result operands are equ/same"); - goto release; - } -#endif - -#if 0 - /* if they are the same registers */ - if (pic16_sameRegs(AOP(left),AOP(result))) { - DEBUGpic16_emitcode("; ***", "left and result registers are same"); - goto release; - } -#endif - #if 1 if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE), pic16_aopGet(AOP(left), 0, TRUE, FALSE))) { @@ -10496,17 +10730,6 @@ static void genDataPointerGet(operand *left, } #endif - -#if 0 - if ( AOP_TYPE(left) == AOP_PCODE) { - fprintf(stderr,"genDataPointerGet %s, %d\n", - AOP(left)->aopu.pcop->name, - (AOP(left)->aopu.pcop->type == PO_DIR)? - PCOR(AOP(left)->aopu.pcop)->instance: - PCOI(AOP(left)->aopu.pcop)->offset); - } -#endif - if(AOP(left)->aopu.pcop->type == PO_DIR) leoffset=PCOR(AOP(left)->aopu.pcop)->instance; @@ -10515,8 +10738,8 @@ static void genDataPointerGet(operand *left, while (size--) { DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset); - if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE - || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) { +// pic16_DumpOp("(result)",result); + if(is_LitAOp(AOP(result))) { pic16_mov2w(AOP(left), offset); // patch 8 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); } else { @@ -10542,15 +10765,17 @@ static void genNearPointerGet (operand *left, operand *result, iCode *ic) { - asmop *aop = NULL; +// asmop *aop = NULL; //regs *preg = NULL ; sym_link *rtype, *retype; - sym_link *ltype = operandType(left); + sym_link *ltype, *letype; FENTRY; rtype = operandType(result); retype= getSpec(rtype); + ltype = operandType(left); + letype= getSpec(ltype); pic16_aopOp(left,ic,FALSE); @@ -10572,35 +10797,53 @@ static void genNearPointerGet (operand *left, } DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + pic16_aopOp (result,ic,TRUE); + + DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result); - /* if the value is already in a pointer register - * then don't need anything more */ - if (!AOP_INPREG(AOP(left))) { - /* otherwise get a free pointer register */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - /* VR -- the whole concept is to load FSR0 with the address of the symbol */ - /* bitfields will be handled by genUnpackBits */ - if(!IS_BITFIELD(retype)) { +#if 1 + if(IS_BITFIELD( retype ) + && (SPEC_BLEN(operandType(result))==1) + ) { + iCode *nextic; + pCodeOp *jop; + int bitstrt, bytestrt; + + /* if this is bitfield of size 1, see if we are checking the value + * of a single bit in an if-statement, + * if yes, then don't generate usual code, but execute the + * genIfx directly -- VR */ + + nextic = ic->next; + + /* CHECK: if next iCode is IFX + * and current result operand is nextic's conditional operand + * and current result operand live ranges ends at nextic's key number + */ + if((nextic->op == IFX) + && (result == IC_COND(nextic)) + && (OP_LIVETO(result) == nextic->seq) + && (OP_SYMBOL(left)->remat) // below fails for "if (p->bitfield)" + ) { + /* everything is ok then */ + /* find a way to optimize the genIfx iCode */ + + bytestrt = SPEC_BSTR(operandType(result))/8; + bitstrt = SPEC_BSTR(operandType(result))%8; + + jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt); - if(is_LitAOp( AOP(left) )) { - pic16_loadFSR0( left ); - } else { - // set up FSR0 with address from left - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10 - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10 + genIfxpCOpJump(nextic, jop); + + pic16_freeAsmop(left, NULL, ic, TRUE); + pic16_freeAsmop(result, NULL, ic, TRUE); + return; } - } } -// else -// rname = pic16_aopGet(AOP(left),0,FALSE,FALSE); - - pic16_aopOp (result,ic,FALSE); - - DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result); +#endif /* if bitfield then unpack the bits */ - if (IS_BITFIELD(retype)) + if (IS_BITFIELD(letype)) genUnpackBits (result, left, NULL, POINTER); else { /* we have can just get the values */ @@ -10609,11 +10852,8 @@ static void genNearPointerGet (operand *left, DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* fsr0 is loaded already -- VR */ -// pic16_loadFSR0( left ); + pic16_loadFSR0( left, 0 ); -// pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0)); -// pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0)); while(size--) { if(size) { pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), @@ -10623,29 +10863,9 @@ static void genNearPointerGet (operand *left, pic16_popGet(AOP(result), offset++))); } } -#if 0 -// pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0)); -// pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++)); - if(size) - pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0)); -#endif -/* - while (size--) { - if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) { - - pic16_emitcode("mov","a,@%s",rname); - pic16_aopPut(AOP(result),"a",offset); - } else { - sprintf(buffer,"@%s",rname); - pic16_aopPut(AOP(result),buffer,offset); - } - offset++ ; - if (size) - pic16_emitcode("inc","%s",rname); - } -*/ } +#if 0 /* now some housekeeping stuff */ if (aop) { /* we had to allocate for this iCode */ @@ -10667,6 +10887,7 @@ static void genNearPointerGet (operand *left, // pic16_emitcode("dec","%s",rname); } } +#endif /* done */ pic16_freeAsmop(left,NULL,ic,TRUE); @@ -10706,7 +10927,7 @@ static void genPagedPointerGet (operand *left, rname = pic16_aopGet(AOP(left),0,FALSE,FALSE); pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_aopOp (result,ic,FALSE); + pic16_aopOp (result,ic,TRUE); /* if bitfield then unpack the bits */ if (IS_BITFIELD(retype)) @@ -10754,6 +10975,10 @@ static void genPagedPointerGet (operand *left, } +#if 0 +/* This code is not adjusted to PIC16 and fails utterly. + * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */ + /*-----------------------------------------------------------------*/ /* genFarPointerGet - gget value from far space */ /*-----------------------------------------------------------------*/ @@ -10784,7 +11009,7 @@ static void genFarPointerGet (operand *left, } /* so dptr know contains the address */ pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_aopOp(result,ic,FALSE); + pic16_aopOp(result,ic,TRUE); /* if bit then unpack */ if (IS_BITFIELD(retype)) @@ -10803,6 +11028,8 @@ static void genFarPointerGet (operand *left, pic16_freeAsmop(result,NULL,ic,TRUE); } +#endif + #if 0 /*-----------------------------------------------------------------*/ /* genCodePointerGet - get value from code space */ @@ -10855,6 +11082,7 @@ static void genCodePointerGet (operand *left, pic16_freeAsmop(result,NULL,ic,TRUE); } #endif + #if 0 /*-----------------------------------------------------------------*/ /* genGenPointerGet - gget value from generic pointer space */ @@ -10896,7 +11124,7 @@ static void genGenPointerGet (operand *left, // set up FSR0 with address from left pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); - + offset = 0 ; while(size--) { @@ -10929,15 +11157,20 @@ static void genGenPointerGet (operand *left, operand *result, iCode *ic) { int size, offset, lit; - sym_link *retype = getSpec(operandType(result)); - char fgptrget[32]; + sym_link *letype = getSpec(operandType(left)); DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,FALSE); + pic16_aopOp(result,ic,TRUE); size = AOP_SIZE(result); DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); + + /* if bit then unpack */ + if (IS_BITFIELD(letype)) { + genUnpackBits(result,left,"BAD",GPOINTER); + goto release; + } if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!) @@ -10962,41 +11195,16 @@ static void genGenPointerGet (operand *left, } else { /* we need to get it byte by byte */ /* set up WREG:PRODL:FSR0L with address from left */ - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl))); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2)); - - switch( size ) { - case 1: strcpy(fgptrget, "__gptrget1"); break; - case 2: strcpy(fgptrget, "__gptrget2"); break; - case 3: strcpy(fgptrget, "__gptrget3"); break; - case 4: strcpy(fgptrget, "__gptrget4"); break; - default: - werror(W_POSSBUG2, __FILE__, __LINE__); - abort(); - } - - pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget )); + mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0); + mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1); + pic16_mov2w(AOP(left), 2); + pic16_callGenericPointerRW(0, size); assignResultValue(result, 1); - { - symbol *sym; - - sym = newSymbol( fgptrget, 0 ); - strcpy(sym->rname, fgptrget); - checkAddSym(&externs, sym); - -// fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fgptrget); - } - goto release; } - /* if bit then unpack */ - if (IS_BITFIELD(retype)) - genUnpackBits(result,left,"BAD",GPOINTER); - release: pic16_freeAsmop(left,NULL,ic,TRUE); pic16_freeAsmop(result,NULL,ic,TRUE); @@ -11023,29 +11231,11 @@ static void genConstPointerGet (operand *left, DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__); -#if 0 // patch 15 - pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key)); - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key)); - pic16_emitpLabel(albl->key); - - poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW); - - /* this performs a goto to the specified address -- Why not to use pointer? -- VR */ - pic16_emitpcode(poc,pic16_popGet(AOP(left),1)); - pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath)); - pic16_emitpcode(poc,pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl)); - - pic16_emitpLabel(blbl->key); - - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0)); -#endif // patch 15 - // set up table pointer if( (AOP_TYPE(left) == AOP_PCODE) && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE) - || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 15 ...... + || (AOP(left)->aopu.pcop->type == PO_DIR))) { pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0)); pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl)); @@ -11053,25 +11243,20 @@ static void genConstPointerGet (operand *left, pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh)); pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2)); pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru)); - } - else - { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru))); - } - + } else { + mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0); + mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1); + mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2); + } - while(size--) - { - pic16_emitpcodeNULLop(POC_TBLRD_POSTINC); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset))); - offset++; - } + while(size--) { + pic16_emitpcodeNULLop(POC_TBLRD_POSTINC); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset))); + offset++; + } pic16_freeAsmop(left,NULL,ic,TRUE); pic16_freeAsmop(result,NULL,ic,TRUE); - } @@ -11080,9 +11265,9 @@ static void genConstPointerGet (operand *left, /*-----------------------------------------------------------------*/ static void genPointerGet (iCode *ic) { - operand *left, *result ; - sym_link *type, *etype; - int p_type; + operand *left, *result ; + sym_link *type, *etype; + int p_type; FENTRY; @@ -11103,57 +11288,61 @@ static void genPointerGet (iCode *ic) /* if left is of type of pointer then it is simple */ if (IS_PTR(type) && !IS_FUNC(type->next)) - p_type = DCL_TYPE(type); + p_type = DCL_TYPE(type); else { - /* we have to go by the storage class */ - p_type = PTR_TYPE(SPEC_OCLS(etype)); + /* we have to go by the storage class */ + p_type = PTR_TYPE(SPEC_OCLS(etype)); - DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__); + DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__); - if (SPEC_OCLS(etype)->codesp ) { - DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__); - //p_type = CPOINTER ; - } - else - if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) - DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__); - /*p_type = FPOINTER ;*/ - else - if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) - DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__); -/* p_type = PPOINTER; */ - else - if (SPEC_OCLS(etype) == idata ) - DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__); -/* p_type = IPOINTER; */ - else - DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__); -/* p_type = POINTER ; */ + if (SPEC_OCLS(etype)->codesp ) { + DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__); + //p_type = CPOINTER ; + } else + if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) { + DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__); + /*p_type = FPOINTER ;*/ + } else + if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) { + DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__); + /* p_type = PPOINTER; */ + } else + if (SPEC_OCLS(etype) == idata ) { + DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__); + /* p_type = IPOINTER; */ + } else { + DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__); + /* p_type = POINTER ; */ + } } /* now that we have the pointer type we assign the pointer values */ switch (p_type) { - - case POINTER: - case IPOINTER: + case POINTER: + case FPOINTER: + case IPOINTER: genNearPointerGet (left,result,ic); break; - case PPOINTER: + case PPOINTER: genPagedPointerGet(left,result,ic); break; - case FPOINTER: +#if 0 + /* PICs do not support FAR pointers... */ + /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */ + case FPOINTER: genFarPointerGet (left,result,ic); break; +#endif - case CPOINTER: + case CPOINTER: genConstPointerGet (left,result,ic); //pic16_emitcodePointerGet (left,result,ic); break; - case GPOINTER: + case GPOINTER: #if 0 if (IS_PTR_CONST(type)) genConstPointerGet (left,result,ic); @@ -11167,7 +11356,6 @@ static void genPointerGet (iCode *ic) "genPointerGet: illegal pointer type"); } - } /*-----------------------------------------------------------------*/ @@ -11181,210 +11369,243 @@ static void genPackBits (sym_link *etype , operand *result, int offset = 0 ; int rLen = 0 ; int blen, bstr ; + int shifted_and_masked = 0; + unsigned long lit = (unsigned long)-1; sym_link *retype; - char *l ; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - blen = SPEC_BLEN(etype); - bstr = SPEC_BSTR(etype); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + blen = SPEC_BLEN(etype); + bstr = SPEC_BSTR(etype); - retype = getSpec(operandType(right)); + retype = getSpec(operandType(right)); - if(AOP_TYPE(right) == AOP_LIT) { - if((blen == 1) && (bstr < 8)) { - unsigned long lit; - /* it is a single bit, so use the appropriate bit instructions */ + if(AOP_TYPE(right) == AOP_LIT) { + lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); + + if((blen == 1) && (bstr < 8)) { + /* it is a single bit, so use the appropriate bit instructions */ - DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__); + DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__); - lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); -// pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); - if((p_type == POINTER) && (result)) { - /* workaround to reduce the extra lfsr instruction */ - if(lit) { - pic16_emitpcode(POC_BSF, - pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr)); - } else { - pic16_emitpcode(POC_BCF, - pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr)); - } - } else { - pic16_loadFSR0( result ); - if(lit) { - pic16_emitpcode(POC_BSF, - pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr)); - } else { - pic16_emitpcode(POC_BCF, - pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr)); - } - } - - return; - } + if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) { + /* workaround to reduce the extra lfsr instruction */ + if(lit) { + pic16_emitpcode(POC_BSF, + pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr)); + } else { + pic16_emitpcode(POC_BCF, + pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr)); + } + } else { + if (PIC_IS_DATA_PTR(operandType(result))) { + pic16_loadFSR0(result, 0); + pic16_emitpcode(lit ? POC_BSF : POC_BCF, + pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr)); + } else { + /* get old value */ + pic16_derefPtr (result, p_type, 0, NULL); + pic16_emitpcode(lit ? POC_BSF : POC_BCF, + pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr)); + /* write back new value */ + pic16_derefPtr (result, p_type, 1, NULL); + } + } - pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0)); - offset++; - } else - if(IS_BITFIELD(retype) - && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR) - && (blen == 1)) { - int rblen, rbstr; + return; + } + /* IORLW below is more efficient */ + //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr)); + lit = (lit & ((1UL << blen) - 1)) << bstr; + shifted_and_masked = 1; + offset++; + } else + if (IS_DIRECT(result) && !IS_PTR(operandType(result)) + && IS_BITFIELD(retype) + && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR) + && (blen == 1)) { + int rblen, rbstr; + + rblen = SPEC_BLEN( retype ); + rbstr = SPEC_BSTR( retype ); + + if(IS_BITFIELD(etype)) { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0)); + pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr)); + } else { + pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg)); + } - rblen = SPEC_BLEN( retype ); - rbstr = SPEC_BSTR( retype ); - + pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr)); - if(IS_BITFIELD(etype)) { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0)); - pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr)); - } else { - pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg)); - } - - pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr)); - - if(IS_BITFIELD(etype)) { - pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr)); - } else { - pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg)); - } + if(IS_BITFIELD(etype)) { + pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr)); + } else { + pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg)); + } - pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0)); - - return; - } else - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++)); + pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0)); - /* if the bit lenth is less than or */ - /* it exactly fits a byte then */ - if((shCnt=SPEC_BSTR(etype)) - || SPEC_BLEN(etype) <= 8 ) { + return; + } else { + /* move right to W */ + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++)); + } - pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1)); + /* if the bit length is less than or */ + /* it exactly fits a byte then */ + if((shCnt=SPEC_BSTR(etype)) + || SPEC_BLEN(etype) <= 8 ) { + int fsr0_setup = 0; - /* shift left acc */ - AccLsh(shCnt); + if (blen != 8 || bstr != 0) { + // we need to combine the value with the old value + if(!shifted_and_masked) + { + pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1)); - /* using PRODL as a temporary register here */ - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl)); + DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt, + SPEC_BSTR(etype), SPEC_BLEN(etype)); - switch (p_type) { - case FPOINTER: - case POINTER: - pic16_loadFSR0( result ); - pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); -// pic16_emitcode ("mov","b,a"); -// pic16_emitcode("mov","a,@%s",rname); - break; + /* shift left acc, do NOT mask the result again */ + AccLsh(shCnt, 0); - case GPOINTER: - werror(W_POSSBUG2, __FILE__, __LINE__); - break; + /* using PRODH as a temporary register here */ + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh)); + } - } + if ((IS_SYMOP(result) && !IS_PTR(operandType (result))) + || IS_DIRECT(result)) { + /* access symbol directly */ + pic16_mov2w (AOP(result), 0); + } else { + /* get old value */ + pic16_derefPtr (result, p_type, 0, &fsr0_setup); + } #if 1 - pic16_emitpcode(POC_ANDLW, pic16_popGetLit( - (unsigned char)((unsigned char)(0xff << (blen+bstr)) | - (unsigned char)(0xff >> (8-bstr))) )); - pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl)); - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0)); -#endif - - return; - } + pic16_emitpcode(POC_ANDLW, pic16_popGetLit( + (unsigned char)((unsigned char)(0xff << (blen+bstr)) | + (unsigned char)(0xff >> (8-bstr))) )); + if (!shifted_and_masked) { + pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh)); + } else { + /* We have the shifted and masked (literal) right value in `lit' */ + if (lit != 0) + pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit)); + } + } // if (blen != 8 || bstr != 0) + /* write new value back */ + if ((IS_SYMOP(result) && !IS_PTR(operandType(result))) + || IS_DIRECT(result)) { + pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0)); + } else { + pic16_derefPtr (result, p_type, 1, &fsr0_setup); + } +#endif - fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n"); - fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n"); - exit(-1); + return; + } - /* if we r done */ - if ( SPEC_BLEN(etype) <= 8 ) - return ; +#if 0 + fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n"); + fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n"); + exit(-1); +#endif - pic16_emitcode("inc","%s",rname); - rLen = SPEC_BLEN(etype) ; + pic16_loadFSR0(result, 0); // load FSR0 with address of result + rLen = SPEC_BLEN(etype)-8; + /* now generate for lengths greater than one byte */ + while (1) { + rLen -= 8 ; + if (rLen <= 0 ) { + mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset); + break ; + } - /* now generate for lengths greater than one byte */ - while (1) { + switch (p_type) { + case POINTER: + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0)); + break; - l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE); + /* + case FPOINTER: + MOVA(l); + pic16_emitcode("movx","@dptr,a"); + break; + + case GPOINTER: + MOVA(l); + DEBUGpic16_emitcode(";lcall","__gptrput"); + break; + */ + default: + assert(0); + } - rLen -= 8 ; - if (rLen <= 0 ) - break ; - switch (p_type) { - case POINTER: - if (*l == '@') { - MOVA(l); - pic16_emitcode("mov","@%s,a",rname); - } else - pic16_emitcode("mov","@%s,%s",rname,l); - break; + pic16_mov2w(AOP(right), offset++); + } - case FPOINTER: - MOVA(l); - pic16_emitcode("movx","@dptr,a"); - break; + /* last last was not complete */ + if (rLen) { + /* save the byte & read byte */ + switch (p_type) { + case POINTER: + // pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl)); + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); + break; - case GPOINTER: - MOVA(l); - DEBUGpic16_emitcode(";lcall","__gptrput"); - break; - } - pic16_emitcode ("inc","%s",rname); + /* + case FPOINTER: + pic16_emitcode ("mov","b,a"); + pic16_emitcode("movx","a,@dptr"); + break; + + case GPOINTER: + pic16_emitcode ("push","b"); + pic16_emitcode ("push","acc"); + pic16_emitcode ("lcall","__gptrget"); + pic16_emitcode ("pop","b"); + break; + */ + default: + assert(0); } + DEBUGpic16_emitcode(";", "rLen = %i", rLen); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen)); + pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh)); + // pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) ); + // pic16_emitcode ("orl","a,b"); + } - MOVA(l); - - /* last last was not complete */ - if (rLen) { - /* save the byte & read byte */ - switch (p_type) { - case POINTER: - pic16_emitcode ("mov","b,a"); - pic16_emitcode("mov","a,@%s",rname); - break; - - case FPOINTER: - pic16_emitcode ("mov","b,a"); - pic16_emitcode("movx","a,@dptr"); - break; - - case GPOINTER: - pic16_emitcode ("push","b"); - pic16_emitcode ("push","acc"); - pic16_emitcode ("lcall","__gptrget"); - pic16_emitcode ("pop","b"); - break; - } + // if (p_type == GPOINTER) + // pic16_emitcode("pop","b"); - pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) ); - pic16_emitcode ("orl","a,b"); - } + switch (p_type) { - if (p_type == GPOINTER) - pic16_emitcode("pop","b"); + case POINTER: + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0)); + // pic16_emitcode("mov","@%s,a",rname); + break; + /* + case FPOINTER: + pic16_emitcode("movx","@dptr,a"); + break; - switch (p_type) { + case GPOINTER: + DEBUGpic16_emitcode(";lcall","__gptrput"); + break; + */ + default: + assert(0); + } - case POINTER: - pic16_emitcode("mov","@%s,a",rname); - break; - - case FPOINTER: - pic16_emitcode("movx","@dptr,a"); - break; - - case GPOINTER: - DEBUGpic16_emitcode(";lcall","__gptrput"); - break; - } + // pic16_freeAsmop(right, NULL, ic, TRUE); } + /*-----------------------------------------------------------------*/ /* genDataPointerSet - remat pointer to data space */ /*-----------------------------------------------------------------*/ @@ -11392,7 +11613,7 @@ static void genDataPointerSet(operand *right, operand *result, iCode *ic) { - int size, offset = 0, resoffset=0 ; + int size, offset = 0, resoffset=0 ; DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); pic16_aopOp(right,ic,FALSE); @@ -11411,33 +11632,27 @@ static void genDataPointerSet(operand *right, } #endif - if(AOP(result)->aopu.pcop->type == PO_DIR) - resoffset=PCOR(AOP(result)->aopu.pcop)->instance; + if(AOP(result)->aopu.pcop->type == PO_DIR) + resoffset=PCOR(AOP(result)->aopu.pcop)->instance; - while (size--) { - if (AOP_TYPE(right) == AOP_LIT) { - unsigned int lit; - - if(!IS_FLOAT(operandType( right ))) - lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit); - else { - union { - unsigned long lit_int; - float lit_float; - } info; + while (size--) { + if (AOP_TYPE(right) == AOP_LIT) { + unsigned int lit; + + if(!IS_FLOAT(operandType( right ))) + lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit); + else { + union { + unsigned long lit_int; + float lit_float; + } info; - /* take care if literal is a float */ - info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit); - lit = info.lit_int; - } - + /* take care if literal is a float */ + info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit); + lit = info.lit_int; + } lit = lit >> (8*offset); - if(lit&0xff) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8 - } else { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8 - } + pic16_movLit2f(pic16_popGet(AOP(result),offset), lit); } else { pic16_mov2w(AOP(right), offset); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8 @@ -11459,135 +11674,100 @@ static void genNearPointerSet (operand *right, iCode *ic) { asmop *aop = NULL; - char *l; sym_link *retype; sym_link *ptype = operandType(result); sym_link *resetype; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - retype= getSpec(operandType(right)); - resetype = getSpec(operandType(result)); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + retype= getSpec(operandType(right)); + resetype = getSpec(operandType(result)); - pic16_aopOp(result,ic,FALSE); + pic16_aopOp(result,ic,FALSE); - /* if the result is rematerializable & - * in data space & not a bit variable */ + /* if the result is rematerializable & + * in data space & not a bit variable */ - /* and result is not a bit variable */ - if (AOP_TYPE(result) == AOP_PCODE -// && AOP_TYPE(result) == AOP_IMMD - && DCL_TYPE(ptype) == POINTER - && !IS_BITFIELD(retype) - && !IS_BITFIELD(resetype)) { - - genDataPointerSet (right,result,ic); - pic16_freeAsmop(result,NULL,ic,TRUE); - return; - } - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_aopOp(right,ic,FALSE); - DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result); - - /* if the value is already in a pointer register - * then don't need anything more */ - if (!AOP_INPREG(AOP(result))) { - /* otherwise get a free pointer register */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - -// if( (AOP_TYPE(result) == AOP_PCODE) -// && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE) -// || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10 - if(is_LitAOp( AOP(result) )) - { - if(!IS_BITFIELD(resetype)) - pic16_loadFSR0( result ); // patch 10 - } else { - if(!IS_BITFIELD(resetype)) { - // set up FSR0 with address of result - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10 - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10 - } - } - - } -// else -// rname = pic16_aopGet(AOP(result),0,FALSE,FALSE); - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + /* and result is not a bit variable */ + if (AOP_TYPE(result) == AOP_PCODE +// && AOP_TYPE(result) == AOP_IMMD + && DCL_TYPE(ptype) == POINTER + && !IS_BITFIELD(retype) + && !IS_BITFIELD(resetype)) { -// pic16_loadFSR0( result ); + genDataPointerSet (right,result,ic); + pic16_freeAsmop(result,NULL,ic,TRUE); + return; + } - /* if bitfield then unpack the bits */ - if (IS_BITFIELD(resetype)) { - genPackBits (resetype, result, right, NULL, POINTER); - } else { - /* we have can just get the values */ - int size = AOP_SIZE(right); - int offset = 0 ; + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + pic16_aopOp(right,ic,FALSE); + DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - while (size--) { - l = pic16_aopGet(AOP(right),offset,FALSE,TRUE); - if (*l == '@' ) { - //MOVA(l); - //pic16_emitcode("mov","@%s,a",rname); - pic16_emitcode("movf","indf0,w ;1"); - } else { + /* if bitfield then unpack the bits */ + if (IS_BITFIELD(resetype)) { + genPackBits (resetype, result, right, NULL, POINTER); + } else { + /* we have can just get the values */ + int size = AOP_SIZE(right); + int offset = 0 ; - if (AOP_TYPE(right) == AOP_LIT) { // patch 10 - pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); // - if (size) { // - pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); // - } else { // - pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); // - } // - } else { // no literal // - if(size) { // - pic16_emitpcode(POC_MOVFF, // - pic16_popGet2p(pic16_popGet(AOP(right),offset), // - pic16_popCopyReg(&pic16_pc_postinc0))); // - } else { // - pic16_emitpcode(POC_MOVFF, // - pic16_popGet2p(pic16_popGet(AOP(right),offset), // - pic16_popCopyReg(&pic16_pc_indf0))); // - } // - } // patch 10 - } - offset++; - } - } + pic16_loadFSR0(result, 0); + + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + while (size--) { + if (AOP_TYPE(right) == AOP_LIT) { + pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); + if (size) { + pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); + } else { + pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0)); + } + } else { // no literal + if(size) { + pic16_emitpcode(POC_MOVFF, + pic16_popGet2p(pic16_popGet(AOP(right),offset), + pic16_popCopyReg(&pic16_pc_postinc0))); + } else { + pic16_emitpcode(POC_MOVFF, + pic16_popGet2p(pic16_popGet(AOP(right),offset), + pic16_popCopyReg(&pic16_pc_indf0))); + } + } + + offset++; + } + } - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* now some housekeeping stuff */ - if (aop) { - /* we had to allocate for this iCode */ - pic16_freeAsmop(NULL,aop,ic,TRUE); - } else { - /* we did not allocate which means left - * already in a pointer register, then - * if size > 0 && this could be used again - * we have to point it back to where it - * belongs */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if (AOP_SIZE(right) > 1 - && !OP_SYMBOL(result)->remat - && ( OP_SYMBOL(result)->liveTo > ic->seq - || ic->depth )) { + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + /* now some housekeeping stuff */ + if (aop) { + /* we had to allocate for this iCode */ + pic16_freeAsmop(NULL,aop,ic,TRUE); + } else { + /* we did not allocate which means left + * already in a pointer register, then + * if size > 0 && this could be used again + * we have to point it back to where it + * belongs */ + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + if (AOP_SIZE(right) > 1 + && !OP_SYMBOL(result)->remat + && ( OP_SYMBOL(result)->liveTo > ic->seq + || ic->depth )) { - int size = AOP_SIZE(right) - 1; + int size = AOP_SIZE(right) - 1; - while (size--) - pic16_emitcode("decf","fsr0,f"); - //pic16_emitcode("dec","%s",rname); - } - } + while (size--) + pic16_emitcode("decf","fsr0,f"); + //pic16_emitcode("dec","%s",rname); + } + } - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* done */ + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + /* done */ //release: - pic16_freeAsmop(right,NULL,ic,TRUE); - pic16_freeAsmop(result,NULL,ic,TRUE); + pic16_freeAsmop(right,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); } /*-----------------------------------------------------------------*/ @@ -11671,6 +11851,10 @@ static void genPagedPointerSet (operand *right, } +#if 0 +/* This code is not adjusted to PIC16 and fails utterly... + * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */ + /*-----------------------------------------------------------------*/ /* genFarPointerSet - set value from far space */ /*-----------------------------------------------------------------*/ @@ -11720,6 +11904,7 @@ static void genFarPointerSet (operand *right, pic16_freeAsmop(right,NULL,ic,TRUE); } +#endif /*-----------------------------------------------------------------*/ /* genGenPointerSet - set value from generic pointer space */ @@ -11852,8 +12037,7 @@ static void genGenPointerSet (operand *right, operand *result, iCode *ic) { int size; - sym_link *retype = getSpec(operandType(right)); - char fgptrput[32]; + sym_link *retype = getSpec(operandType(result)); DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); @@ -11876,11 +12060,10 @@ static void genGenPointerSet (operand *right, DEBUGpic16_emitcode ("; ***","%s %d size=%d",__FUNCTION__,__LINE__,size); - /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */ /* value of right+0 is placed on stack, which will be retrieved - * by the support function this restoring the stack. The important + * by the support function thus restoring the stack. The important * thing is that there is no need to manually restore stack pointer * here */ pushaop(AOP(right), 0); @@ -11896,27 +12079,7 @@ static void genGenPointerSet (operand *right, pic16_popCopyReg(&pic16_pc_prodl))); pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2)); - - /* put code here */ - switch (size) { - case 1: strcpy(fgptrput, "__gptrput1"); break; - case 2: strcpy(fgptrput, "__gptrput2"); break; - case 3: strcpy(fgptrput, "__gptrput3"); break; - case 4: strcpy(fgptrput, "__gptrput4"); break; - default: - werror(W_POSSBUG2, __FILE__, __LINE__); - abort(); - } - - pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrput )); - - { - symbol *sym; - - sym = newSymbol( fgptrput, 0 ); - strcpy(sym->rname, fgptrput); - checkAddSym(&externs, sym); - } + pic16_callGenericPointerRW(1, size); release: pic16_freeAsmop(right,NULL,ic,TRUE); @@ -11941,6 +12104,7 @@ static void genPointerSet (iCode *ic) move it to the correct pointer register */ type = operandType(result); etype = getSpec(type); + /* if left is of type of pointer then it is simple */ if (IS_PTR(type) && !IS_FUNC(type->next)) { p_type = DCL_TYPE(type); @@ -11968,27 +12132,30 @@ static void genPointerSet (iCode *ic) /* now that we have the pointer type we assign the pointer values */ switch (p_type) { - - case POINTER: - case IPOINTER: - genNearPointerSet (right,result,ic); + case POINTER: + case FPOINTER: + case IPOINTER: + genNearPointerSet (right,result,ic); + break; + + case PPOINTER: + genPagedPointerSet (right,result,ic); break; - case PPOINTER: - genPagedPointerSet (right,result,ic); - break; - - case FPOINTER: - genFarPointerSet (right,result,ic); - break; - - case GPOINTER: - genGenPointerSet (right,result,ic); - break; +#if 0 + /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */ + case FPOINTER: + genFarPointerSet (right,result,ic); + break; +#endif + + case GPOINTER: + genGenPointerSet (right,result,ic); + break; - default: - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "genPointerSet: illegal pointer type"); + default: + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "genPointerSet: illegal pointer type"); } } @@ -12019,7 +12186,7 @@ static void genIfx (iCode *ic, iCode *popIc) /* if the condition is a bit variable */ if (isbit && IS_ITEMP(cond) && SPIL_LOC(cond)) { - genIfxJump(ic,SPIL_LOC(cond)->rname); + genIfxJump(ic,"c"); DEBUGpic16_emitcode ("; isbit SPIL_LOC","%s",SPIL_LOC(cond)->rname); } else { if (isbit && !IS_ITEMP(cond)) @@ -12050,26 +12217,28 @@ static void genAddrOf (iCode *ic) /* get address of symbol on stack */ DEBUGpic16_emitcode("; ", "%s symbol %s on stack", __FUNCTION__, sym->name); #if 0 - fprintf(stderr, "%s:%d symbol %s on stack offset %d\n", __FILE__, __LINE__, - OP_SYMBOL(left)->name, OP_SYMBOL(left)->stack); + fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__, + OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack); #endif // operands on stack are accessible via "FSR2 + index" with index // starting at 2 for arguments and growing from 0 downwards for // local variables (index == 0 is not assigned so we add one here) { - int soffs = OP_SYMBOL( IC_LEFT(ic))->stack; - if (soffs <= 0) { - assert (soffs < 0); - soffs++; - } // if - DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs); - pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF )); - pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(&pic16_pc_fsr2l)); - pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0)); - pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF )); - pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(&pic16_pc_fsr2h)); - pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1)); + int soffs = OP_SYMBOL( IC_LEFT(ic))->stack; + + if (soffs <= 0) { + assert (soffs < 0); + soffs++; + } // if + + DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs); + pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF )); + pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo)); + pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0)); + pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF )); + pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi)); + pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1)); } goto release; @@ -12083,10 +12252,6 @@ static void genAddrOf (iCode *ic) pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE); size = AOP_SIZE(IC_RESULT(ic)); - - /* Assume that what we want the address of is in data space - * since there is no stack on the PIC, yet! -- VR */ - pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype)))); pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype)))); pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype)))); @@ -12150,177 +12315,212 @@ static void genFarFarAssign (operand *result, operand *right, iCode *ic) static void genAssign (iCode *ic) { operand *result, *right; + sym_link *restype, *rtype; int size, offset,know_W; unsigned long lit = 0L; - result = IC_RESULT(ic); - right = IC_RIGHT(ic) ; + result = IC_RESULT(ic); + right = IC_RIGHT(ic) ; - FENTRY; + FENTRY; - /* if they are the same */ - if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) - return ; + /* if they are the same */ + if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) + return ; - /* reversed order operands are aopOp'ed so that result operand - * is effective in case right is a stack symbol. This maneauver - * allows to use the _G.resDirect flag later */ - pic16_aopOp(result,ic,TRUE); - pic16_aopOp(right,ic,FALSE); + /* reversed order operands are aopOp'ed so that result operand + * is effective in case right is a stack symbol. This maneauver + * allows to use the _G.resDirect flag later */ + pic16_aopOp(result,ic,TRUE); + pic16_aopOp(right,ic,FALSE); - DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result); + DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result); - /* if they are the same registers */ - if (pic16_sameRegs(AOP(right),AOP(result))) - goto release; + /* if they are the same registers */ + if (pic16_sameRegs(AOP(right),AOP(result))) + goto release; - /* if the result is a bit */ - if (AOP_TYPE(result) == AOP_CRY) { - /* if the right size is a literal then - we know what the value is */ - if (AOP_TYPE(right) == AOP_LIT) { + /* if the result is a bit */ + if (AOP_TYPE(result) == AOP_CRY) { + /* if the right size is a literal then + we know what the value is */ + if (AOP_TYPE(right) == AOP_LIT) { - pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF), - pic16_popGet(AOP(result),0)); + pic16_emitpcode( ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF), + pic16_popGet(AOP(result),0)); - if (((int) operandLitValue(right))) - pic16_emitcode("bsf","(%s >> 3),(%s & 7)", - AOP(result)->aopu.aop_dir, - AOP(result)->aopu.aop_dir); - else - pic16_emitcode("bcf","(%s >> 3),(%s & 7)", - AOP(result)->aopu.aop_dir, - AOP(result)->aopu.aop_dir); - goto release; - } + if (((int) operandLitValue(right))) + pic16_emitcode("bsf","(%s >> 3),(%s & 7)", + AOP(result)->aopu.aop_dir, + AOP(result)->aopu.aop_dir); + else + pic16_emitcode("bcf","(%s >> 3),(%s & 7)", + AOP(result)->aopu.aop_dir, + AOP(result)->aopu.aop_dir); + + goto release; + } + + /* the right is also a bit variable */ + if (AOP_TYPE(right) == AOP_CRY) { + pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); + + goto release ; + } - /* the right is also a bit variable */ - if (AOP_TYPE(right) == AOP_CRY) { + /* we need to or */ pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0)); + pic16_toBoolean(right); + emitSKPZ; pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); - - pic16_emitcode("bcf","(%s >> 3),(%s & 7)", - AOP(result)->aopu.aop_dir, - AOP(result)->aopu.aop_dir); - pic16_emitcode("btfsc","(%s >> 3),(%s & 7)", - AOP(right)->aopu.aop_dir, - AOP(right)->aopu.aop_dir); - pic16_emitcode("bsf","(%s >> 3),(%s & 7)", - AOP(result)->aopu.aop_dir, - AOP(result)->aopu.aop_dir); + //pic16_aopPut(AOP(result),"a",0); goto release ; } - /* we need to or */ - pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0)); - pic16_toBoolean(right); - emitSKPZ; - pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); - //pic16_aopPut(AOP(result),"a",0); - goto release ; - } + /* bit variables done */ + /* general case */ + size = AOP_SIZE(result); + offset = 0 ; /* bit variables done */ /* general case */ size = AOP_SIZE(result); + restype = operandType(result); + rtype = operandType(right); offset = 0 ; if(AOP_TYPE(right) == AOP_LIT) { - if(!IS_FLOAT(operandType( right ))) - lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); - else { - union { - unsigned long lit_int; - float lit_float; - } info; - - /* take care if literal is a float */ - info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit); - lit = info.lit_int; + if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right)))) + { + lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); + + /* patch tag for literals that are cast to pointers */ + if (IS_CODEPTR(restype)) { + //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno); + lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16); + } else { + if (IS_GENPTR(restype)) + { + if (IS_CODEPTR(rtype)) { + //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno); + lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16); + } else if (PIC_IS_DATA_PTR(rtype)) { + //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno); + lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16); + } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) { + //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16)); + } else if (IS_PTR(rtype)) { + fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno); + lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16); + } } + } + } else { + union { + unsigned long lit_int; + float lit_float; + } info; + + + if(IS_FIXED16X16(operandType(right))) { + lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit)); + } else { + /* take care if literal is a float */ + info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit); + lit = info.lit_int; + } + } } // fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit, // sizeof(unsigned long int), sizeof(float)); - if (AOP_TYPE(right) == AOP_REG) { - DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__); - while (size--) { - - pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++)); - } // while - goto release; - } - - if(AOP_TYPE(right) != AOP_LIT - && IN_CODESPACE(SPEC_OCLS(OP_SYMBOL(right)->etype)) - && !IS_FUNC(OP_SYM_TYPE(right)) - ) { - DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__); - fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name); - - // set up table pointer - if(is_LitOp(right)) { -// fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__); - pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl)); - pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1)); - pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh)); - pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2)); - pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru)); - } else { -// fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0), - pic16_popCopyReg(&pic16_pc_tblptrl))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1), - pic16_popCopyReg(&pic16_pc_tblptrh))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2), - pic16_popCopyReg(&pic16_pc_tblptru))); - } + if (AOP_TYPE(right) == AOP_REG) { + DEBUGpic16_emitcode("; ", "%s:%d assign from register\n", __FUNCTION__, __LINE__); + while (size--) { + pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++)); + } // while + goto release; + } - size = min(AOP_SIZE(right), AOP_SIZE(result)); - while(size--) { - pic16_emitpcodeNULLop(POC_TBLRD_POSTINC); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), - pic16_popGet(AOP(result),offset))); - offset++; - } + /* when do we have to read the program memory? + * - if right itself is a symbol in code space + * (we don't care what it points to if it's a pointer) + * - AND right is not a function (we would want its address) + */ + if(AOP_TYPE(right) != AOP_LIT + && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right))) + && !IS_FUNC(OP_SYM_TYPE(right)) + && !IS_ITEMP(right)) { - if(AOP_SIZE(result) > AOP_SIZE(right)) { - size = AOP_SIZE(result) - AOP_SIZE(right); - while(size--) { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset)); - offset++; - } - } - goto release; - } + DEBUGpic16_emitcode("; ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__); + fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name); + + // set up table pointer + if(is_LitOp(right)) { +// fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__); + pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl)); + pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1)); + pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh)); + pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2)); + pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru)); + } else { +// fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0), + pic16_popCopyReg(&pic16_pc_tblptrl))); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1), + pic16_popCopyReg(&pic16_pc_tblptrh))); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2), + pic16_popCopyReg(&pic16_pc_tblptru))); + } + /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */ + size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result)); + while(size--) { + pic16_emitpcodeNULLop(POC_TBLRD_POSTINC); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), + pic16_popGet(AOP(result),offset))); + offset++; + } + /* FIXME: for pointers we need to extend differently (according + * to pointer type DATA/CODE/EEPROM/... :*/ + size = getSize(OP_SYM_TYPE(right)); + if(AOP_SIZE(result) > size) { + size = AOP_SIZE(result) - size; + while(size--) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset)); + offset++; + } + } + goto release; + } #if 0 -/* VR - What is this?! */ - if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if(aopIdx(AOP(result),0) == 4) { - - /* this is a workaround to save value of right into wreg too, - * value of wreg is going to be used later */ + /* VR - What is this?! */ + if( AOP_TYPE(right) == AOP_DIR && (AOP_TYPE(result) == AOP_REG) && size==1) { DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - goto release; - } else + + if(aopIdx(AOP(result),0) == 4) { + /* this is a workaround to save value of right into wreg too, + * value of wreg is going to be used later */ + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); + goto release; + } else // assert(0); DEBUGpic16_emitcode ("; WARNING","%s %d ignoring register storage",__FUNCTION__,__LINE__); - } + } #endif know_W=-1; while (size--) { - DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size); + DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size); if(AOP_TYPE(right) == AOP_LIT) { if(lit&0xff) { if(know_W != (lit&0xff)) @@ -12345,17 +12545,25 @@ static void genAssign (iCode *ic) } else { DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if(!_G.resDirect) /* use this aopForSym feature */ - pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset)); + if(!_G.resDirect) { /* use this aopForSym feature */ + if(AOP_TYPE(result) == AOP_ACC) { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset)); + } else + if(AOP_TYPE(right) == AOP_ACC) { + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); + } else { + pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset)); + } + } + } + + offset++; } - - offset++; - } - release: +release: pic16_freeAsmop (right,NULL,ic,FALSE); pic16_freeAsmop (result,NULL,ic,TRUE); -} +} /*-----------------------------------------------------------------*/ /* genJumpTab - generates code for jump table */ @@ -12430,9 +12638,10 @@ static void genJumpTab (iCode *ic) pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl)); pic16_emitpLabelFORCE(jtab->key); - #endif + pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE); +// pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN)); pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, "")); /* now generate the jump labels */ @@ -12596,8 +12805,8 @@ static void genCast (iCode *ic) // if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic))) // return ; - pic16_aopOp(right,ic,FALSE) ; pic16_aopOp(result,ic,FALSE); + pic16_aopOp(right,ic,FALSE) ; DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result); @@ -12669,6 +12878,74 @@ static void genCast (iCode *ic) && IS_BITFIELD(getSpec(rtype))) { DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__); } + + /* port from pic14 to cope with generic pointers */ + if (PIC_IS_TAGGED(restype)) + { + operand *result = IC_RESULT(ic); + //operand *left = IC_LEFT(ic); + operand *right = IC_RIGHT(ic); + int tag = 0xff; + + /* copy common part */ + int max, size = AOP_SIZE(result); + if (size > AOP_SIZE(right)) size = AOP_SIZE(right); + DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__); + + max = size; + while (size--) + { + pic16_mov2w (AOP(right), size); + pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size)); + } // while + + /* upcast into generic pointer type? */ + if (IS_GENPTR(restype) + && !PIC_IS_TAGGED(rtype) + && (AOP_SIZE(result) > max)) + { + /* determine appropriate tag for right */ + if (PIC_IS_DATA_PTR(rtype)) + tag = GPTR_TAG_DATA; + else if (IS_CODEPTR(rtype)) + tag = GPTR_TAG_CODE; + else if (PIC_IS_DATA_PTR(ctype)) { + //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno); + tag = GPTR_TAG_DATA; + } else if (IS_CODEPTR(ctype)) { + //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno); + tag = GPTR_TAG_CODE; + } else if (IS_PTR(rtype)) { + PERFORM_ONCE(weirdcast, + fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno); + ); + tag = GPTR_TAG_DATA; + } else { + PERFORM_ONCE(weirdcast, + fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno); + ); + tag = GPTR_TAG_DATA; + } + + assert (AOP_SIZE(result) == 3); + /* zero-extend address... */ + for (size = max; size < AOP_SIZE(result)-1; size++) + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size)); + /* ...and add tag */ + pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag); + } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) { + //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno); + for (size = max; size < AOP_SIZE(result)-1; size++) + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size)); + /* add __code tag */ + pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE); + } else if (AOP_SIZE(result) > max) { + /* extend non-pointers */ + //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno); + pic16_addSign(result, max, 0); + } // if + goto release; + } /* if they are the same size : or less */ if (AOP_SIZE(result) <= AOP_SIZE(right)) { @@ -12784,7 +13061,7 @@ static void genCast (iCode *ic) while (size--) { if(offset < AOP_SIZE(right)) { DEBUGpic16_emitcode("; ***","%s %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type); - mov2f(AOP(result), AOP(right), offset); + pic16_mov2f(AOP(result), AOP(right), offset); /* if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) { @@ -12805,26 +13082,26 @@ static void genCast (iCode *ic) switch (p_type) { case IPOINTER: case POINTER: - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1)); -// pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1)); + case FPOINTER: + pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA); break; case CPOINTER: pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1)); break; - case FPOINTER: - pic16_emitcode(";BUG!? ","%d",__LINE__); - l = one; - break; case PPOINTER: pic16_emitcode(";BUG!? ","%d",__LINE__); l = "#0x03"; break; case GPOINTER: - pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1)); + if (GPTRSIZE > AOP_SIZE(right)) { + // assume __data pointer... THIS MIGHT BE WRONG! + pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA); + } else { + pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1)); + } break; default: @@ -12837,6 +13114,8 @@ static void genCast (iCode *ic) goto release ; } + + assert( 0 ); /* just copy the pointers */ size = AOP_SIZE(result); offset = 0 ; @@ -12864,8 +13143,10 @@ static void genCast (iCode *ic) /* we move to result for the size of source */ size = AOP_SIZE(right); offset = 0 ; + while (size--) { - mov2f(AOP(result), AOP(right), offset); + if(!_G.resDirect) + pic16_mov2f(AOP(result), AOP(right), offset); offset++; } @@ -12882,7 +13163,7 @@ static void genCast (iCode *ic) /* Save one instruction of casting char to int */ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset)); + pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset)); } else { pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg)); @@ -13020,10 +13301,26 @@ static void genReceive (iCode *ic) static void genDummyRead (iCode * ic) { - pic16_emitcode ("; genDummyRead",""); - pic16_emitcode ("; not implemented",""); + operand *op; + int i; - ic = ic; + op = IC_RIGHT(ic); + if (op && IS_SYMOP(op)) { + if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) { + fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__); + return; + } + pic16_aopOp (op, ic, FALSE); + for (i=0; i < AOP_SIZE(op); i++) { + // may need to protect this from the peepholer -- this is not nice but works... + pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN")); + pic16_mov2w (AOP(op),i); + pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END")); + } // for i + pic16_freeAsmop (op, NULL, ic, TRUE); + } else if (op) { + fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__); + } // if } /*-----------------------------------------------------------------*/ @@ -13059,7 +13356,7 @@ void genpic16Code (iCode *lic) for (ic = lic ; ic ; ic = ic->next ) { - DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op); + DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op)); if ( cln != ic->lineno ) { if ( options.debug ) { debugFile->writeCLine (ic); @@ -13080,7 +13377,7 @@ void genpic16Code (iCode *lic) l = Safe_strdup(printILine(ic)); pic16_emitpcomment("ic:%d: %s", ic->seq, l); } - + /* if the result is marked as * spilt and rematerializable or code for * this has already been generated then