// // picsim.c - PIC C simulator for embedding pic microcode into a C program // // Copyright (C) 2006 Nathan (Acorn) Pooley // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // version 2 as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License (gpl.txt) for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // You can contact the author, Nathan (Acorn) Pooley, by writing // to Nathan (Acorn) Pooley, 949 Buckeye Drive, Sunnyvale, CA 94086, USA // or through the form at http://www.rawbw.com/~acorn/wand/feedback.html // // #@DOC@ PIC C simulator for embedding pic microcode into a C program //########################################################################### //############################### INCLUDES ################################## //########################################################################### #include <stdio.h> #include <stdlib.h> #include <string.h> #include "picsim.h" #include "ac_assert.h" //########################################################################### //############################### DEFINES ################################### //########################################################################### #define PIC_REG_CNT_LOG2 12 #define PIC_REG_CNT (1UL<<PIC_REG_CNT_LOG2) #define PIC_FLASH_BANK_CNT_LOG2 6 #define PIC_FLASH_BANK_CNT (1UL<<PIC_FLASH_BANK_CNT_LOG2) #define PIC_FLASH_BANK_BYTES_LOG2 10 #define PIC_FLASH_BANK_BYTES (1UL<<PIC_FLASH_BANK_BYTES_LOG2) #define ASSERT(c) AC_ASSERT(c) //########################################################################### //############################### TYPEDEFS ################################## //########################################################################### typedef int (*picRegFunc)(picChip *ch, picReg *reg, int val); typedef struct picRegNamespaceRec { const char *name; picRegFunc findFunc; struct picRegNamespaceRec *next; } picRegNamespace; struct picRegRec { int id; int sub; picRegFunc rd; picRegFunc wr; picRegNamespace *ns; char *name; picReg *next; }; struct picChipRec { picReg *regList[PIC_REG_CNT]; picReg *regs; picRegNamespace *ns_list; picRegNamespace *ns_global; picRegNamespace *ns_local; picRegNamespace *ns_param; picRegNamespace *ns_inoutparam; picRegNamespace *ns_return; picRegNamespace *ns_sfr; int ram[0xfff]; short *flash[PIC_FLASH_BANK_CNT]; int flashSize; int skip; int movff_tmp; int plusw_savew; int cycle; int trace; }; enum { ST_N = 0x10, ST_OV = 0x08, ST_Z = 0x04, ST_DC = 0x02, ST_C = 0x01, ST_END = 0x7fffffff }; //########################################################################### //############################### GLOBALS ################################### //########################################################################### picChip *picCurChip = 0; const char *picNamespaceSfr = "Sfr"; const char *picNamespaceGlobal = "Global"; const char *picNamespaceLocal = "Local"; const char *picNamespaceParam = "Param"; const char *picNamespaceInOutParam = "Param"; const char *picNamespaceReturn = "Return"; //########################################################################### //############################### CODE ###################################### //########################################################################### #if 0 // not used //=========================================================================== // picFatalError() - big bad error //=========================================================================== static void picFatalError(picChip *ch) { ASSERT(!"Fatal error in picsim"); } #endif //=========================================================================== // picRegFindFuncLocal() - local variable init //=========================================================================== static int picRegFindFuncLocal(picChip *ch, picReg *r, int val) { picRegErase(ch,r->id); return 0; } //=========================================================================== // picRegFindFuncParam() - local variable init //=========================================================================== static int picRegFindFuncParam(picChip *ch, picReg *r, int val) { return 0; } //=========================================================================== // picRegFindFuncInOut() - local variable init //=========================================================================== static int picRegFindFuncInOut(picChip *ch, picReg *r, int val) { return 0; } //=========================================================================== // picRegFindFuncReturn() - local variable init //=========================================================================== static int picRegFindFuncReturn(picChip *ch, picReg *r, int val) { picRegErase(ch,r->id); return 0; } //=========================================================================== // picRegFindFuncGlobal() - local variable init //=========================================================================== static int picRegFindFuncGlobal(picChip *ch, picReg *r, int val) { return 0; } //=========================================================================== // picRegFindFuncSfr() - Sfr variable init //=========================================================================== static int picRegFindFuncSfr(picChip *ch, picReg *r, int val) { return 0; } //=========================================================================== // picNamespaceFind() - find (& create) a namespace //=========================================================================== static picRegNamespace *picNamespaceFind(picChip *ch, const char *name, int create) { picRegNamespace *ns; if (name == picNamespaceLocal) return ch->ns_local; if (name == picNamespaceParam) return ch->ns_param; if (name == picNamespaceInOutParam) return ch->ns_inoutparam; if (name == picNamespaceReturn) return ch->ns_return; if (name == picNamespaceGlobal) return ch->ns_global; if (name == picNamespaceSfr) return ch->ns_sfr; if (name) { for (ns=ch->ns_list; ns; ns=ns->next) { if (ns->name && !strcmp(name,ns->name)) { return ns; } } } if (create) { ns = calloc(1,sizeof(picRegNamespace)); if (ns) { ns->name = name ? strdup(name) : 0; ns->findFunc = picRegFindFuncGlobal; ns->next = ch->ns_list; ch->ns_list = ns; } } return ns; } //=========================================================================== // picRegWriteFsr() - fsr reg write //=========================================================================== static int picRegWriteFsr(picChip *ch, picReg *reg, int val) { picReg *sub = ch->regList[reg->sub]; picReg *fsrh = ch->regList[reg->sub+FSR0H-FSR0L]; picReg *fsrl = ch->regList[reg->sub+FSR0L-FSR0L]; int x = (ch->ram[fsrh->id] | ch->ram[fsrl->id]) >> 8; int idx = (ch->ram[fsrh->id] << 8) | ch->ram[fsrl->id]; int idx2 = idx; int w; switch(reg->id - sub->id) { case PLUSW0-FSR0L: w = ch->plusw_savew; ASSERT(w>=-128 && w<=128); idx += w; ASSERT(idx > 0x17f); ASSERT(idx < 0xf80); ch->ram[idx] = val; ch->plusw_savew = -1000; return val; case POSTDEC0-FSR0L: idx2 -= 2; case POSTINC0-FSR0L: idx2 += 1; case PREINC0-FSR0L: case INDF0-FSR0L: ASSERT(idx > 0x17f); ASSERT(idx < 0xf80); ASSERT(x == 0); ch->ram[fsrh->id] = idx2 >> 8; ch->ram[fsrl->id] = idx2 & 0xff; ch->ram[idx] = val; return val; default: ASSERT(!"Bad reg in picRegWriteFsr"); return -1; } } //=========================================================================== // picRegReadFsr() - fsr reg read //=========================================================================== static int picRegReadFsr(picChip *ch, picReg *reg, int val) { picReg *sub = ch->regList[reg->sub]; picReg *fsrh = ch->regList[reg->sub+FSR0H-FSR0L]; picReg *fsrl = ch->regList[reg->sub+FSR0L-FSR0L]; int x = (ch->ram[fsrh->id] | ch->ram[fsrl->id]) >> 8; int idx = (ch->ram[fsrh->id] << 8) | ch->ram[fsrl->id]; int w; switch(reg->id - sub->id) { case PLUSW0-FSR0L: w = ch->ram[WREG]; if (w & ~0xff) return 0xff00; ASSERT(w != 0x80); // manual is vague on this value if (w & 0x80) w -= 256; ASSERT(ch->plusw_savew < -128); // should be invalid ch->plusw_savew = w; idx += w; ASSERT(idx > 0x17f); ASSERT(idx < 0xf80); return x ? 0xff00 : ch->ram[idx]; case PREINC0-FSR0L: idx++; ASSERT(idx > 0x17f); ASSERT(idx < 0xf80); ch->ram[fsrh->id] = idx >> 8; ch->ram[fsrl->id] = idx & 0xff; return x ? 0xff00 : ch->ram[idx]; case POSTDEC0-FSR0L: case POSTINC0-FSR0L: case INDF0-FSR0L: ASSERT(idx > 0x17f); ASSERT(idx < 0xf80); return x ? 0xff00 : ch->ram[idx]; default: ASSERT(!"Bad reg in picRegWriteFsr"); } return -1; } #if 0 //=========================================================================== // picRegWriteGeneric() - generic reg write //=========================================================================== static int picRegWriteGeneric(picChip *ch, picReg *reg, int val) { return (ch->ram[reg->id] = val); } //=========================================================================== // picRegReadGeneric() - generic reg read //=========================================================================== static int picRegReadGeneric(picChip *ch, picReg *reg, int val) { return ch->ram[reg->id]; } #endif //=========================================================================== // picRegWrite() - reg write //=========================================================================== static int picRegWrite(picChip *ch, int id, int val) { picReg *reg; ASSERT((unsigned int)id < PIC_REG_CNT); if ((unsigned int)id >= PIC_REG_CNT) return -1; reg = ch->regList[id]; if (reg && reg->wr) { return reg->wr(ch,reg,val); } else { return (ch->ram[id] = val); } } //=========================================================================== // picRegRead() - reg read //=========================================================================== static int picRegRead(picChip *ch, int id) { picReg *reg; ASSERT((unsigned int)id < PIC_REG_CNT); if ((unsigned int)id >= PIC_REG_CNT) return -1; reg = ch->regList[id]; if (reg && reg->rd) { return reg->rd(ch,reg,0); } else { return ch->ram[id]; } } //=========================================================================== // picOpcodeName() - return name of opcode //=========================================================================== const char *picOpcodeName( picChip *chip, unsigned int op) { static char *opStr[] = { #define PIC_OPCODES_STR(f) #f, PIC_OPCODES(PIC_OPCODES_STR) 0 }; if (op < PIC_INST_CNT) { return opStr[op]; } return "???"; } //=========================================================================== // picRegName() - return name of reg (a string) //=========================================================================== const char *picRegName( picChip *chip, int id, int maxlen) { picChip *ch = chip ? chip : picCurChip; static char buf[100]; picReg *r; if (id==WREG) return "WREG"; if (id==STATUS) return "STATUS"; if (maxlen <=0 || maxlen > sizeof(buf)-1) maxlen = sizeof(buf)-1; snprintf(buf,maxlen, "reg[%03x]",id); buf[maxlen] = 0; if (!ch) return buf; for (r=ch->regs; r; r=r->next) { if (id == r->id) { snprintf(buf,maxlen, "reg[%03x](%s)",id,r->name); break; } } buf[maxlen] = 0; return buf; } //=========================================================================== // picRegCreate() - create a new register //=========================================================================== static picReg *picRegCreate( picChip *ch, int id, int sub, const char *name, picRegFunc r, picRegFunc w, const char *namespace) { picReg *reg = calloc(1,sizeof(picReg)); if (id < 0) { for (id=0; ch->regList[id]; id++); } ASSERT((unsigned int)id < PIC_REG_CNT); ASSERT(ch->regList[id] == 0); ch->regList[id] = reg; reg->rd = r; reg->wr = w; reg->name = strdup(name); reg->sub = sub; reg->id = id; reg->ns = picNamespaceFind(ch,namespace,1); if (!reg->ns) reg->ns = ch->ns_global; reg->next = ch->regs; ch->regs = reg; return reg; } //=========================================================================== // picChipReset() - reset chip //=========================================================================== void picChipReset(picChip *chip, enum picResetTypeEnum r) { picChip *ch = chip ? chip : picCurChip; if (r == PIC_RESET_POWERON) { memset(ch->ram, 0xff, sizeof(ch->ram)); } picRegWrite(ch,BSR,0); ch->skip = 0; ch->movff_tmp = -1; } //=========================================================================== // picChipSetCurrent() - Call this before running instructions //=========================================================================== int picChipSetCurrent(picChip *ch) { picCurChip = ch; return 0; } //=========================================================================== // picChipCreate() - create a pic chip //=========================================================================== // name - name to identify this chip // partnum - part number. e.g. pic18lf2525 // picChip *picChipCreate(const char *name, const char *partnum) { picChip *ch = calloc(1,sizeof(picChip)); // // init special registers // ch->plusw_savew = -1000; // // init register namespaces // ch->ns_sfr = picNamespaceFind(ch, 0, 1); ch->ns_global = picNamespaceFind(ch, 0, 1); ch->ns_param = picNamespaceFind(ch, 0, 1); ch->ns_inoutparam = picNamespaceFind(ch, 0, 1); ch->ns_return = picNamespaceFind(ch, 0, 1); ch->ns_local = picNamespaceFind(ch, 0, 1); ch->ns_sfr->findFunc = picRegFindFuncSfr; ch->ns_local->findFunc = picRegFindFuncLocal; ch->ns_param->findFunc = picRegFindFuncParam; ch->ns_inoutparam->findFunc = picRegFindFuncInOut; ch->ns_return->findFunc = picRegFindFuncReturn; ch->ns_global->findFunc = picRegFindFuncGlobal; ch->ns_sfr->name = picNamespaceSfr; ch->ns_local->name = picNamespaceLocal; ch->ns_param->name = picNamespaceParam; ch->ns_inoutparam->name = picNamespaceInOutParam; ch->ns_return->name = picNamespaceReturn; ch->ns_global->name = picNamespaceGlobal; // // init Special Function Registers (SFRs) // #define REGI(name,rd,wr,sub) picRegCreate(ch,name,sub,#name,rd,wr, \ picNamespaceSfr) REGI(FSR0L, 0, 0, FSR0L); REGI(FSR0H, 0, 0, FSR0L); REGI(INDF0, picRegReadFsr, picRegWriteFsr, FSR0L); REGI(POSTINC0, picRegReadFsr, picRegWriteFsr, FSR0L); REGI(POSTDEC0, picRegReadFsr, picRegWriteFsr, FSR0L); REGI(PREINC0, picRegReadFsr, picRegWriteFsr, FSR0L); REGI(PLUSW0, picRegReadFsr, picRegWriteFsr, FSR0L); REGI(FSR1L, 0, 0, FSR1L); REGI(FSR1H, 0, 0, FSR1L); REGI(INDF1, picRegReadFsr, picRegWriteFsr, FSR1L); REGI(POSTINC1, picRegReadFsr, picRegWriteFsr, FSR1L); REGI(POSTDEC1, picRegReadFsr, picRegWriteFsr, FSR1L); REGI(PREINC1, picRegReadFsr, picRegWriteFsr, FSR1L); REGI(PLUSW1, picRegReadFsr, picRegWriteFsr, FSR1L); REGI(FSR2L, 0, 0, FSR2L); REGI(FSR2H, 0, 0, FSR2L); REGI(INDF2, picRegReadFsr, picRegWriteFsr, FSR2L); REGI(POSTINC2, picRegReadFsr, picRegWriteFsr, FSR2L); REGI(POSTDEC2, picRegReadFsr, picRegWriteFsr, FSR2L); REGI(PREINC2, picRegReadFsr, picRegWriteFsr, FSR2L); REGI(PLUSW2, picRegReadFsr, picRegWriteFsr, FSR2L); #undef REGI #define REGI(name) picRegCreate(ch,name,-1,#name,0,0, \ picNamespaceSfr) REGI(WREG); REGI(STATUS); REGI(BSR); REGI(TBLPTRU); REGI(TBLPTRH); REGI(TBLPTRL); REGI(TABLAT); REGI(PRODH); REGI(PRODL); #undef REGI ch->flashSize = PIC_FLASH_BANK_BYTES * PIC_FLASH_BANK_CNT; picChipReset(ch, PIC_RESET_POWERON); return ch; } //=========================================================================== // picChipDestroy() - destroy a pic chip //=========================================================================== void picChipDestroy(picChip *ch) { ASSERT(!"Unimplemented"); } //=========================================================================== // picRegX() - get which bits are unknown //=========================================================================== unsigned int picRegX(picChip *chip, int id) { picChip *ch = chip ? chip : picCurChip; ASSERT(ch); return (picRegRead(ch,id) >> 8) & 0xff; } //=========================================================================== // picRegValU() - get unsigned register value //=========================================================================== unsigned int picRegValU(picChip *chip, int id) { picChip *ch = chip ? chip : picCurChip; ASSERT(ch); return picRegRead(ch,id) & 0xff; } //=========================================================================== // picRegValS() - get signed register value //=========================================================================== signed int picRegValS(picChip *chip, int id) { picChip *ch = chip ? chip : picCurChip; int val = picRegRead(ch,id) & 0xff; ASSERT(ch); if (val & 0x80) val = -((-val)&0xff); return val; } //=========================================================================== // picRegSet() - set register values //=========================================================================== void picRegSet(picChip *chip, int id, int val) { picChip *ch = chip ? chip : picCurChip; ASSERT(ch); picRegWrite(ch,id,val & 0xff); } //=========================================================================== // picRegSet32() - set up to 32 bit reg val //=========================================================================== void picRegSet32(picChip *chip, int id0, int id1, int id2, int id3, int val) { picChip *ch = chip ? chip : picCurChip; ASSERT(ch); picRegWrite(ch,id0, (val) & 0xff); if (id1<0) return; picRegWrite(ch,id1, (val>>8) & 0xff); if (id2<0) return; picRegWrite(ch,id2, (val>>16) & 0xff); if (id3<0) return; picRegWrite(ch,id3, (val>>24) & 0xff); } //=========================================================================== // picRegValU32() - get up to 32 bit unsigned reg val //=========================================================================== unsigned int picRegValU32(picChip *chip, int id0, int id1, int id2, int id3) { picChip *ch = chip ? chip : picCurChip; int val; ASSERT(ch); val = (picRegRead(ch,id0) & 0xff); if (id1<0) return val; val |= (picRegRead(ch,id1) & 0xff) << 8; if (id2<0) return val; val |= (picRegRead(ch,id2) & 0xff) << 16; if (id3<0) return val; val |= (picRegRead(ch,id3) & 0xff) << 24; return val; } //=========================================================================== // picRegValS32() - get up to 32 bit signed reg val //=========================================================================== signed int picRegValS32(picChip *chip, int id0, int id1, int id2, int id3) { picChip *ch = chip ? chip : picCurChip; int val; int mask; ASSERT(ch); ASSERT(sizeof(val) == 4); do { val = (picRegRead(ch,id0) & 0xff); mask = 0x80; if (id1<0) break; val |= (picRegRead(ch,id1) & 0xff) << 8; mask = 0x8000; if (id2<0) break; val |= (picRegRead(ch,id2) & 0xff) << 16; mask = 0x8000; if (id3<0) break; val |= (picRegRead(ch,id3) & 0xff) << 24; return val; } while(0); if (val & mask) { val = -((-val) & (mask | (mask-1))); } return val; } //=========================================================================== // picRegX32() - get up to 32 bit reg unknown bits //=========================================================================== unsigned int picRegX32(picChip *chip, int id0, int id1, int id2, int id3) { picChip *ch = chip ? chip : picCurChip; int val; ASSERT(ch); val = (picRegRead(ch,id0) & 0xff00) >> 8; if (id1<0) return val; val |= (picRegRead(ch,id1) & 0xff00); if (id2<0) return val; val |= (picRegRead(ch,id2) & 0xff00) << 8; if (id3<0) return val; val |= (picRegRead(ch,id3) & 0xff00) << 16; return val; } //=========================================================================== // picRegEraseRange() - erase several register values (for debug) //=========================================================================== void picRegEraseRange(picChip *chip, int firstId, int lastId) { picChip *ch = chip ? chip : picCurChip; ASSERT(ch); ASSERT(firstId <= lastId); while(firstId <= lastId) { picRegWrite(ch,firstId,-1); firstId++; } } //=========================================================================== // picRegErase() - erase register value (for debug) //=========================================================================== void picRegErase(picChip *chip, int id) { picChip *ch = chip ? chip : picCurChip; ASSERT(ch); picRegWrite(ch,id,-1); } //=========================================================================== // picRegFind() - variable declaration //=========================================================================== int picRegFind(picChip *chip, const char *name, const char *namespace) { picChip *ch = chip ? chip : picCurChip; picReg *r = ch->regs; ASSERT(ch); for (r = ch->regs; r; r=r->next) { if (!strcmp(name, r->name)) { picRegNamespace *ns = picNamespaceFind(ch, namespace, 0); ns = ns ? ns : r->ns; ns->findFunc(ch,r,0); return r->id; } } r = picRegCreate(ch, -1, -1, name, 0, 0, namespace); picRegErase(ch,r->id); ASSERT(r && r->id >= 0); return r->id; } //=========================================================================== // picFlashBank() - get bank containing the address //=========================================================================== static short *picFlashBank(picChip *ch, int addr) { int bank = addr >> PIC_FLASH_BANK_BYTES_LOG2; short *ptr; if ((unsigned long)addr > ch->flashSize) return 0; ptr = ch->flash[bank]; if (!ptr) { ptr = malloc(PIC_FLASH_BANK_BYTES * 2); memset(ptr,0xff,PIC_FLASH_BANK_BYTES * 2); ch->flash[bank] = ptr; } return ptr; } //=========================================================================== // picReadFlash() - read flash memory byte (for debug) //=========================================================================== int picReadFlash(picChip *chip, int addr) { picChip *ch = chip ? chip : picCurChip; short *ptr = picFlashBank(ch,addr); ASSERT(ptr); if (!ptr) return 0xffff; ptr += addr & ((1UL<<PIC_FLASH_BANK_BYTES_LOG2)-1); return *ptr; } //=========================================================================== // picWriteFlash() - write flash memory byte (immediate - for debug) //=========================================================================== void picWriteFlash(picChip *chip, int addr, int val) { picChip *ch = chip ? chip : picCurChip; short *ptr = picFlashBank(ch,addr); ASSERT(ptr); if (!ptr) return; ptr += addr & ((1UL<<PIC_FLASH_BANK_BYTES_LOG2)-1); *ptr = val & 0xff; } //=========================================================================== // picReadFlashInstr() - read flash memory byte (from instruction) //=========================================================================== static int picReadFlashInstr(picChip *ch, int addr) { return picReadFlash(ch,addr); } //=========================================================================== // picWriteFlashInstr() - write flash memory byte (from instruction) //=========================================================================== static void picWriteFlashInstr(picChip *ch, int addr, int val) { ASSERT(!"picWriteFlashInstr() not supported yet"); } //=========================================================================== // picCalcStatus() - calc status of a result //=========================================================================== static void picCalcStatus(picChip *ch, int r, int rx, int mask) { int s = ((r>>8) & 0x01) | // C ((r>>3) & 0x10) | // N ((r&0xff) ? 0 : ST_Z); // Z mask &= 0x1f; s &= mask; mask |= mask<<8; if (rx) { s |= mask & 0x1f00; } ch->ram[STATUS] = (ch->ram[STATUS] & ~mask) | (s & mask); } //=========================================================================== // picCalcAdd() - calc sum //=========================================================================== static int picCalcAdd( picChip *ch, int a, int b, int neg, int use_carry, int rx) { int ah,bh; int r,rh,s; int c = neg ? 1 : 0; b = neg ? ~b : b; a &= 0xff; b &= 0xff; ah = a & 0xf; bh = b & 0xf; if (use_carry) { c = ch->ram[STATUS] & 1; rx |= ch->ram[STATUS] & (ST_C<<8); } r = a + b + c; rh = ah + bh + c; s = ((r>>8) & 0x01) | // C ((r>>3) & 0x10) | // N ((r&0xff) ? 0 : ST_Z) | // Z ((((a ^ ~b) & (a ^ r)) & 0x80) >> 4) | // OV ((rh>>3) & 0x2); // DC r &= 0xff; if (rx) { s |= 0x1f00; } ch->ram[STATUS] = s; return r; } #define PIC_TESTS 1 #if PIC_TESTS //=========================================================================== // picTestAdd() - test adds //=========================================================================== static void picTestAdd(void) { picChip *ch = picChipCreate("test","pic18f2525"); int a,b,ic,in; int r, c, ov, z, n; int gr,gc,gov,gz,gn; for (a=0; a<0x100; a++) { for (b=0; b<0x100; b++) { for (ic=0; ic<3; ic++) { for (in=0; in<2; in++) { ch->ram[STATUS] = ic; r = picCalcAdd(ch,a,b,in,ic!=2,0); gov = 0; if (in) { switch(ic) { case 0: gr = (a-b-1) & 0xff; if (a>=b+1) gr |= 0x100; break; case 1: case 2: gr = (a-b) & 0xff; if (a>=b) gr |= 0x100; break; default: ASSERT(0); } } else { gr = (a+b+(ic&1)); } gc = (gr & 0x100) ? 1 : 0; gr &= 0xff; gn = (gr & 0x080) ? 1 : 0; gz = (gr) ? 0 : 1; c = (ch->ram[STATUS] & ST_C) ? 1 : 0; n = (ch->ram[STATUS] & ST_N) ? 1 : 0; z = (ch->ram[STATUS] & ST_Z) ? 1 : 0; ov = (ch->ram[STATUS] & ST_OV) ? 1 : 0; gr &= 0xff; if (r != gr || c != gc || z != gz || n != gn) { printf("a= %02x\n",a); printf("b= %02x neg=%d c=%d\n",b,in,ic); printf("r=%02x %02x\n",r,gr); printf("c=%2x %2x\n",c,gc); printf("z=%2x %2x\n",z,gz); printf("n=%2x %2x\n",n,gn); } ASSERT(r == gr); ASSERT(c == gc); ASSERT(z == gz); ASSERT(n == gn); //ASSERT(ov == gov); }}}} } #endif //=========================================================================== // picOpTrace() - print trace info for an opcode //=========================================================================== void picOpTrace( picChip *ch, const char *file, int line, int op, int regId, int dst, int imm, int oldf, int result, int resultx, const char *dbstr) { if (ch->trace) { const char *rn = regId==-1 ? "" : picRegName(ch,regId,25); int stat = picRegValU(ch,STATUS); int statx = picRegX(ch,STATUS); printf("%s:%-5d ", file,line); if (dst == PICDST_W || dst == PICDST_F || dst == PICDST_READF) { if (imm != -1) { printf(" %-27s=%02x%s ", "immediate", imm, " "); } else if (regId != -1) { printf(" f=%-25s=%02x%s ", rn, oldf&0xff, oldf&~0xff?"?":" "); } else { printf(" %31s ",""); } printf(" w=%02x%s %-6s ", ch->ram[WREG]&0xff, ch->ram[WREG]&~0xff?"?":" ", picOpcodeName(ch,op)); if (dst == PICDST_W) { printf("%s%02x->%-25s", (resultx)?"?":" ", (result)&0xff, "w"); } else if (dst == PICDST_F) { printf("%s%02x->%-25s", (resultx)?"?":" ", (result)&0xff, rn); } else { printf("%-30s",dbstr?dbstr:""); dbstr = 0; } } else { printf(" %31s w=%02x%s %-6s %-30s", "", ch->ram[WREG]&0xff, ch->ram[WREG]&~0xff?"?":" ", picOpcodeName(ch,op), dbstr?dbstr:""); dbstr = 0; } printf(" S=%02x %s%s%s%s%s %s", stat&0xff, statx&ST_C ?"?":stat&ST_C ?"C":"c", statx&ST_DC?"?":stat&ST_DC?"D":"d", statx&ST_Z ?"?":stat&ST_Z ?"Z":"z", statx&ST_OV?"?":stat&ST_OV?"V":"v", statx&ST_N ?"?":stat&ST_N ?"N":"n", ch->skip ? "<<SKIP-NEXT>>" : ""); if (regId >= INDF0 && regId <= PLUSW0) { printf(" using FSR0=%02x%02x", picRegValU(ch,FSR0H), picRegValU(ch,FSR0L)); } if (regId >= INDF1 && regId <= PLUSW1) { printf(" using FSR1=%02x%02x", picRegValU(ch,FSR1H), picRegValU(ch,FSR1L)); } if (regId >= INDF2 && regId <= PLUSW2) { printf(" using FSR2=%02x%02x", picRegValU(ch,FSR2H), picRegValU(ch,FSR2L)); } if (dbstr) { printf(" %s",dbstr); } printf(" \n"); } } //=========================================================================== // picInstDB() - run 1 instruction //=========================================================================== int picInstDB(int regId, int dst, picOpcode op, const char *file, int line, const char *dbstr) { picChip *ch = picCurChip; int rx, fx, wx; int r, f; int w = ch->ram[WREG]; int s = ch->ram[STATUS]; int s_ok = 0; int bit; int oldf; int imm = -1; char dbstr2[30]; if (op == PIC_LABEL) { if (ch->trace) { printf(" %s:\n",dbstr?dbstr:""); } return 1; } ch->cycle++; if (ch->skip) { if (op != PIC_MOVFFa && op != PIC_LFSRa) { ch->skip = 0; } if (ch->trace) { printf("%s:%-5d <skip %s>\n", file,line, picOpcodeName(ch,op)); } return 0; } switch(op) { case PIC_NOP: if (ch->trace) { picOpTrace(ch, file, line, op, -1, 0, -1, -1, 0, 0, dbstr); } return 0; case PIC_MOVWF: break; case PIC_BCF: case PIC_BSF: case PIC_BTFSC: case PIC_BTFSS: case PIC_BTG: s_ok = 1; ASSERT(dst >= PICDST_BIT0 && dst <= PICDST_BIT0+7); bit = 1<<(dst - PICDST_BIT0); ASSERT(bit > 0 && bit < 0x100); dst = PICDST_F; // fall through case PIC_ADDWF: case PIC_ADDWFC: case PIC_ANDWF: case PIC_CLRF: case PIC_COMF: case PIC_CPFSEQ: case PIC_CPFSGT: case PIC_CPFSLT: case PIC_DECF: case PIC_DECFSZ: case PIC_DCFSNZ: case PIC_INCF: case PIC_INCFSZ: case PIC_INFSNZ: case PIC_IORWF: case PIC_MOVF: case PIC_MOVFFa: case PIC_MOVFFb: case PIC_MULWF: case PIC_NEGF: case PIC_RLCF: case PIC_RLNCF: case PIC_RRCF: case PIC_RRNCF: case PIC_SETF: case PIC_SUBFWB: case PIC_SUBWF: case PIC_SUBWFB: case PIC_SWAPF: case PIC_TSTFSZ: case PIC_XORWF: f = picRegRead(ch,regId); break; case PIC_BC: ASSERT((ch->ram[STATUS] & (ST_C<<8)) == 0); if (ch->trace) { picOpTrace(ch, file, line, op, -1, 0, -1, -1, 0, 0, dbstr); } return ch->ram[STATUS] & ST_C; case PIC_BNC: ASSERT((ch->ram[STATUS] & (ST_C<<8)) == 0); if (ch->trace) { picOpTrace(ch, file, line, op, -1, 0, -1, -1, 0, 0, dbstr); } return ~ch->ram[STATUS] & ST_C; case PIC_BN: ASSERT((ch->ram[STATUS] & (ST_N<<8)) == 0); if (ch->trace) { picOpTrace(ch, file, line, op, -1, 0, -1, -1, 0, 0, dbstr); } return ch->ram[STATUS] & ST_N; case PIC_BNN: ASSERT((ch->ram[STATUS] & (ST_N<<8)) == 0); if (ch->trace) { picOpTrace(ch, file, line, op, -1, 0, -1, -1, 0, 0, dbstr); } return ~ch->ram[STATUS] & ST_N; case PIC_BOV: ASSERT((ch->ram[STATUS] & (ST_OV<<8)) == 0); if (ch->trace) { picOpTrace(ch, file, line, op, -1, 0, -1, -1, 0, 0, dbstr); } return ch->ram[STATUS] & ST_OV; case PIC_BNOV: ASSERT((ch->ram[STATUS] & (ST_OV<<8)) == 0); if (ch->trace) { picOpTrace(ch, file, line, op, -1, 0, -1, -1, 0, 0, dbstr); } return ~ch->ram[STATUS] & ST_OV; case PIC_BNZ: ASSERT((ch->ram[STATUS] & (ST_Z<<8)) == 0); if (ch->trace) { picOpTrace(ch, file, line, op, -1, 0, -1, -1, 0, 0, dbstr); } return ~ch->ram[STATUS] & ST_Z; case PIC_BZ: ASSERT((ch->ram[STATUS] & (ST_Z<<8)) == 0); if (ch->trace) { picOpTrace(ch, file, line, op, -1, 0, -1, -1, 0, 0, dbstr); } return ch->ram[STATUS] & ST_Z; case PIC_BRA: case PIC_GOTO: case PIC_CALL: case PIC_RCALL: case PIC_RETURN: if (ch->trace) { picOpTrace(ch, file, line, op, -1, 0, -1, -1, 0, 0, dbstr); } return 1; case PIC_DAW: case PIC_CLRWDT: case PIC_POP: case PIC_PUSH: case PIC_RETFIE: case PIC_SLEEP: ASSERT(!"Unimplemented op"); return 0; case PIC_RESET: picChipReset(ch, PIC_RESET_INSTRUCTION); if (ch->trace) { picOpTrace(ch, file, line, op, -1, 0, -1, -1, 0, 0, dbstr); } return 1; case PIC_RETLW: case PIC_ADDLW: case PIC_ANDLW: case PIC_IORLW: case PIC_MOVLW: case PIC_MULLW: case PIC_SUBLW: case PIC_XORLW: ASSERT((dst & ~0xffUL) == 0 || ((dst+0x100) & ~0xffUL) == 0); f = dst & 0xff; dst = PICDST_W; regId = -1; imm = f; break; case PIC_MOVLB: // // BSR != 0 is not supported in red/write funcs yet // ASSERT(dst == 0); picRegSet(ch, BSR, dst); if (ch->trace) { picOpTrace(ch, file, line, op, BSR, PICDST_F, ch->ram[BSR], -1, ch->ram[BSR], 0, dbstr); } return 1; case PIC_LFSRa: ASSERT( regId == FSR0L || regId == FSR1L || regId == FSR2L); // // dst holds immediate value // f = ch->ram[regId]; ch->movff_tmp = ch->ram[regId+FSR0H-FSR0L]; picRegSet32(ch, regId, regId+FSR0H-FSR0L, -1, -1, dst); break; case PIC_LFSRb: ASSERT( regId == FSR0H || regId == FSR1H || regId == FSR2H); f = ch->movff_tmp; break; case PIC_TBLRD_PREINC: case PIC_TBLWT_PREINC: r = picRegValU32(ch, TBLPTRL, TBLPTRH, TBLPTRU, -1); r++; picRegSet32(ch, TBLPTRL, TBLPTRH, TBLPTRU, -1, r); break; case PIC_TBLRD_POSTINC: case PIC_TBLWT_POSTINC: r = picRegValU32(ch, TBLPTRL, TBLPTRH, TBLPTRU, -1); picRegSet32(ch, TBLPTRL, TBLPTRH, TBLPTRU, -1, r+1); break; case PIC_TBLRD_POSTDEC: case PIC_TBLWT_POSTDEC: r = picRegValU32(ch, TBLPTRL, TBLPTRH, TBLPTRU, -1); picRegSet32(ch, TBLPTRL, TBLPTRH, TBLPTRU, -1, r-1); break; case PIC_TBLRD: case PIC_TBLWT: r = picRegValU32(ch, TBLPTRL, TBLPTRH, TBLPTRU, -1); break; default: ASSERT(!"bad opcode"); return 0; } oldf = f; r = f; rx = wx = fx = 0; if ((w | f) & ~0xffUL) { rx = ~0xffUL; wx = rx & w; fx = rx & f; w = w & 0xff; f = f & 0xff; } switch(op) { case PIC_NOP: break; case PIC_ADDLW: r = picCalcAdd(ch, f, w, 0,0, rx); break; case PIC_ADDWF: r = picCalcAdd(ch, f, w, 0,0, rx); break; case PIC_ADDWFC: r = picCalcAdd(ch, f, w, 0,1, rx); break; case PIC_SUBFWB: r = picCalcAdd(ch, w, f, 1,1, rx); break; case PIC_SUBWFB: r = picCalcAdd(ch, f, w, 1,1, rx); break; case PIC_SUBWF: r = picCalcAdd(ch, f, w, 1,0, rx); break; case PIC_SUBLW: r = picCalcAdd(ch, f, w, 1,0, rx); break; case PIC_DECF: rx = fx; r = picCalcAdd(ch, f, 1, 1, 0, rx); break; case PIC_INCF: rx = fx; r = picCalcAdd(ch, f, 1, 0, 0, rx); break; case PIC_NEGF: rx = fx; r = picCalcAdd(ch, 0, f, 1, 0, rx); dst = PICDST_F; break; case PIC_DECFSZ: r = (f - 1) & 0xff; ch->skip = (r==0); rx = fx; ASSERT(!rx); break; case PIC_DCFSNZ: r = (f - 1) & 0xff; ch->skip = (r!=0); rx = fx; ASSERT(!rx); break; case PIC_INCFSZ: r = (f + 1) & 0xff; ch->skip = (r==0); rx = fx; ASSERT(!rx); break; case PIC_INFSNZ: r = (f + 1) & 0xff; ch->skip = (r!=0); rx = fx; ASSERT(!rx); break; case PIC_ANDLW: case PIC_ANDWF: r = w & f; picCalcStatus(ch, r, rx, ST_Z|ST_N); break; case PIC_IORLW: case PIC_IORWF: r = w | f; picCalcStatus(ch, r, rx, ST_Z|ST_N); break; case PIC_XORLW: case PIC_XORWF: r = w ^ f; picCalcStatus(ch, r, rx, ST_Z|ST_N); break; case PIC_MOVF: r = f; rx = fx; picCalcStatus(ch, r, rx, ST_Z|ST_N); break; case PIC_LFSRa: case PIC_LFSRb: r = ch->ram[regId]; rx = 0; dst = PICDST_F; break; case PIC_COMF: r = ~f; rx = fx; picCalcStatus(ch, r, rx, ST_Z|ST_N); break; case PIC_CLRF: r = rx = 0; s |= ST_Z; s |= ST_Z<<8; // suspicious - do not depend on it ch->ram[STATUS] = s; dst = PICDST_F; break; case PIC_SETF: r = 0xff; rx = 0; dst = PICDST_F; break; case PIC_RLCF: r = (f << 1) | (s & 1); s = (s & ~1UL) | ((r >> 8) & 1); rx = 0; if (fx | (s&0x0100)) { rx = 0xff00; s |= 0x0100; } r &= 0xff; ch->ram[STATUS] = s; break; case PIC_RRCF: r = (f >> 1) | ((s & 1) << 7); s = (s & ~1UL) | (f & 1); rx = 0; if (fx | (s&0x0100)) { rx = 0xff00; s |= 0x0100; } ch->ram[STATUS] = s; break; case PIC_RLNCF: r = ((f << 1) | (f >> 7)) & 0xff; rx = ((fx << 1) | (fx >> 7)) & 0xff00; picCalcStatus(ch, r, rx, ST_Z|ST_N); break; case PIC_RRNCF: r = ((f >> 1) | (f << 7)) & 0xff; rx = ((fx >> 1) | (fx << 7)) & 0xff00; picCalcStatus(ch, r, rx, ST_Z|ST_N); break; case PIC_SWAPF: r = ((f >> 4) | (f << 4)) & 0xff; rx = ((fx >> 4) | (fx << 4)) & 0xff00; break; case PIC_CPFSEQ: ASSERT(!rx); ch->skip = (f == w); dst = PICDST_READF; break; case PIC_CPFSGT: ASSERT(!rx); ch->skip = (f > w); dst = PICDST_READF; break; case PIC_CPFSLT: ASSERT(!rx); ch->skip = (f < w); dst = PICDST_READF; break; case PIC_TSTFSZ: ASSERT(!fx); ch->skip = (f == 0); dst = PICDST_READF; break; case PIC_MOVFFa: ch->movff_tmp = f | fx; dst = PICDST_READF; break; case PIC_MOVFFb: r = ch->movff_tmp; rx = r & 0xff00; r = r & 0xff; dst = PICDST_F; break; case PIC_MOVWF: r = w; rx = wx; dst = PICDST_F; break; case PIC_MULLW: case PIC_MULWF: r = w * f; ch->ram[PRODH] = rx | (r >> 8); ch->ram[PRODL] = rx | (r & 0xff); dst = PICDST_READF; if (ch->trace) { snprintf(dbstr2,sizeof(dbstr2), "%02x%02x->PROD", ch->ram[PRODH], ch->ram[PRODL]); dbstr = dbstr2; } break; case PIC_BCF: r = f & ~bit; rx = fx & ~bit; break; case PIC_BSF: r = f | bit; rx = fx & ~bit; break; case PIC_BTG: r = f ^ bit; rx = fx; break; case PIC_BTFSC: ASSERT(!(bit & fx)); ch->skip = (~f & bit); dst = PICDST_READF; break; case PIC_BTFSS: ASSERT(!(bit & fx)); ch->skip = (f & bit); dst = PICDST_READF; break; case PIC_CLRWDT: case PIC_DAW: case PIC_POP: case PIC_PUSH: case PIC_SLEEP: ASSERT(!"Unsupported"); return 0; case PIC_TBLRD: case PIC_TBLRD_POSTINC: case PIC_TBLRD_POSTDEC: case PIC_TBLRD_PREINC: ch->ram[TABLAT] = picReadFlashInstr(ch,r); if (ch->trace) { printf("%s:%-5d TABLE READ rom[%06x]: %02x\n", file,line, r,ch->ram[TABLAT]); } if (ch->trace) { picOpTrace(ch, file, line, op, TABLAT, 0, -1, -1, ch->ram[TABLAT],ch->ram[TABLAT]&~0xff, dbstr); } return 1; case PIC_TBLWT: case PIC_TBLWT_POSTINC: case PIC_TBLWT_POSTDEC: case PIC_TBLWT_PREINC: picWriteFlashInstr(ch,r,ch->ram[TABLAT]); if (ch->trace) { picOpTrace(ch, file, line, op, -1, 0, -1, ch->ram[TABLAT], ch->ram[TABLAT], ch->ram[TABLAT]&~0xff, dbstr); } return 1; case PIC_MOVLW: case PIC_RETLW: r = f; rx = fx; break; default: ASSERT(!"bad opcode"); return 0; } // // most instructions should not be used with status reg // ASSERT(regId != STATUS || s_ok); // // BSR is not supported yet in picRegRead, picRegWrite, etc. // ASSERT(regId != BSR); if (ch->trace) { picOpTrace(ch, file, line, op, regId, dst, imm, oldf, r, rx, dbstr); } switch(dst) { case PICDST_READF: case PICDST_NONE: break; case PICDST_W: ch->ram[WREG] = r | rx; if (regId == WREG) regId = -1; break; case PICDST_F: f = r; fx = rx; ASSERT(regId >= 0); break; default: ASSERT(!"bad dst"); return 0; } if (regId >= 0) { picRegWrite(ch, regId, f | fx); } return 1; } //########################################################################### //############################### DEBUG CODE ################################ //########################################################################### //=========================================================================== // picTrace() - enable/disable tracing //=========================================================================== int picTrace(int enable) { int old = 0; if (!picCurChip) return -1; old = picCurChip->trace; picCurChip->trace = enable; return old; } //=========================================================================== // picGetCycle() - get cycle count //=========================================================================== int picGetCycle(void) { if (!picCurChip) return -1; return picCurChip->cycle; } //=========================================================================== // picSetCycle() - set cycle count //=========================================================================== void picSetCycle(int cyc) { if (!picCurChip) return; picCurChip->cycle = cyc; } //=========================================================================== // pr() - print register //=========================================================================== int pr(int id) { int x; int val = -1; if (!picCurChip) return -1; val = picRegValU(picCurChip,id); x = picRegX(picCurChip,id); printf("%20s = %02x", picRegName(picCurChip,id,0), val); if (x) { printf(" UNKNOWN BITS: %02x",x&0xff); } printf("\n"); return val; } //=========================================================================== // prr() - print register range //=========================================================================== int prr(int first,int last) { int val; int start = 1; char x[17]; char *xp = x; if (last<first) { printf("first>last\n"); return -1; } for(;first<=last; first++) { if (start || (first & 0xf) == 0) { if (!start) { *xp = 0; printf(" %s\n",x); } printf("%06x: ",first); start=0; xp = x; } val = picRegValU(picCurChip,first); printf("%02x ",val&0xff); *(xp++) = (val & ~0xff) ? '?' : '.'; } printf("\n"); return 0; } //=========================================================================== // pfsr() - print fsr //=========================================================================== int pfsr(int id) { int val,h,l,reg; if (!picCurChip) return -1; switch(id) { case 0: reg = FSR0L; break; case 1: reg = FSR1L; break; case 2: reg = FSR2L; break; default: printf("bad fsr %d\n",id); return -1; } h = picRegValU(0,reg+FSR0H-FSR0L); l = picRegValU(0,reg); val = picRegValU(0,(h<<8)+l); printf("FSR%d = 0x%02x%02x *=0x%02x\n",id,h,l,val); return val; } //=========================================================================== // picTest() - run test suite //=========================================================================== void picTest(void) { #if PIC_TESTS picTestAdd(); //printf("picTest() pass!"); #endif } |
This file Copyright (C) 2006 by Nathan (Acorn) Pooley
Go to TOP Wand page
Go to Acorn's personal webpage
Go to Hogwarts website: www.gotohogwarts.com
Snout: www.snout.org/game
Gadgets of Justice Unlimited
Snout GC (Wiki)
Snout Wiki
File created by do_doc at Wed May 30 03:28:42 PDT 2007