X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic16%2Fgen.c;h=7f9dbe233b1fe782e292a873fe6e4482ede89c58;hb=643b7d1a43dce67e766bb9d87a5549c66d07d5f7;hp=fc6eb6f85420df6f758d1433c2dc0b9f7b51fe4d;hpb=abbf0a9fb214f2b26c1e2c57e8f6f5bb6dd5b3fe;p=fw%2Fsdcc diff --git a/src/pic16/gen.c b/src/pic16/gen.c index fc6eb6f8..7f9dbe23 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 (2003-2006) + 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 @@ -46,6 +47,7 @@ #include "genutils.h" #include "device.h" #include "main.h" +#include "glue.h" /* Set the following to 1 to enable the slower/bigger * but more robust generic shifting routine (which also @@ -58,17 +60,33 @@ * 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) + +void pic16_genMult8X8_n (operand *, operand *,operand *); +#if 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 *); void pic16_genMult16X16_16(operand *, operand *, operand *); void pic16_genMult32X32_32(operand *, operand *, operand *); +#endif pCode *pic16_AssembleLine(char *line, int peeps); 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); @@ -95,7 +113,6 @@ static int GpsuedoStkPtr=0; pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index); -unsigned int pic16aopLiteral (value *val, int offset); const char *pic16_AopType(short type); static iCode *ifxForOp ( operand *op, iCode *ic ); @@ -135,6 +152,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; @@ -153,27 +171,18 @@ 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; +extern struct dbuf_s *codeOutBuf; //static void saverbank (int, iCode *,bool); static lineNode *lineHead = NULL; @@ -242,7 +251,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); @@ -257,6 +266,7 @@ void pic16_emitpcomment (char *fmt, ...) (lineHead = newLineNode(lb))); lineCurr->isInline = _G.inLine; lineCurr->isDebug = _G.debugLine; + lineCurr->isComment = 1; pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb)); va_end(ap); @@ -268,7 +278,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; @@ -311,7 +321,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) @@ -346,7 +358,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); @@ -367,6 +379,8 @@ void pic16_emitcode (char *inst,char *fmt, ...) (lineHead = newLineNode(lb))); lineCurr->isInline = _G.inLine; lineCurr->isDebug = _G.debugLine; + lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':'); + lineCurr->isComment = (*lbp == ';'); // VR fprintf(stderr, "lb = <%s>\n", lbp); @@ -401,7 +415,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); @@ -419,7 +433,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)); } @@ -648,11 +662,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; @@ -666,26 +698,36 @@ 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 { +// debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq); 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) ); } @@ -693,7 +735,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) { @@ -702,9 +744,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_frame_plusw ), 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])); + } } } @@ -780,7 +830,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); @@ -807,14 +857,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); @@ -852,11 +909,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 ); } @@ -872,7 +933,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; @@ -890,10 +951,13 @@ static asmop *aopForRemat (operand *op) // x symbol *sym) DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__); } +// if(!result) /* fixme-vr */ for (;;) { oldic = ic; -// pic16_emitpcomment("ic: %s\n", printILine(ic)); +// chat *iLine = printILine(ic); +// pic16_emitpcomment("ic: %s\n", iLine); +// dbuf_free(iLine); if (ic->op == '+') { val += (int) operandLitValue(IC_RIGHT(ic)); @@ -1069,10 +1133,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) @@ -1170,11 +1236,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; @@ -1196,7 +1263,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); @@ -1206,10 +1273,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; @@ -1228,12 +1295,30 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) sym->rname, sym->usl.spillLoc->offset); #endif - 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); - aop->size = getSize(sym->type); + if (sym->usl.spillLoc && sym->usl.spillLoc->rname) { + sym->aop = op->aop = aop = newAsmop(AOP_PCODE); + aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, + getSize(sym->type), + sym->usl.spillLoc->offset, op); + } else if (getSize(sym->type) <= 1) { + //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type)); + pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__); + assert (getSize(sym->type) <= 1); + sym->aop = op->aop = aop = newAsmop(AOP_PCODE); + aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg); + } else { + /* We need some kind of dummy area for getSize(sym->type) byte, + * use WREG for all storage locations. + * XXX: This only works if we are implementing a `dummy read', + * the stored value will not be retrievable... + * See #1503234 for a case requiring this. */ + sym->aop = op->aop = aop = newAsmop(AOP_REG); + aop->size = getSize(sym->type); + for ( i = 0 ; i < aop->size ;i++) + aop->aopu.aop_reg[i] = pic16_pc_wreg.r; + } + aop->size = getSize(sym->type); return; } @@ -1342,8 +1427,24 @@ void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop) } 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); +// pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0); + } + } + + { + regs *sr; + + _G.sregsAllocSet = reverseSet( _G.sregsAllocSet ); + for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) { + pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) ); + deleteSetItem( &_G.sregsAllocSet, sr ); + } + } } _G.resDirect = 0; } @@ -1491,13 +1592,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: @@ -1509,16 +1606,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]; @@ -1531,9 +1633,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) { - 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); @@ -1543,6 +1645,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); @@ -1579,7 +1696,7 @@ int _TempReg_lock = 0; /*-----------------------------------------------------------------*/ pCodeOp *pic16_popGetTempReg(int lock) { - pCodeOp *pcop; + pCodeOp *pcop=NULL; symbol *cfunc; // DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); @@ -1592,6 +1709,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; @@ -1600,6 +1745,7 @@ pCodeOp *pic16_popGetTempReg(int lock) /* push value on stack */ pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) ); } +#endif currFunc = cfunc; @@ -1607,13 +1753,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__); @@ -1626,15 +1774,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; @@ -1654,13 +1845,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); @@ -1679,17 +1871,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); @@ -1704,6 +1899,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 */ /*-----------------------------------------------------------------*/ @@ -1761,6 +1962,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 @@ -1772,7 +1974,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; @@ -1785,11 +1987,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; @@ -1804,17 +2009,8 @@ static pCodeOp *pic16_popRegFromIdx(int rIdx) /*---------------------------------------------------------------------------------*/ pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset) { - pCodeOpReg2 *pcop2; - pCodeOp *temp; - - pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset); - - /* comment the following check, so errors to throw up */ -// if(!pcop2)return NULL; - - temp = pic16_popGet(aop_dst, offset); - pcop2->pcop2 = temp; - + pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2( + pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset)); return PCOP(pcop2); } @@ -1826,32 +2022,19 @@ pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset) /*--------------------------------------------------------------------------------.-*/ pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst) { - pCodeOpReg2 *pcop2; - - pcop2 = (pCodeOpReg2 *)src; - pcop2->pcop2 = dst; - - return PCOP(pcop2); + pCodeOp2 *pcop2; + pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst); + return PCOP(pcop2); } - - /*---------------------------------------------------------------------------------*/ /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with */ /* movff instruction */ /*---------------------------------------------------------------------------------*/ pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc) { - pCodeOpReg2 *pcop2; - - if(!noalloc) { - pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src); - pcop2->pcop2 = pic16_popCopyReg(dst); - } else { - /* the pCodeOp may be already allocated */ - pcop2 = (pCodeOpReg2 *)(src); - pcop2->pcop2 = (pCodeOp *)(dst); - } + pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2( + pic16_popCopyReg(src), pic16_popCopyReg(dst) ); return PCOP(pcop2); } @@ -1862,13 +2045,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 */ + + /* offset is greater than size then zero */ // if (offset > (aop->size - 1) && // aop->type != AOP_LIT) @@ -1876,75 +2059,79 @@ 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; - assert (aop && aop->aopu.aop_reg[offset] != NULL); + +// debugf2("aop = %p\toffset = %d\n", aop, offset); +// assert (aop && aop->aopu.aop_reg[offset] != NULL); rIdx = aop->aopu.aop_reg[offset]->rIdx; DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__); @@ -1952,16 +2139,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; } @@ -2001,7 +2188,11 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) 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; @@ -2258,7 +2449,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)); @@ -2270,6 +2461,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)) { @@ -2282,7 +2487,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 )); @@ -2290,7 +2495,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); } @@ -2300,7 +2506,12 @@ 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_stack_postdec ))); //&pic16_pc_postdec1))); + if (pcop->type == PO_LITERAL) { + pic16_emitpcode(POC_MOVLW, pcop); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); + } else { + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec ))); + } if(pic16_options.gstack) pic16_testStackOverflow(); @@ -2321,7 +2532,7 @@ void pic16_poppCodeOp(pCodeOp *pcop) void pushw(void) { DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); //&pic16_pc_postdec1)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); if(pic16_options.gstack) pic16_testStackOverflow(); } @@ -2334,12 +2545,14 @@ 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_stack_postdec )); //&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_stack_postdec ))); //&pic16_pc_postdec1))); + pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec ))); } if(pic16_options.gstack) @@ -2550,108 +2763,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 */ /*-----------------------------------------------------------------*/ @@ -2663,9 +2774,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++; } @@ -2680,6 +2792,8 @@ static void genUminus (iCode *ic) { int size, i; sym_link *optype, *rtype; + symbol *label; + int needLabel=0; FENTRY; @@ -2700,29 +2814,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 */ @@ -2857,7 +2988,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 { @@ -2871,7 +3002,7 @@ void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src) /* assignResultValue - assign results to oper, rescall==1 is */ /* called from genCall() or genPcall() */ /*-----------------------------------------------------------------*/ -static void assignResultValue(operand * oper, int rescall) +static void assignResultValue(operand * oper, int res_size, int rescall) { int size = AOP_SIZE(oper); int offset=0; @@ -2890,20 +3021,22 @@ static void assignResultValue(operand * oper, int rescall) /* 8-bits, result in WREG */ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0)); - if(size>1) { + if(size > 1 && res_size > 1) { /* 16-bits, result in PRODL:WREG */ pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl)); } - if(size>2) { + if(size > 2 && res_size > 2) { /* 24-bits, result in PRODH:PRODL:WREG */ pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14 } - if(size>3) { + if(size > 3 && res_size > 3) { /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */ pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14 } + + pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper))); } else { /* >32-bits, result on stack, and FSR0 points to beginning. @@ -3172,7 +3305,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 ); @@ -3237,8 +3370,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(); } } @@ -3272,7 +3407,11 @@ static void genCall (iCode *ic) pic16_aopOp(IC_RESULT(ic),ic,FALSE); _G.accInUse--; - assignResultValue(IC_RESULT(ic), 1); + /* Must not assign an 8-bit result to a 16-bit variable; + * this would use (used...) the uninitialized PRODL! */ + /* FIXME: Need a proper way to obtain size of function result type, + * OP_SYM_ETYPE does not work: it dereferences pointer types! */ + assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1); DEBUGpic16_emitcode ("; ","%d left %s",__LINE__, pic16_AopType(AOP_TYPE(IC_RESULT(ic)))); @@ -3325,14 +3464,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 */ @@ -3376,6 +3514,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)); @@ -3385,12 +3528,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)); @@ -3410,7 +3558,9 @@ static void genPcall (iCode *ic) pic16_aopOp(IC_RESULT(ic),ic,FALSE); _G.accInUse--; - assignResultValue(IC_RESULT(ic), 1); + /* FIXME: Need proper way to obtain the function result's type. + * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */ + assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1); DEBUGpic16_emitcode ("; ","%d left %s",__LINE__, pic16_AopType(AOP_TYPE(IC_RESULT(ic)))); @@ -3448,12 +3598,6 @@ static int resultRemat (iCode *ic) return 0; } -#if defined(__BORLANDC__) || defined(_MSC_VER) -#define STRCASECMP stricmp -#else -#define STRCASECMP strcasecmp -#endif - #if 0 /*-----------------------------------------------------------------*/ /* inExcludeList - return 1 if the string is in exclude Reg list */ @@ -3503,38 +3647,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); +// debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type)); - 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 ))); + 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; @@ -3542,14 +3681,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); } @@ -3560,10 +3704,12 @@ static void genFunction (iCode *ic) pic16_emitcode(";"," function %s",sym->name); pic16_emitcode(";","-----------------------------------------"); + /* prevent this symbol from being emitted as 'extern' */ + pic16_stringInSet(sym->rname, &pic16_localFunctions, 1); + pic16_emitcode("","%s:",sym->rname); pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname)); - { absSym *ab; @@ -3575,7 +3721,6 @@ static void genFunction (iCode *ic) } } - if(IFFUNC_ISNAKED(ftype)) { DEBUGpic16_emitcode("; ***", "_naked function, no prologue"); return; @@ -3586,7 +3731,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 */ @@ -3594,7 +3742,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; @@ -3609,25 +3757,31 @@ static void genFunction (iCode *ic) pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh )); pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l )); pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h )); + pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath )); + pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu )); // 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_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_stackpnt_hi, pic16_framepnt_hi, 0)); + pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0)); } } @@ -3642,7 +3796,7 @@ static void genFunction (iCode *ic) 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 @@ -3653,27 +3807,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)); + } } @@ -3708,7 +3881,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)); @@ -3721,9 +3905,10 @@ 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) { @@ -3742,30 +3927,37 @@ static void genEndFunction (iCode *ic) } 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 */ + pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo )); if(STACK_MODEL_LARGE) pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi )); - pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo )); } } _G.useWreg = 0; if (IFFUNC_ISISR(sym->type)) { + pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu )); + pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath )); pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h )); pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l)); 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 */ @@ -3805,23 +3997,51 @@ 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)); - return; } - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest)); - } + + if (AOP_TYPE(op) == AOP_LIT) { + /* FIXME: broken for + * char __at(0x456) foo; + * return &foo; + * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */ + pic16_movLit2f(dest, (lit >> (8ul*offset))); + } else if (AOP_TYPE(op) == AOP_PCODE + && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) { + /* char *s= "aaa"; return s; */ + /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so + * that the generic pointer is interpreted correctly + * as referring to __code space, but this is fragile! */ + pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset )); + /* XXX: should check that dest != WREG */ + pic16_emitpcode(POC_MOVWF, dest); + } 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)); + } } /*-----------------------------------------------------------------*/ @@ -3845,27 +4065,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 */ @@ -4028,9 +4237,10 @@ static void genMultOneByte (operand *left, pic16_aopGet(AOP(result),0,FALSE,FALSE)); } - pic16_genMult8X8_8 (left, right,result); + pic16_genMult8X8_n (left, right,result); } +#if 0 /*-----------------------------------------------------------------*/ /* genMultOneWord : 16 bit multiplication */ /*-----------------------------------------------------------------*/ @@ -4067,7 +4277,9 @@ static void genMultOneWord (operand *left, pic16_genMult16X16_16(left, right,result); } +#endif +#if 0 /*-----------------------------------------------------------------*/ /* genMultOneLong : 32 bit multiplication */ /*-----------------------------------------------------------------*/ @@ -4104,6 +4316,7 @@ static void genMultOneLong (operand *left, pic16_genMult32X32_32(left, right,result); } +#endif @@ -4139,6 +4352,7 @@ static void genMult (iCode *ic) goto release ; } +#if 0 /* if both are of size == 2 */ if(AOP_SIZE(left) == 2 && AOP_SIZE(right) == 2) { @@ -4152,7 +4366,11 @@ static void genMult (iCode *ic) genMultOneLong(left, right, result); goto release; } - +#endif + + fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ ); + assert( !"Multiplication should have been transformed into function call!" ); + pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor."); @@ -4166,6 +4384,7 @@ release : pic16_freeAsmop(result,NULL,ic,TRUE); } +#if 0 /*-----------------------------------------------------------------*/ /* genDivbits :- division of bits */ /*-----------------------------------------------------------------*/ @@ -4335,6 +4554,7 @@ static void genDivOneByte (operand *left, pic16_aopPut(AOP(result),"a",offset++); } +#endif /*-----------------------------------------------------------------*/ /* genDiv - generates code for division */ @@ -4344,8 +4564,12 @@ static void genDiv (iCode *ic) operand *left = IC_LEFT(ic); operand *right = IC_RIGHT(ic); operand *result= IC_RESULT(ic); - - + int negated = 0; + int leftVal = 0, rightVal = 0; + int signedLits = 0; + char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } }; + int op = 0; + /* Division is a very lengthy algorithm, so it is better * to call support routines than inlining algorithm. * Division functions written here just in case someone @@ -4358,6 +4582,207 @@ static void genDiv (iCode *ic) pic16_aopOp (right,ic,FALSE); pic16_aopOp (result,ic,TRUE); + if (ic->op == '/') + op = 0; + else if (ic->op == '%') + op = 1; + else + assert( !"invalid operation requested in genDivMod" ); + + /* get literal values */ + if (IS_VALOP(left)) { + leftVal = (int)floatFromVal( OP_VALUE(left) ); + assert( leftVal >= -128 && leftVal < 256 ); + if (leftVal < 0) { signedLits++; } + } + if (IS_VALOP(right)) { + rightVal = (int)floatFromVal( OP_VALUE(right) ); + assert( rightVal >= -128 && rightVal < 256 ); + if (rightVal < 0) { signedLits++; } + } + + /* We should only come here to convert all + * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t} + * with exactly one operand being s8_t into + * u8_t x u8_t -> u8_t. All other cases should have been + * turned into calls to support routines beforehand... */ + if ((AOP_SIZE(left) == 1 || IS_VALOP(left)) + && (AOP_SIZE(right) == 1 || IS_VALOP(right))) + { + if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0) + && (!IS_UNSIGNED(operandType(left)) || leftVal < 0)) + { + /* Both operands are signed or negative, use _divschar + * instead of _divuchar */ + pushaop(AOP(right), 0); + pushaop(AOP(left), 0); + + /* call _divschar */ + pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0])); + + { + symbol *sym; + sym = newSymbol( functions[op][0], 0 ); + sym->used++; + strcpy(sym->rname, functions[op][0]); + checkAddSym(&externs, sym); + } + + /* assign result */ + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); + if (AOP_SIZE(result) > 1) + { + pic16_emitpcode(POC_MOVFF, + pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl), + pic16_popGet(AOP(result), 1))); + /* sign extend */ + pic16_addSign(result, 2, 1); + } + + /* clean up stack */ + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc)); + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc)); + + goto release; + } + + /* push right operand */ + if (IS_VALOP(right)) { + if (rightVal < 0) { + pic16_pushpCodeOp( pic16_popGetLit(-rightVal) ); + negated++; + } else { + pushaop(AOP(right), 0); + } + } else if (!IS_UNSIGNED(operandType(right))) { + pic16_mov2w(AOP(right), 0); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7)); + pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec)); + negated++; + } else { + pushaop(AOP(right), 0); + } + + /* push left operand */ + if (IS_VALOP(left)) { + if (leftVal < 0) { + pic16_pushpCodeOp(pic16_popGetLit(-leftVal)); + negated++; + } else { + pushaop(AOP(left), 0); + } + } else if (!IS_UNSIGNED(operandType(left))) { + pic16_mov2w(AOP(left),0); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7)); + pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec)); + negated++; + } else { + pushaop(AOP(left), 0); + } + + /* call _divuchar */ + pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1])); + + { + symbol *sym; + sym = newSymbol( functions[op][1], 0 ); + sym->used++; + strcpy(sym->rname, functions[op][1]); + checkAddSym(&externs, sym); + } + + /* Revert negation(s) from above. + * This is inefficient: if both operands are negative, this + * should not touch WREG. However, determining that exactly + * one operand was negated costs at least 3 instructions, + * so there is nothing to be gained here, is there? + * + * I negate WREG because either operand might share registers with + * result, so assigning first might destroy an operand. */ + + /* For the modulus operator, (a/b)*b == a shall hold. + * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0 + * a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) = 125 and +3 remaining) + * a<0, b>0 --> a/b <= 0 and a%b < 0 (e.g. -128 / 5 = -25, -25* 5 = -125 and -3 remaining) + * a<0, b<0 --> a/b >= 0 and a%b < 0 (e.g. -128 / -5 = 25, 25*(-5) = -125 and -3 remaining) + * Only invert the result if the left operand is negative (sigh). + */ + if (AOP_SIZE(result) <= 1 || !negated) + { + if (ic->op == '/') + { + if (IS_VALOP(right)) { + if (rightVal < 0) { + /* we negated this operand above */ + pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg)); + } + } else if (!IS_UNSIGNED(operandType(right))) { + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7)); + pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg)); + } + } + + if (IS_VALOP(left)) { + if (leftVal < 0) { + /* we negated this operand above */ + pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg)); + } + } else if (!IS_UNSIGNED(operandType(left))) { + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7)); + pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg)); + } + + /* Move result to destination. */ + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); + + /* Zero-extend: no operand was signed (or result is just a byte). */ + pic16_addSign(result, 1, 0); + } else { + assert( AOP_SIZE(result) > 1 ); + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1)); + if (ic->op == '/') + { + if (IS_VALOP(right)) { + if (rightVal < 0) { + /* we negated this operand above */ + pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1)); + } + } else if (!IS_UNSIGNED(operandType(right))) { + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7)); + pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1)); + } + } + + if (IS_VALOP(left)) { + if (leftVal < 0) { + /* we negated this operand above */ + pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1)); + } + } else if (!IS_UNSIGNED(operandType(left))) { + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7)); + pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1)); + } + + /* Move result to destination. */ + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); + + /* Negate result if required. */ + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7)); + pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0)); + + /* Sign-extend. */ + pic16_addSign(result, 2, 1); + } + + /* clean up stack */ + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc)); + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc)); + goto release; + } + +#if 0 /* special cases first */ /* both are bits */ if (AOP_TYPE(left) == AOP_CRY && @@ -4372,6 +4797,7 @@ static void genDiv (iCode *ic) genDivOneByte(left,right,result); goto release ; } +#endif /* should have been converted to function call */ assert(0); @@ -4381,6 +4807,7 @@ release : pic16_freeAsmop(result,NULL,ic,TRUE); } +#if 0 /*-----------------------------------------------------------------*/ /* genModbits :- modulus of bits */ /*-----------------------------------------------------------------*/ @@ -4480,12 +4907,16 @@ static void genModOneByte (operand *left, pic16_aopPut(AOP(result),"b",0); } +#endif /*-----------------------------------------------------------------*/ /* genMod - generates code for division */ /*-----------------------------------------------------------------*/ static void genMod (iCode *ic) { + /* Task deferred to genDiv */ + genDiv(ic); +#if 0 operand *left = IC_LEFT(ic); operand *right = IC_RIGHT(ic); operand *result= IC_RESULT(ic); @@ -4519,6 +4950,7 @@ release : pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); pic16_freeAsmop(result,NULL,ic,TRUE); +#endif } /*-----------------------------------------------------------------*/ @@ -4662,9 +5094,9 @@ 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; @@ -4767,11 +5199,6 @@ static int genChkZeroes(operand *op, int lit, int size) } #endif -#if !defined(__BORLANDC__) && !defined(_MSC_VER) -#define DEBUGpc(fmt,...) DEBUGpic16_emitcode("; =:=", "%s:%s:%d: " fmt, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__) -#endif -#define isAOP_LIT(x) (AOP_TYPE(x) == AOP_LIT) -#define isAOP_REGlike(x) (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE || AOP_TYPE(x) == AOP_STA) /*-----------------------------------------------------------------*/ /* mov2w_regOrLit :- move to WREG either the offset's byte from */ @@ -4790,7 +5217,7 @@ void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) { /* genCmp :- greater or less than comparison */ /*-----------------------------------------------------------------*/ -#if USE_SIMPLE_GENCMP +#if USE_SIMPLE_GENCMP /* { */ /* genCmp performs a left < right comparison, stores * the outcome in result (if != NULL) and generates @@ -4814,8 +5241,8 @@ static void genCmp (operand *left,operand *right, FENTRY; - assert (AOP_SIZE(left) == AOP_SIZE(right)); assert (left && right); + assert (AOP_SIZE(left) == AOP_SIZE(right)); size = AOP_SIZE(right) - 1; mask = (0x100UL << (size*8)) - 1; @@ -4826,6 +5253,10 @@ static void genCmp (operand *left,operand *right, 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! * **********************************************************************/ @@ -4852,9 +5283,7 @@ static void genCmp (operand *left,operand *right, * make sure that left is register (or the like) * *************************************************/ if (!isAOP_REGlike(left)) { - #if !defined(__BORLANDC__) && !defined(_MSC_VER) DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right)); - #endif assert (isAOP_LIT(left)); assert (isAOP_REGlike(right)); // swap left and right @@ -4868,14 +5297,14 @@ static void genCmp (operand *left,operand *right, } // if // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed), - // that's we handled it above. + // 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" + 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 @@ -4890,9 +5319,7 @@ static void genCmp (operand *left,operand *right, if (isAOP_LIT(right)) { if (!sign) { // unsigned comparison to a literal - #if !defined(__BORLANDC__) && !defined(_MSC_VER) DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1); - #endif if (lit == 0) { // unsigned left < 0? always false if (performedLt) emitCLRC; else emitSETC; @@ -4900,9 +5327,7 @@ static void genCmp (operand *left,operand *right, } } else { // signed comparison to a literal - #if !defined(__BORLANDC__) && !defined(_MSC_VER) DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask); - #endif if ((lit & mask) == ((0x80 << (size*8)) & mask)) { // signed left < 0x80000000? always false if (performedLt) emitCLRC; else emitSETC; @@ -4946,6 +5371,7 @@ static void genCmp (operand *left,operand *right, 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); @@ -4976,7 +5402,7 @@ 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) + * (F=left, W=right) * ****************************************************/ if (performedLt) { @@ -5002,16 +5428,14 @@ correct_result_in_carry: } // if (result) // perform conditional jump - // genSkipc branches to rifx->label if (rifx->condition != CARRY) if (ifx) { //DEBUGpc ("generate control flow"); - rIfx.condition ^= 1; genSkipc (&rIfx); ifx->generated = 1; } // if } -#elif 1 +#elif 1 /* } */ /* { */ /* original code */ static void genCmp (operand *left,operand *right, @@ -5644,7 +6068,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)); @@ -5734,7 +6158,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, @@ -5844,10 +6268,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) { @@ -5871,7 +6291,7 @@ static void genCmp (operand *left, operand *right, pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir); werror(W_POSSBUG2, __FILE__, __LINE__); - exit(-1); + exit(EXIT_FAILURE); } /* if literal is on the right then swap with left */ @@ -5906,6 +6326,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 ); @@ -5986,7 +6407,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; @@ -5999,7 +6419,6 @@ static void genCmp (operand *left, operand *right, } } else { - /* unsigned compare */ DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__); @@ -6010,10 +6429,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 ); @@ -6098,531 +6515,74 @@ 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)); - - DEBUGpic16_pic16_AopType(__LINE__,left,right,result); + + left = IC_LEFT(ic); + right= IC_RIGHT(ic); + result = IC_RESULT(ic); - /* POC_CPFSGT compare f, wreg, skip if f greater than wreg - * POC_CPFSLT compare f, wreg, skip if f less then wreg */ - + 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); - /* 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; + genCmp(right, left, result, ifx, sign); - lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit); + 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 = (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); - } +/*-----------------------------------------------------------------*/ +/* genCmpLt - less than comparisons */ +/*-----------------------------------------------------------------*/ +static void genCmpLt (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + sym_link *letype , *retype; + int sign ; + FENTRY; - //if(IC_TRUE(ifx) == NULL) - /* if left & right are bit variables */ - if (AOP_TYPE(left) == AOP_CRY && - AOP_TYPE(right) == AOP_CRY ) { + left = IC_LEFT(ic); + right= IC_RIGHT(ic); + result = IC_RESULT(ic); - pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); - pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir); + letype = getSpec(operandType(left)); + retype =getSpec(operandType(right)); + sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype)); - } else { - symbol *lbl = newiTempLabel(NULL); + /* assign the amsops */ + pic16_aopOp (left,ic,FALSE); + pic16_aopOp (right,ic,FALSE); + pic16_aopOp (result,ic,TRUE); - if(AOP_TYPE(left) == AOP_LIT) { - DEBUGpic16_emitcode(";left lit","lit = 0x%x, sign=%d",lit,sign); - - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) - willCheckCarry = 1; - else willCheckCarry = 0; - - /* 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)); - - genSkipz2(&rFalseIfx,0); - if(ifx)ifx->generated = 1; - return; - } - - 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)); - - 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 /* } */ + 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); +} - -/*-----------------------------------------------------------------*/ -/* 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 +#if 0 +// not needed ATM +// FIXME reenable literal optimisation when the pic16 port is stable /*-----------------------------------------------------------------*/ /* genc16bit2lit - compare a 16 bit value to a literal */ @@ -6967,6 +6927,7 @@ static void genCmpEq (iCode *ic, iCode *ifx) int preserve_result = 0; int generate_result = 0; int i=0; + unsigned long lit = -1; FENTRY; @@ -6991,6 +6952,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; @@ -7003,6 +6968,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) @@ -7012,9 +6978,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)); @@ -7481,7 +7449,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); @@ -7530,7 +7498,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); @@ -7753,7 +7721,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)); @@ -7969,6 +7937,7 @@ static void genOr (iCode *ic, iCode *ifx) unsigned long lit = 0L; DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE); pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE); @@ -8173,13 +8142,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)); } } @@ -8220,21 +8189,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; @@ -8244,17 +8213,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)); } } @@ -8274,6 +8243,7 @@ static void genXor (iCode *ic, iCode *ifx) unsigned long lit = 0L; DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE); pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE); @@ -8518,8 +8488,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) { @@ -8539,6 +8570,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++; } @@ -8567,7 +8603,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); @@ -8612,7 +8648,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); @@ -8719,7 +8755,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){ @@ -8752,8 +8788,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])); + } } /*-----------------------------------------------------------------*/ @@ -8918,7 +8956,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)); } @@ -8933,7 +8971,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: @@ -9050,7 +9088,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) { @@ -9295,8 +9333,9 @@ static void shiftR2Left2Result (operand *left, int offl, case 1: case 2: case 3: + /* obtain sign from left operand */ if(sign) - pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16)); else emitCLRC; @@ -9312,9 +9351,10 @@ static void shiftR2Left2Result (operand *left, int offl, while(--shCount) { if(sign) - pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16)); + /* now get sign from already assigned result (avoid BANKSEL) */ + pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16)); else - emitCLRC; + emitCLRC; pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16)); pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr)); } @@ -9421,7 +9461,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)); @@ -9639,7 +9679,7 @@ void pic16_genLeftShiftLiteral (operand *left, operand *result, iCode *ic) { - int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit)); + int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit)); int size; FENTRY; @@ -9647,7 +9687,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)); @@ -9773,7 +9813,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++; } @@ -9805,7 +9845,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 @@ -9956,7 +9996,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++; } @@ -9985,7 +10025,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)); @@ -10107,12 +10147,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 */ @@ -10249,13 +10284,13 @@ static void genRightShiftLiteral (operand *left, iCode *ic, int sign) { - int shCount = (int) abs(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)); @@ -10270,8 +10305,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)){ @@ -10280,7 +10317,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 { @@ -10603,7 +10640,7 @@ static void genGenericShift (iCode *ic, int isShiftLeft) { pic16_aopOp(right,ic,FALSE); pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,FALSE); + pic16_aopOp(result,ic,TRUE); sign = !SPEC_USIGN(operandType (left)); signedCount = !SPEC_USIGN(operandType (right)); @@ -10649,7 +10686,7 @@ static void genGenericShift (iCode *ic, int isShiftLeft) { // (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++) { - mov2f (AOP(result),AOP(left), offset); + pic16_mov2f (AOP(result),AOP(left), offset); } // for // if result is longer than left, fill with zeros (or sign) @@ -10741,9 +10778,88 @@ static void genRightShift (iCode *ic) { #endif -void pic16_loadFSR0(operand *op) +/* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */ +void pic16_loadFSR0(operand *op, int lit) { - pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0))); + 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))); + } +} + +/*----------------------------------------------------------------*/ +/* 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) +{ + 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; + } } /*-----------------------------------------------------------------*/ @@ -10752,182 +10868,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 *reading*\n"); + fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n"); + exit(EXIT_FAILURE); - 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))) { @@ -10936,17 +10994,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; @@ -10955,8 +11002,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 { @@ -10982,15 +11029,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); @@ -11012,7 +11061,7 @@ static void genNearPointerGet (operand *left, } DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_aopOp (result,ic,FALSE); + pic16_aopOp (result,ic,TRUE); DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result); @@ -11038,6 +11087,7 @@ static void genNearPointerGet (operand *left, 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 */ @@ -11056,29 +11106,8 @@ static void genNearPointerGet (operand *left, } #endif - - /* 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(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 - } - } - } - /* 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 */ @@ -11087,11 +11116,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), @@ -11101,29 +11127,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 */ @@ -11145,6 +11151,7 @@ static void genNearPointerGet (operand *left, // pic16_emitcode("dec","%s",rname); } } +#endif /* done */ pic16_freeAsmop(left,NULL,ic,TRUE); @@ -11184,7 +11191,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)) @@ -11232,6 +11239,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 */ /*-----------------------------------------------------------------*/ @@ -11262,7 +11273,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)) @@ -11281,6 +11292,7 @@ static void genFarPointerGet (operand *left, pic16_freeAsmop(result,NULL,ic,TRUE); } +#endif #if 0 /*-----------------------------------------------------------------*/ @@ -11376,7 +11388,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--) { @@ -11409,15 +11421,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!) @@ -11442,41 +11459,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(); - } + 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); - pic16_emitpcode(POC_CALL, pic16_popGetWithString( fgptrget )); + assignResultValue(result, size, 1); - 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); @@ -11516,9 +11508,9 @@ static void genConstPointerGet (operand *left, 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))); + 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--) { @@ -11592,6 +11584,7 @@ static void genPointerGet (iCode *ic) the pointer values */ switch (p_type) { case POINTER: + case FPOINTER: case IPOINTER: genNearPointerGet (left,result,ic); break; @@ -11600,9 +11593,13 @@ static void genPointerGet (iCode *ic) genPagedPointerGet(left,result,ic); break; +#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: genConstPointerGet (left,result,ic); @@ -11636,210 +11633,248 @@ 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 % 8) != 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)); + } + } else { // if (blen == 8 && (bstr % 8) == 0) + if (shifted_and_masked) { + // move right (literal) to WREG (only case where right is not yet in WREG) + pic16_mov2w(AOP(right), (bstr / 8)); } + } + /* 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(EXIT_FAILURE); +#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 */ /*-----------------------------------------------------------------*/ @@ -11847,7 +11882,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); @@ -11864,42 +11899,22 @@ static void genDataPointerSet(operand *right, PCOR(AOP(result)->aopu.pcop)->instance: PCOI(AOP(result)->aopu.pcop)->offset); } -#endif - - 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; - - /* 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 - } - } else { - pic16_mov2w(AOP(right), offset); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8 - } - offset++; - resoffset++; - } +#endif + + 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 = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset); + 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 + } + offset++; + resoffset++; + } pic16_freeAsmop(right,NULL,ic,TRUE); } @@ -11914,135 +11929,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) { - 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++; - } - } + 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); } /*-----------------------------------------------------------------*/ @@ -12126,6 +12106,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 */ /*-----------------------------------------------------------------*/ @@ -12175,6 +12159,7 @@ static void genFarPointerSet (operand *right, pic16_freeAsmop(right,NULL,ic,TRUE); } +#endif /*-----------------------------------------------------------------*/ /* genGenPointerSet - set value from generic pointer space */ @@ -12307,8 +12292,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__); @@ -12331,11 +12315,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); @@ -12351,27 +12334,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); @@ -12396,6 +12359,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); @@ -12424,6 +12388,7 @@ static void genPointerSet (iCode *ic) the pointer values */ switch (p_type) { case POINTER: + case FPOINTER: case IPOINTER: genNearPointerSet (right,result,ic); break; @@ -12432,9 +12397,12 @@ static void genPointerSet (iCode *ic) genPagedPointerSet (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); @@ -12504,26 +12472,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_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)); + 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; @@ -12600,212 +12570,258 @@ 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); - if(AOP_TYPE(right) == AOP_LIT) { - if(lit&0xff) { - if(know_W != (lit&0xff)) - pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff)); - know_W = lit&0xff; - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - } else - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); + size = AOP_SIZE(right); + if (size > AOP_SIZE(result)) size = AOP_SIZE(result); + know_W=-1; + while (size--) { + DEBUGpic16_emitcode ("; ***","%s %d size %d",__FUNCTION__,__LINE__, size); + if(AOP_TYPE(right) == AOP_LIT) { + if(lit&0xff) { + if(know_W != (lit&0xff)) + pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff)); + know_W = lit&0xff; + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); + } else + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); - lit >>= 8; + lit >>= 8; - } else if (AOP_TYPE(right) == AOP_CRY) { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); - if(offset == 0) { - //debugf("%s: BTFSS offset == 0\n", __FUNCTION__); - pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0)); - } - } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) { + } else if (AOP_TYPE(right) == AOP_CRY) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); + if(offset == 0) { + //debugf("%s: BTFSS offset == 0\n", __FUNCTION__); + pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0)); + } + } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) { pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - } else { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + } else { + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + 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)); + } + } + } - if(!_G.resDirect) /* use this aopForSym feature */ - pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset)); + offset++; } - - offset++; - } + pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right))); - release: +release: pic16_freeAsmop (right,NULL,ic,FALSE); pic16_freeAsmop (result,NULL,ic,TRUE); -} +} /*-----------------------------------------------------------------*/ /* genJumpTab - generates code for jump table */ @@ -12880,9 +12896,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 */ @@ -13046,8 +13063,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); @@ -13119,6 +13136,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*)' -- assuming __data space\n", ic->filename, ic->lineno); + ); + tag = GPTR_TAG_DATA; + } else { + PERFORM_ONCE(weirdcast, + fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __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)) { @@ -13177,10 +13262,13 @@ static void genCast (iCode *ic) if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) { pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1)); - if(AOP_SIZE(result) <2) - fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__); + + if(AOP_SIZE(result) < 2) { + fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__); + } else { + pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1)); + } } else { /* if they in different places then copy */ size = AOP_SIZE(result); @@ -13234,7 +13322,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) { @@ -13255,26 +13343,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: @@ -13287,6 +13375,8 @@ static void genCast (iCode *ic) goto release ; } + + assert( 0 ); /* just copy the pointers */ size = AOP_SIZE(result); offset = 0 ; @@ -13314,8 +13404,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++; } @@ -13332,7 +13424,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)); @@ -13458,7 +13550,9 @@ static void genReceive (iCode *ic) GpsuedoStkPtr = ic->parmBytes; /* setting GpsuedoStkPtr has side effects here: */ - assignResultValue(IC_RESULT(ic), 0); + /* FIXME: What's the correct size of the return(ed) value? + * For now, assuming '4' as before... */ + assignResultValue(IC_RESULT(ic), 4, 0); } pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); @@ -13470,10 +13564,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 } /*-----------------------------------------------------------------*/ @@ -13524,13 +13634,14 @@ void genpic16Code (iCode *lic) } if(options.iCodeInAsm) { - char *l; + char *iLine; /* insert here code to print iCode as comment */ - l = Safe_strdup(printILine(ic)); - pic16_emitpcomment("ic:%d: %s", ic->seq, l); + iLine = printILine(ic); + pic16_emitpcomment("ic:%d: %s", ic->seq, iLine); + dbuf_free(iLine); } - + /* if the result is marked as * spilt and rematerializable or code for * this has already been generated then @@ -13736,7 +13847,7 @@ void genpic16Code (iCode *lic) peepHole (&lineHead); /* now do the actual printing */ - printLine (lineHead, codeOutFile); + printLine (lineHead, codeOutBuf); #ifdef PCODE_DEBUG DFPRINTF((stderr,"printing pBlock\n\n"));