X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic16%2Fgen.c;h=0a15d8cfcfa4677b287643dc951553b40947dcb6;hb=9182d601aa287fff2b037d607180a06bcf0b281b;hp=e9b64a7875aa9c027db62037f8c4530d4454c85c;hpb=d10151253d907646b1040f76f9b152f2f9d25835;p=fw%2Fsdcc diff --git a/src/pic16/gen.c b/src/pic16/gen.c index e9b64a78..0a15d8cf 100644 --- a/src/pic16/gen.c +++ b/src/pic16/gen.c @@ -6,7 +6,7 @@ Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a) PIC port - Scott Dattalo scott@dattalo.com (2000) PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002) - - Vangelis Rokas vrokas@otenet.gr (2003,2004) + - Vangelis Rokas vrokas@otenet.gr (2003,2004,2005) 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 @@ -153,7 +153,6 @@ static struct { short ipushRegs; set *sendSet; set *stackRegSet; - int interruptvector; int usefastretfie; bitVect *fregsUsed; int stack_lat; /* stack offset latency */ @@ -648,11 +647,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; @@ -780,7 +797,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); @@ -852,11 +869,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 ); } @@ -1172,6 +1193,7 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) b) has a spill location */ if (sym->isspilt || sym->nRegs == 0) { +// debugf2("%s:%d symbol %s\tisspilt: %d\tnRegs: %d\n", sym->isspilt, sym->nRegs); DEBUGpic16_emitcode(";","%d",__LINE__); /* rematerialize it NOW */ if (sym->remat) { @@ -1232,9 +1254,16 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) sym->aop = op->aop = aop = newAsmop(AOP_PCODE); //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset); - aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, - getSize(sym->type), - sym->usl.spillLoc->offset, op); + if (sym->usl.spillLoc && sym->usl.spillLoc->rname) { + aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, + getSize(sym->type), + sym->usl.spillLoc->offset, op); + } else { + fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK!\n", __FUNCTION__, __LINE__); + DEBUGpic16_emitcode (";","%s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__); + assert (getSize(sym->type) <= 1); + aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);//pic16_popRegFromString("_WREG", getSize(sym->type), 0, op); + } aop->size = getSize(sym->type); return; @@ -1545,6 +1574,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); @@ -1943,6 +1987,12 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__); 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; @@ -2003,7 +2053,9 @@ 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; @@ -3188,7 +3240,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 ); @@ -3392,6 +3444,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)); @@ -3401,6 +3458,11 @@ 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))); @@ -3519,6 +3581,10 @@ static void genFunction (iCode *ic) char asymname[128]; pBlock *apb; + +// debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type)); + +#if 0 { int i, found=-1; @@ -3534,12 +3600,16 @@ static void genFunction (iCode *ic) if(found == -1) { fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n", __FILE__, __LINE__, sym->name); - assert( 0 ); +// assert( 0 ); } _G.interruptvector = found; } +#endif - sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name); + if(FUNC_INTNO(sym->type) == 256) + sprintf(asymname, "ivec_%s", sym->name); + else + sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name); asym = newSymbol(asymname, 0); apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section")); @@ -3558,14 +3628,18 @@ 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: + 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); } @@ -3610,7 +3684,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; @@ -3658,7 +3732,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 @@ -3774,14 +3848,14 @@ static void genEndFunction (iCode *ic) pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh )); pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl )); - if(!(_G.interruptvector == 1)) { + if(!FUNC_ISSHADOWREGS(sym->type)) { /* do not restore interrupt vector for WREG,STATUS,BSR * for high priority interrupt, see genFunction */ pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr )); pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status )); pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg )); } - _G.interruptvector = 0; /* sanity check */ +// _G.interruptvector = 0; /* sanity check */ /* if debug then send end of function */ @@ -3823,8 +3897,25 @@ static void genEndFunction (iCode *ic) void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest) { - if(is_LitOp(op)) { - unsigned long lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit); + unsigned long lit=1; + + // 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 { + 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; + } + } + + if (is_LitOp(op)) { if(lit == 0) { pic16_emitpcode(POC_CLRF, dest); } else { @@ -11726,39 +11817,106 @@ static void genPackBits (sym_link *etype , operand *result, } else pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++)); - /* if the bit lenth is less than or */ + /* 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; - pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1)); + if (blen != 8 || bstr != 0) { + // we need to combine the value with the old value + pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1)); - /* shift left acc */ - AccLsh(shCnt); + /* shift left acc */ + AccLsh(shCnt); - /* using PRODL as a temporary register here */ - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl)); + /* using PRODH as a temporary register here */ + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh)); - switch (p_type) { + /* get old value */ + switch (p_type) { case FPOINTER: case POINTER: pic16_loadFSR0( result ); + fsr0_setup = 1; pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); // pic16_emitcode ("mov","b,a"); // pic16_emitcode("mov","a,@%s",rname); break; case GPOINTER: - werror(W_POSSBUG2, __FILE__, __LINE__); + if (AOP(result)->aopu.aop_reg[2]) { + // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?) + pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); + pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl))); + pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2)); + pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrget1")); + { + symbol *sym; + sym = newSymbol( "__gptrget1", 0 ); + strcpy(sym->rname, "__gptrget1"); + checkAddSym(&externs, sym); + } + } else { + // data pointer (just 2 byte given) + pic16_loadFSR0( result ); + fsr0_setup = 1; + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0)); + } + + // warnings will be emitted below + //pic16_emitpcomment ("; =?= genPackBits, GPOINTER..."); + //werror(W_POSSBUG2, __FILE__, __LINE__); break; - } + default: + assert (0 && "invalid pointer type specified"); + break; + } #if 1 - pic16_emitpcode(POC_ANDLW, pic16_popGetLit( + 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)); + pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh)); + } // if (blen != 8 || bstr != 0) + + /* write new value back */ + switch (p_type) { + case FPOINTER: + case POINTER: + if (!fsr0_setup) pic16_loadFSR0( result ); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0)); + break; + + case GPOINTER: + if (AOP(result)->aopu.aop_reg[2]) { + // prepare call to __gptrset1, this is actually genGenPointerSet(WREG, result, ?ic?) + pic16_emitpcode (POC_MOVWF, pic16_popCopyReg (pic16_stack_postdec/*pic16_pc_postdec1*/)); + pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); + pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_prodl))); + pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(result),2)); + pic16_emitpcode (POC_CALL, pic16_popGetWithString ("__gptrput1")); + { + symbol *sym; + sym = newSymbol( "__gptrput1", 0 ); + strcpy(sym->rname, "__gptrput1"); + checkAddSym(&externs, sym); + } + } else { + // data pointer (just 2 byte given) + if (!fsr0_setup) pic16_loadFSR0( result ); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0)); + } + + // this should work in all cases (as soon as gptrget/gptrput work on EEPROM and PROGRAM MEMORY) + //pic16_emitpcomment ("; =?= genPackBits, GPOINTER access"); + werror(W_POSSBUG2, __FILE__, __LINE__); + break; + + default: + assert (0 && "invalid pointer type specified"); + break; + } #endif return; @@ -12746,7 +12904,7 @@ static void genAssign (iCode *ic) pic16_popCopyReg(&pic16_pc_tblptru))); } - size = min(AOP_SIZE(right), AOP_SIZE(result)); + size = min(getSize(OP_SYM_ETYPE(right)), AOP_SIZE(result)); while(size--) { pic16_emitpcodeNULLop(POC_TBLRD_POSTINC); pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), @@ -12754,8 +12912,9 @@ static void genAssign (iCode *ic) offset++; } - if(AOP_SIZE(result) > AOP_SIZE(right)) { - size = AOP_SIZE(result) - AOP_SIZE(right); + size = getSize(OP_SYM_ETYPE(right)); + if(AOP_SIZE(result) > size) { + size = AOP_SIZE(result) - size; while(size--) { pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset)); offset++; @@ -13492,10 +13651,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 } /*-----------------------------------------------------------------*/