/* ======================================================================= C25LIB.C - Library of routines for building TMS320C25 simulators Copyright (C) 1995 Will Ware 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 Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. ======================================================================= */ #include "stdio.h" #include "stdlib.h" #include "string.h" #include "conio.h" #include "c25lib.h" extern void __write(char *s); /* ======================================================================= */ /* #define statements */ /* ======================================================================= */ #define X(z) #define NUM_OPCODES (sizeof(opcodes) / sizeof(opcodes[0])) #define MAX_NUM_BRKPTS 100 #define read_bit(var, bit) ((int) (((var) >> (bit)) & 1)) #define set_bit(var, flag, bit) \ var = (var & ~(1 << bit)) | (flag ? (1 << bit) : 0) #define SIGN_BIT 0x80000000L #define sign32(x) ((x) & SIGN_BIT) #define phex(n) { sprintf(toprint, "%04X ", n); __write(toprint); } #define plhex(n) { sprintf(toprint, "%08lX ", n); __write(toprint); } typedef void (*voidfunc) (void); typedef struct Sspecmem { int addr, rdef, wdef; } specmem; typedef struct Smemblk { char prog_data, high_addr; int contents[256]; struct Smemblk *next; } memblk; typedef struct Sinstruction_format { char *pattern, cycle_type; voidfunc f, rpt_prep; char *opname; } instruction_format; typedef struct Sbitmask_format { int andmask, pattern; } bitmask_format; /* ======================================================================= */ /* Public Functions */ /* ======================================================================= */ int *program_memory_address(int a); void write_program_memory(int a, int d); int read_program_memory(int a); int *data_memory_address(int a); void write_data_memory(int a, int d); int read_data_memory(int a); void advance(void); void initialize_simulator(void); void c25_reset(void); void c25_interrupt(enum int_type n); void load_hex_files(char *word); void load_map_file(char *word); int lookup_symbol(char *name); char * disassemble(int instruc); int print_matching_symbols(int a); int print_all_symbols(void); void short_report(void); void long_report(void); void add_breakpoint(int a); void delete_breakpoint(int a); void clear_all_breakpoints(void); int go_til_breakpoint(long int n); /* ======================================================================= */ /* Static Functions */ /* ======================================================================= */ static memblk *allot_block(char p_d, char high_addr); static memblk *search_for_block(char p_d, char hi_addr); static memblk *find_prog_block(char hi_addr); static memblk *find_data_block(char hi_addr); static int in_block_b0(int a); static int on_chip_rom(int a); static int on_chip_ram(int a); static int get_address(void); static void sign_extend(long int *x); static void fetch_operand(void); static void store_result(int x); static int detect_overflow(long number_added); static void saturate_overflow(long number_added); static void add_operand(int c_in); static void sub_operand(int c_in); static void cb(int flag); static void cbs(int flag, int dest); static void shift_operand(void); static void long_immediate_with_shift(void); static long int shifted_p(void); static void repeat_instruction(void); static int c25_hardware_pop(void); static void c25_hardware_push(int d); static void check_dmov_okay(int addr, char *instruc_name); static void handle_non_branch(int a, int pi_di, int pi_de, int pe_di, int pe_de, int pr_di, int pr_de); static void handle_branch(int a, int pi_di_i, int pi_de_i, int pe_di_i, int pe_de_i, int pr_di_i, int pr_de_i, int pi_di_r, int pi_de_r, int pe_di_r, int pe_de_r, int pr_di_r, int pr_de_r, int pi_di_e, int pi_de_e, int pe_di_e, int pe_de_e, int pr_di_e, int pr_de_e); static int get_pmem_wait_states(int addr); static int get_dmem_wait_states(int addr); static int lookup(int instruc); static void burn_cycles(int cycle_type, int n); static void service_pending_interrupts(void); static void Abs(void); static void Add(void); static void Addc(void); static void Addh(void); static void Addk(void); static void Adds(void); static void Addt(void); static void Adlk(void); static void Adrk(void); static void And(void); static void Andk(void); static void Apac(void); static void B(void); static void Bacc(void); static void Banz(void); static void Bbnz(void); static void Bbz(void); static void Bc(void); static void Bgez(void); static void Bgz(void); static void Bioz(void); static void Bit(void); static void Bitt(void); static void Blez(void); static void Blkd_rpt_prep(void); static void Blkd(void); static void Blkp(void); static void Blz(void); static void Bnc(void); static void Bnv(void); static void Bnz(void); static void Bv(void); static void Bz(void); static void Cala(void); static void Call(void); static void Cmpl(void); static void Cmpr(void); static void Cnfd(void); static void Cnfp(void); static void Dint(void); static void Dmov(void); static void Eint(void); static void Fort(void); static void Idle(void); static void In(void); static void Lac(void); static void Lack(void); static void Lact(void); static void Lalk(void); static void Lar(void); static void Lark(void); static void Larp(void); static void Ldp(void); static void Ldpk(void); static void Lph(void); static void Lrlk(void); static void Lst(void); static void Lst1(void); static void Lt(void); static void Lta(void); static void Ltd(void); static void Ltp(void); static void Lts(void); static void Mac(void); static void Macd(void); static void Mar(void); static void Mpy(void); static void Mpya(void); static void Mpyk(void); static void Mpys(void); static void Mpyu(void); static void Neg(void); static void Nop(void); static void Norm(void); static void Or(void); static void Ork(void); static void Out(void); static void Pac(void); static void Pop(void); static void Popd(void); static void Pshd(void); static void Push(void); static void Rc(void); static void Ret(void); static void Rfsm(void) ; static void Rhm(void) ; static void Rol(void); static void Ror(void); static void Rovm(void); static void Rpt(void); static void Rptk(void); static void Rsxm(void); static void Rtc(void); static void Rtxm(void); static void Rxf(void); static void Sach(void); static void Sacl(void); static void Sar(void); static void Sblk(void); static void Sbrk(void); static void Sc(void) ; static void Sfl(void); static void Sfr(void); static void Sfsm(void); static void Shm(void); static void Sovm(void); static void Spac(void); static void Sph(void); static void Spl(void); static void Spm(void); static void Sqra(void); static void Sqrs(void); static void Sst(void); static void Sst1(void); static void Ssxm(void); static void Stc(void); static void Stxm(void); static void Sub(void); static void Subb(void); static void Subc(void); static void Subh(void); static void Subk(void); static void Subs(void); static void Subt(void); static void Sxf(void); static void Tblr_rpt_prep(void); static void Tblr(void); static void Tblw(void); static void Trap(void); static void Xor(void); static void Xork(void); static void Zac(void); static void Zalh(void); static void Zalr(void); static void Zals(void); /* ======================================================================= */ /* Public Variables */ /* ======================================================================= */ /* C25 registers */ int arp, ov, ovm, intm, dp; /* st0 */ int arb, cnf, tc, sxm, c, hm, fsm, xf, fo, txm, pm; /* st1 */ long int accumulator, p_register; unsigned int pc; int t_register, _stack[8], _sp, ar[8]; int mp_mc_mode; int ports[16], bio; int drr, dxr, tim, prd, imr, greg; unsigned long int steps_taken, cycles; int warn_progmem_writes; iufunc pwaitf = NULL, dwaitf = NULL, iwaitf = NULL; /* ======================================================================= */ /* Static Variables */ /* ======================================================================= */ static char toprint[100]; static bitmask_format opcode_masks[200]; static int instruction, operand_address, branch_condition, branch_destination; static int pending_interrupts; static int port_addr, new_allotment, idle_mode = 0; static long int operand, old_accum; static int pfc, repeating, rptc; static memblk *first_memblk = NULL; static char fname[40], fhiline[80], floline[80]; static FILE *fhi, *flo; static int breakpoint_list[MAX_NUM_BRKPTS], number_breakpoints = 0; static instruction_format opcodes[] = { "1100111000011011", 0, Abs, NULL, "ABS", "0000xxxxxxxxxxxx", 1, Add, NULL, "ADD", "01000011xxxxxxxx", 1, Addc, NULL, "ADDC", "01001000xxxxxxxx", 1, Addh, NULL, "ADDH", "11001100xxxxxxxx", 0, Addk, NULL, "ADDK", "01001001xxxxxxxx", 1, Adds, NULL, "ADDS", "01001010xxxxxxxx", 1, Addt, NULL, "ADDT", "1101xxxx00000010", 2, Adlk, NULL, "ADLK", "01111110xxxxxxxx", 0, Adrk, NULL, "ADRK", "01001110xxxxxxxx", 0, And, NULL, "AND", "1101xxxx00000100", 2, Andk, NULL, "ANDK", "1100111000010101", 0, Apac, NULL, "APAC", "111111111xxxxxxx", 3, B, NULL, "B", "1100111000100101", 4, Bacc, NULL, "BACC", "111110111xxxxxxx", 3, Banz, NULL, "BANZ", "111110011xxxxxxx", 3, Bbnz, NULL, "BBNZ", "111110001xxxxxxx", 3, Bbz, NULL, "BBZ", "010111101xxxxxxx", 3, Bc, NULL, "BC", "111101001xxxxxxx", 3, Bgez, NULL, "BGEZ", "111100011xxxxxxx", 3, Bgz, NULL, "BGZ", "111110101xxxxxxx", 3, Bioz, NULL, "BIOZ", "1001xxxxxxxxxxxx", 1, Bit, NULL, "BIT", "01010111xxxxxxxx", 1, Bitt, NULL, "BITT", "111100101xxxxxxx", 3, Blez, NULL, "BLEZ", "11111101xxxxxxxx", 4, Blkd, Blkd_rpt_prep, "BLKD", "11111100xxxxxxxx", 4, Blkp, Blkd_rpt_prep, "BLKP", "111100111xxxxxxx", 3, Blz, NULL, "BLZ", "010111111xxxxxxx", 3, Bnc, NULL, "BNC", "111101111xxxxxxx", 3, Bnv, NULL, "BNV", "111101011xxxxxxx", 3, Bnz, NULL, "BNZ", "111100001xxxxxxx", 3, Bv, NULL, "BV", "111101101xxxxxxx", 3, Bz, NULL, "BZ", "1100111000100100", 4, Cala, NULL, "CALA", "111111101xxxxxxx", 3, Call, NULL, "CALL", "1100111000100111", 0, Cmpl, NULL, "CMPL", "11001110010100xx", 0, Cmpr, NULL, "CMPR", "1100111000000100", 0, Cnfd, NULL, "CNFD", "1100111000000101", 0, Cnfp, NULL, "CNFP", "1100111000000001", 0, Dint, NULL, "DINT", "01010110xxxxxxxx", 1, Dmov, NULL, "DMOV", "1100111000000000", 0, Eint, NULL, "EINT", "110011100000111x", 0, Fort, NULL, "FORT", "1100111000011111", 6, Idle, NULL, "IDLE", "1110xxxxxxxxxxxx", 7, In, NULL, "IN", "0010xxxxxxxxxxxx", 1, Lac, NULL, "LAC", "11001010xxxxxxxx", 0, Lack, NULL, "LACK", "01000010xxxxxxxx", 1, Lact, NULL, "LACT", "1101xxxx00000001", 2, Lalk, NULL, "LALK", "00110xxxxxxxxxxx", 1, Lar, NULL, "LAR", "11000xxxxxxxxxxx", 0, Lark, NULL, "LARK", "0101010110001xxx", 0, Larp, NULL, "LARP", "01010010xxxxxxxx", 1, Ldp, NULL, "LDP", "1100100xxxxxxxxx", 0, Ldpk, NULL, "LDPK", "01010011xxxxxxxx", 1, Lph, NULL, "LPH", "11010xxx00000000", 2, Lrlk, NULL, "LRLK", "01010000xxxxxxxx", 1, Lst, NULL, "LST", "01010001xxxxxxxx", 1, Lst1, NULL, "LST1", "00111100xxxxxxxx", 1, Lt, NULL, "LT", "00111101xxxxxxxx", 1, Lta, NULL, "LTA", "00111111xxxxxxxx", 1, Ltd, NULL, "LTD", "00111110xxxxxxxx", 1, Ltp, NULL, "LTP", "01011011xxxxxxxx", 1, Lts, NULL, "LTS", "01011101xxxxxxxx", 8, Mac, Blkd_rpt_prep, "MAC", "01011100xxxxxxxx", 8, Macd, Blkd_rpt_prep, "MACD", "0101010100000000", 0, Nop, NULL, "NOP", /* special case of MAR */ "01010101xxxxxxxx", 0, Mar, NULL, "MAR", "00111000xxxxxxxx", 1, Mpy, NULL, "MPY", "00111010xxxxxxxx", 1, Mpya, NULL, "MPYA", "101xxxxxxxxxxxxx", 0, Mpyk, NULL, "MPYK", "00111011xxxxxxxx", 1, Mpys, NULL, "MPYS", "11001111xxxxxxxx", 1, Mpyu, NULL, "MPYU", "1100111000100011", 0, Neg, NULL, "NEG", "1100111010100010", 0, Norm, NULL, "NORM", "01001101xxxxxxxx", 1, Or, NULL, "OR", "1101xxxx00000101", 2, Ork, NULL, "ORK", "1110xxxxxxxxxxxx", 7, Out, NULL, "OUT", "1100111000010100", 0, Pac, NULL, "PAC", "1100111000011101", 0, Pop, NULL, "POP", "01111010xxxxxxxx", 10, Popd, NULL, "POPD", "01010100xxxxxxxx", 1, Pshd, NULL, "PSHD", "1100111000011100", 0, Push, NULL, "PUSH", "1100111000110000", 0, Rc, NULL, "RC", "1100111000100110", 4, Ret, NULL, "RET", "1100111000110110", 0, Rfsm, NULL, "RFSM", "1100111000101000", 0, Rhm, NULL, "RHM", "1100111000110100", 0, Rol, NULL, "ROL", "1100111000110101", 0, Ror, NULL, "ROR", "1100111000000010", 0, Rovm, NULL, "ROVM", "01001011xxxxxxxx", 1, Rpt, NULL, "RPT", "11001011xxxxxxxx", 0, Rptk, NULL, "RPTK", "1100111000000110", 0, Rsxm, NULL, "RSXM", "1100111000110010", 0, Rtc, NULL, "RTC", "1100111000100000", 0, Rtxm, NULL, "RTXM", "1100111000001100", 0, Rxf, NULL, "RXF", "01101xxxxxxxxxxx", 10, Sach, NULL, "SACH", "01100xxxxxxxxxxx", 10, Sacl, NULL, "SACL", "01110xxxxxxxxxxx", 10, Sar, NULL, "SAR", "1101xxxx00000011", 2, Sblk, NULL, "SBLK", "01111111xxxxxxxx", 0, Sbrk, NULL, "SBRK", "1100111000110001", 0, Sc, NULL, "SC", "1100111000011000", 0, Sfl, NULL, "SFL", "1100111000011001", 0, Sfr, NULL, "SFR", "1100111000110111", 0, Sfsm, NULL, "SFSM", "1100111000111001", 0, Shm, NULL, "SHM", "1100111000000011", 0, Sovm, NULL, "SOVM", "1100111000010110", 0, Spac, NULL, "SPAC", "01111101xxxxxxxx", 10, Sph, NULL, "SPH", "01111100xxxxxxxx", 10, Spl, NULL, "SPL", "11001110000010xx", 0, Spm, NULL, "SPM", "00111001xxxxxxxx", 1, Sqra, NULL, "SQRA", "01011010xxxxxxxx", 1, Sqrs, NULL, "SQRS", "01111000xxxxxxxx", 10, Sst, NULL, "SST", "01111001xxxxxxxx", 10, Sst1, NULL, "SST1", "1100111000000111", 0, Ssxm, NULL, "SSXM", "1100111000110011", 0, Stc, NULL, "STC", "1100111000100001", 0, Stxm, NULL, "STXM", "0001xxxxxxxxxxxx", 1, Sub, NULL, "SUB", "01001111xxxxxxxx", 1, Subb, NULL, "SUBB", "01000111xxxxxxxx", 1, Subc, NULL, "SUBC", "01000100xxxxxxxx", 1, Subh, NULL, "SUBH", "11001101xxxxxxxx", 0, Subk, NULL, "SUBK", "01000101xxxxxxxx", 1, Subs, NULL, "SUBS", "01000110xxxxxxxx", 1, Subt, NULL, "SUBT", "1100111000001101", 0, Sxf, NULL, "SXF", "01011000xxxxxxxx", 9, Tblr, Tblr_rpt_prep, "TBLR", "01011001xxxxxxxx", 5, Tblw, Tblr_rpt_prep, "TBLW", "1100111000011110", 4, Trap, NULL, "TRAP", "01001100xxxxxxxx", 1, Xor, NULL, "XOR", "1101xxxx00000110", 2, Xork, NULL, "XORK", "1100101000000000", 0, Zac, NULL, "ZAC", "01000000xxxxxxxx", 1, Zalh, NULL, "ZALH", "01111011xxxxxxxx", 1, Zalr, NULL, "ZALR", "01000001xxxxxxxx", 1, Zals, NULL, "ZALS", }; /* ======================================================================= */ /* Alternative Scheme for implementing Status Registers */ /* ======================================================================= */ #if 0 int st0, st1; #define read_bits(x,m,n) ((x >> m) & n) #define set_bits(x,amask,y,n) \ x = (x & ~amask) | ((y << n) & amask) #define arp read_bits(st0,13,7) #define ov read_bits(st0,12,1) #define ovm read_bits(st0,11,1) #define intm read_bits(st0,9,1) #define dp read_bits(st0,0,0x1FF) #define set_arp(x) set_bits(st0,0xE000,x,13) #define set_ov(x) set_bits(st0,0x1000,x,12) #define set_ovm(x) set_bits(st0,0x0800,x,11) #define set_intm(x) set_bits(st0,0x0200,x,9) #define set_dp(x) set_bits(st0,0x01FF,x,0) #define arb read_bits(st1,13,7) #define cnf read_bits(st1,12,1) #define tc read_bits(st1,11,1) #define sxm read_bits(st1,10,1) #define c read_bits(st1,9,1) #define hm read_bits(st1,6,1) #define fsm read_bits(st1,5,1) #define xf read_bits(st1,4,1) #define fo read_bits(st1,3,1) #define rxm read_bits(st1,2,1) #define pm read_bits(st1,0,3) #define set_arb(x) set_bits(st1,0xE000,x,13) #define set_cnf(x) set_bits(st1,0x1000,x,12) #define set_tc(x) set_bits(st1,0x0800,x,11) #define set_sxm(x) set_bits(st1,0x0400,x,10) #define set_c(x) set_bits(st1,0x0200,x,9) #define set_hm(x) set_bits(st1,0x0040,x,6) #define set_fsm(x) set_bits(st1,0x0020,x,5) #define set_xf(x) set_bits(st1,0x0010,x,4) #define set_fo(x) set_bits(st1,0x0008,x,3) #define set_rxm(x) set_bits(st1,0x0004,x,2) #define set_pm(x) set_bits(st1,0x0003,x,0) #endif /* ======================================================================= */ /* Memory System */ /* ======================================================================= */ static memblk *allot_block(char p_d, char high_addr) { memblk *p, *q; q = malloc(sizeof(memblk)); if (q == NULL) { sprintf(toprint, "Out of program/data memory!!\n"); __write(toprint); exit(1); } if (first_memblk == NULL) { first_memblk = q; goto FillErUp; } for (p = first_memblk; p->next != NULL; p = p->next); p->next = q; FillErUp: q->prog_data = p_d; q->high_addr = high_addr; q->next = NULL; new_allotment = 1; return q; } static memblk *search_for_block(char p_d, char hi_addr) { memblk *p = NULL; for (p = first_memblk; p != NULL; p = p->next) if (p->prog_data == p_d && p->high_addr == hi_addr) return p; return NULL; } static memblk *find_prog_block(char hi_addr) { memblk *p; new_allotment = 0; if ((p = search_for_block(1, hi_addr)) != NULL) return p; return allot_block(1, hi_addr); } int *program_memory_address(int a) { memblk *x; x = find_prog_block((char) (a >> 8)); return &(x->contents[a & 0xFF]); } void write_program_memory(int a, int d) { if (warn_progmem_writes) { sprintf(toprint, "WARNING: Writing program memory, address %04X data %04X\n", a, d); __write(toprint); } *program_memory_address(a) = d; } int read_program_memory(int a) { int d; d = *program_memory_address(a); if (new_allotment) { sprintf(toprint, "WARNING: Reading uninitialized program memory!\n"); __write(toprint); } return d; } static memblk *find_data_block(char hi_addr) { memblk *p; new_allotment = 0; if ((p = search_for_block(0, hi_addr)) != NULL) return p; return allot_block(0, hi_addr); } int *data_memory_address(int a) { memblk *x; switch (a) { case 0: return &drr; case 1: return &dxr; case 2: return &tim; case 3: return &prd; case 4: return &imr; case 5: return &greg; } x = find_data_block((char) (a >> 8)); return &(x->contents[a & 0xFF]); } void write_data_memory(int a, int d) { *data_memory_address(a) = d; } int read_data_memory(int a) { int d; d = *data_memory_address(a); if (new_allotment) { sprintf(toprint, "WARNING: Reading uninitialized data memory!\n"); __write(toprint); } return d; } /* ======================================================================= */ /* Instruction helpers */ /* ======================================================================= */ static int in_block_b0(int a) { if (cnf) return (a & 0xFF00) == 0xFF00; return (a & 0xFF00) == 0x200; } static int on_chip_rom(int a) { if (mp_mc_mode) return 0; return ((a >= 0x20 && a < 0xFAF) || (cnf && in_block_b0(a))); } static int on_chip_ram(int a) { return ((a >= 0x60 && a < 0x80) /* block B2 */ || (a & 0xFF00) == 0x300 /* block B1 */ || (!cnf && in_block_b0(a))); } static int get_address(void) { int i, mask, r, s, carry; if ((instruction & 0x80) == 0) r = ((dp << 7) & 0xFF80) | (instruction & 0x7F); else { /* handle updates to AR(ARP) and ARP */ r = ar[arp]; s = ar[0]; switch ((instruction >> 4) & 7) { case 0: break; case 1: ar[arp]--; break; case 2: ar[arp]++; break; case 3: sprintf(toprint, "Bad addressing mode in instruction at %04X\n", pc); __write(toprint); break; case 4: carry = 0; for (i = 0; i < 16; i++) { mask = 1 << (15 - i); carry = ((ar[arp] & mask) ? 1 : 0) - ((s & mask) ? 1 : 0) - carry; ar[arp] = (ar[arp] & ~mask) + ((carry & 1) ? mask : 0); carry = (carry >> 1) & 1; } break; case 5: ar[arp] -= ar[0]; break; case 6: ar[arp] += ar[0]; break; case 7: carry = 0; for (i = 0; i < 16; i++) { mask = 1 << (15 - i); carry += ((ar[arp] & mask) ? 1 : 0) + ((s & mask) ? 1 : 0); ar[arp] = (ar[arp] & ~mask) + ((carry & 1) ? mask : 0); carry = (carry >> 1) & 1; } break; } if (instruction & 8) { arb = arp; arp = (instruction & 7); } } operand_address = r; return r; } static void sign_extend(long int *x) { if (sxm && (*x & 0x8000)) *x |= 0xFFFF0000L; else *x &= 0x0000FFFFL; } static void fetch_operand(void) { int a; old_accum = accumulator; a = get_address(); operand = read_data_memory(a); } static void store_result(int x) { write_data_memory(get_address(), x); } static int detect_overflow(long number_added) { if (!sign32(number_added)) if (!sign32(old_accum) && sign32(accumulator)) return 1; if (sign32(number_added)) if (sign32(old_accum) && !sign32(accumulator)) return 1; return 0; } static void saturate_overflow(long number_added) { if (!sign32(number_added)) accumulator = ~SIGN_BIT; else accumulator = SIGN_BIT; } static void add_operand(int c_in) { int i; long mask; old_accum = accumulator; for (i = 0, mask = SIGN_BIT; i < 32; i++, mask >>= 1) { if ((accumulator & operand) & mask) { c = 1; goto c_done; } if ((~accumulator & ~operand) & mask) { c = 0; goto c_done; } } c = c_in; c_done: if (c_in) operand++; accumulator += operand; if (detect_overflow(operand)) { ov = 1; if (ovm) saturate_overflow(operand); } } static void sub_operand(int c_in) /* I think this is right */ { operand = -operand; add_operand(c_in); } static void cb(int flag) /* conditional branch */ { branch_condition = flag; if (flag) branch_destination = read_program_memory(pc); else branch_destination = pc + 1; pc = branch_destination; get_address(); } static void cbs(int flag, int dest) /* conditional branch, special destination */ { if (flag) pc = dest; get_address(); } static void shift_operand(void) { operand <<= (instruction >> 8) & 15; } static void long_immediate_with_shift(void) { operand = (long) read_program_memory(pc++); shift_operand(); } static long int shifted_p(void) { long int shp; switch (pm) { case 0: return p_register; case 1: return p_register << 1; case 2: return p_register << 4; case 3: shp = p_register >> 6; if (p_register & SIGN_BIT) shp |= 0xFC000000L; return shp; } } static void repeat_instruction(void) { voidfunc g; int i, init_rptc; instruction = read_program_memory(pc++); i = lookup(instruction); if (i == -1) { sprintf(toprint, "Trying to repeat uknown opcode at address %04X\n", pc-1); __write(toprint); return; } repeating = 1; g = opcodes[i].rpt_prep; if (g != NULL) (*g) (); g = opcodes[i].f; init_rptc = rptc; while (rptc >= 0) { (*g) (); rptc--; } burn_cycles(opcodes[i].cycle_type, init_rptc + 1); repeating = 0; rptc = 0; } static int c25_hardware_pop(void) { _sp = (_sp - 1) & 7; return _stack[_sp]; } static void c25_hardware_push(int d) { _stack[_sp] = d; _sp = (_sp + 1) & 7; } static void check_dmov_okay(int addr, char *instruc_name) { /* For the instructions DMOV, LTD, and MACD, both addr and addr+1 must be in on-chip ram for the data move to work. */ if (on_chip_ram(addr) && on_chip_ram(addr + 1)) return; sprintf(toprint, "Instruction %s at %04X using non-internal " "data memory at address %04X\n", instruc_name, pc, addr); __write(toprint); } /* ======================================================================= */ /* Instruction Cycle Times */ /* ======================================================================= */ static void handle_non_branch(int a, int pi_di, int pi_de, int pe_di, int pe_de, int pr_di, int pr_de) { int n; if (on_chip_ram(a) && on_chip_ram(operand_address)) n = pi_di; else if (on_chip_ram(a)) n = pi_de; else if (on_chip_rom(a) && on_chip_ram(operand_address)) n = pr_di; else if (on_chip_rom(a)) n = pr_de; else if (on_chip_ram(operand_address)) n = pe_di; else n = pe_de; cycles += n; tim -= n; if ((tim + n) > 0 && tim <= 0) c25_interrupt(TINT); } static void handle_branch(int a, int pi_di_i, int pi_de_i, int pe_di_i, int pe_de_i, int pr_di_i, int pr_de_i, int pi_di_r, int pi_de_r, int pe_di_r, int pe_de_r, int pr_di_r, int pr_de_r, int pi_di_e, int pi_de_e, int pe_di_e, int pe_de_e, int pr_di_e, int pr_de_e) { if (on_chip_ram(branch_destination)) { handle_non_branch(a, pi_di_i, pi_de_i, pe_di_i, pe_de_i, pr_di_i, pr_de_i); return; } if (on_chip_rom(branch_destination)) { handle_non_branch(a, pi_di_r, pi_de_r, pe_di_r, pe_de_r, pr_di_r, pr_de_r); return; } handle_non_branch(a, pi_di_e, pi_de_e, pe_di_e, pe_de_e, pr_di_e, pr_de_e); } static int get_pmem_wait_states(int addr) { if (on_chip_rom(addr)) return 0; if (pwaitf == NULL) return 0; return (*pwaitf) (addr); } static int get_dmem_wait_states(int addr) { if (on_chip_ram(addr)) return 0; if (dwaitf == NULL) return 0; return (*dwaitf) (addr); } static void burn_cycles(int cycle_type, int n) { int a, p, d, i; a = pc - 1; /* n is the RPTC+1, or zero if not repeating */ p = get_pmem_wait_states(a); d = get_dmem_wait_states(operand_address); if (n == 0) switch (cycle_type) { case 0: /* ABS, ... */ handle_non_branch(a, 1, 1, 1+p, 1+p, 1, 1); return; case 1: /* ADD, ADC ... */ handle_non_branch(a, 1, 2+d, 1+p, 2+d+p, 1, 2+d); return; case 2: /* ADLK */ handle_non_branch(a, 2, 2, 2+2*p, 2+2*p, 2, 2); return; case 3: /* B */ if (!branch_condition) { handle_non_branch(a, 2, 2, 2+2*p, 2+2*p, 2, 2); return; } handle_branch(a, 2, 2, 2+2*p, 2+2*p, 2, 2, 3, 3, 3+2*p, 3+2*p, 3, 3, 3+p, 3+p, 3+3*p, 3+3*p, 3+p, 3+p); return; case 4: /* Bacc */ handle_branch(a, 2, 2, 2+2*p, 2+2*p, 2, 2, 3, 3, 3+2*p, 3+2*p, 3, 3, 3+p, 3+p, 3+2*p, 3+2*p, 3+p, 3+p); return; case 6: /* Idle */ handle_non_branch(a, 3, 3+2*p, 3, 3+2*p, 3, 3+2*p); return; case 7: /* In */ if (iwaitf == NULL) i = 0; else i = (*iwaitf) (port_addr); handle_non_branch(a, 2+i, 2+d+i, 2+p+i, 3+d+p+i, 2+i, 2+d+i); return; case 10: /* Popd */ handle_non_branch(a, 1, 1+d, 1+p, 2+d+p, 1, 1+d); return; case 9: /* Tblr */ branch_destination = pfc; handle_branch(a, 2, 2+d, 3+p, 3+d+p, 3, 3+d, 3, 3+d, 4+p, 4+d+p, 4, 4+d, 3+p, 3+d+p, 4+2*p, 4+d+2*p, 4+p, 4+d+p); return; case 5: /* Tblw */ branch_destination = pfc; handle_branch(a, 2, 3+d, 3+p, 4+d+p, 3, 4+d, 0, 0, 0, 0, 0, 0, 2+p, 3+d+p, 3+2*p, 4+d+2*p, 3+p, 4+d+p); return; case 8: /* Mac */ branch_destination = pfc; handle_branch(a, 3, 4+d, 4+2*p, 5+d+2*p, 4, 5+d, 4, 5+d, 4+2*p, 5+d+2*p, 4, 5+d, 4+p, 5+d+p, 4+3*p, 5+d+3*p, 4+p, 5+d+p); return; default: sprintf(toprint, "Not yet handling burn_cycles(%d, %d)\n", cycle_type, repeating); __write(toprint); } else switch (cycle_type) { case 0: /* ABS, ... */ handle_non_branch(a, n, n, n+p, n+p, n, n); return; case 1: /* ADD, ADC ... */ handle_non_branch(a, 1+n, 1+n+n*d, n+p, 1+n+n*d+p, n, 1+n+n*d); return; case 2: /* ADLK */ case 3: /* B */ case 4: /* Bacc */ case 6: /* Idle */ sprintf(toprint, "Can't repeat instruction at address %04X\n", a); __write(toprint); return; case 7: /* In */ if (iwaitf == NULL) i = 0; else i = (*iwaitf) (port_addr); handle_non_branch(a, 1+n+n*i, n*(2+d+i), 1+n+p+n*i, 1+p+n*(2+d+i), 1+n+n*i, n*(2+d+i)); return; case 10: /* Popd */ handle_non_branch(a, n, n+n*d, n+p, 1+n+n*d+p, n, n+n*d); return; case 9: /* Tblr */ branch_destination = pfc; handle_branch(a, 1+n, 1+n+n*d, 2+n+p, 2+n+n*d+p, 2+n, 2+n+n*d, 2+n, 2+n+n*d, 3+n+p, 3+n+n*d+p, 3+n, 3+n+n*d, 2+n+n*p, 1+n*(2+d+p), 3+n+p+n*p, 2+p+n*(2+d+p), 3+n+n*p, 2+n*(2+d+p)); return; case 5: /* Tblw */ branch_destination = pfc; handle_branch(a, 1+n, 2+n+n*d, 2+n+p, 3+n+n*d+p, 2+n, 3+n+n*d, 0, 0, 0, 0, 0, 0, 1+n+n*p, 1+n*(2+d+p), 2+n+p+n*p, 2+p+n*(2+d+p), 2+n+n*p, 2+n*(2+d+p)); return; case 8: /* Mac */ branch_destination = pfc; handle_branch(a, 2+n, 2+2*n+n*d, 3+n+2*p, 3+2*n+n*d+2*p, 3+n, 3+2*n+n*d, 3+n, 3+2*n+n*d, 3+n+2*p, 3+2*n+n*d+2*p, 3+n, 3+2*n+n*d, 3+n+n*p, 3+n*(2+d+p), 3+n+2*p+n*p, 3+2*p+n*(2+d+p), 3+n+n*p, 3+n*(2+d+p)); return; default: printf(toprint, "Not yet handling burn_cycles(%d, %d)\n", cycle_type, repeating); __write(toprint); } } /* ======================================================================= */ /* Lookup table, advance */ /* ======================================================================= */ static int lookup(int instruc) { int i; for (i = 0; i < NUM_OPCODES; i++) if ((instruc & opcode_masks[i].andmask) == opcode_masks[i].pattern) return i; return -1; } char * disassemble(int instruc) { int i; if ((i = lookup(instruc)) != -1) return opcodes[i].opname; return "ILLEGAL"; } void advance(void) { int i; service_pending_interrupts(); if (idle_mode) { cycles++; tim--; if (tim == 0) c25_interrupt(TINT); return; } instruction = read_program_memory(pc++); i = lookup(instruction); if (i != -1) { (*opcodes[i].f) (); burn_cycles(opcodes[i].cycle_type, 0); } else __write("ILLEGAL OPCODE\n"); steps_taken++; } void c25_reset(void) { int i; pc = 0; _sp = 0; accumulator = 0; t_register = 0; p_register = 0; rptc = 0; for (i = 0; i < 8; i++) { _stack[i] = 0; ar[i] = 0; } arp = 0; ov = 0; ovm = 0; intm = 1; dp = 0; arb = 0; cnf = 0; tc = 0; sxm = 0; c = 0; hm = 0; fsm = 0; xf = 0; fo = 0; txm = 0; pm = 0; drr = 0; dxr = 0; tim = 0xFFFF; prd = 0xFFFF; imr = 0; greg = 0; mp_mc_mode = 1; repeating = 0; idle_mode = 0; steps_taken = 0; cycles = 0; } void initialize_simulator(void) { int i, j; c25_reset(); warn_progmem_writes = 1; for (i = 0; i < NUM_OPCODES; i++) { opcode_masks[i].andmask = 0; opcode_masks[i].pattern = 0; for (j = 0; j < 16; j++) switch (opcodes[i].pattern[15 - j]) { case '0': opcode_masks[i].andmask |= (1 << j); break; case '1': opcode_masks[i].andmask |= (1 << j); opcode_masks[i].pattern |= (1 << j); break; default: break; } } } /* ======================================================================= */ /* Interrupts */ /* ======================================================================= */ void c25_interrupt(enum int_type n) { switch (n) { case RS: c25_reset(); return; case INT0: pending_interrupts |= 1; return; case INT1: pending_interrupts |= 2; return; case INT2: pending_interrupts |= 4; return; case TINT: tim += prd; pending_interrupts |= 8; return; case RINT: pending_interrupts |= 0x10; return; case XINT: pending_interrupts |= 0x20; return; case TRAP: c25_hardware_push(pc); pc = 0x001E; intm = 1; idle_mode = 0; return; default: sprintf(toprint, "Illegal interrupt\n"); __write(toprint); break; } } static int try_interrupt_bit(int n, int addr) { if (read_bit(imr & pending_interrupts, n)) { pending_interrupts &= ~(1 << n); c25_hardware_push(pc); pc = addr; intm = 1; idle_mode = 0; return 1; } return 0; } static void service_pending_interrupts(void) { if (intm) return; if (try_interrupt_bit(0, 0x0002)) return; if (try_interrupt_bit(1, 0x0004)) return; if (try_interrupt_bit(2, 0x0006)) return; if (try_interrupt_bit(3, 0x0018)) return; if (try_interrupt_bit(4, 0x001A)) return; if (try_interrupt_bit(5, 0x001C)) return; } /* ======================================================================= */ /* C25 instructions */ /* ======================================================================= */ /* Ancillary Functions */ static void Blkd_rpt_prep(void) { pfc = read_program_memory(pc++); } static void Tblr_rpt_prep(void) { pfc = (int) accumulator; } /* Real C25 Instructions */ static void Abs(void) { /* exceptional case for 0x80000000, depending on OVF flag */ if (accumulator == 0x80000000L) { if (ovm) accumulator = ~SIGN_BIT; ov = 1; } else if (accumulator & SIGN_BIT) accumulator = -accumulator; } static void Add(void) { fetch_operand(); sign_extend(&operand); shift_operand(); add_operand(0); } static void Addc(void) { fetch_operand(); add_operand(c); } static void Addh(void) { int old_c; c = old_c; fetch_operand(); operand = (operand << 16) & 0xFFFF0000L; add_operand(0); c |= old_c; } static void Addk(void) { operand = instruction & 0xFF; add_operand(0); } static void Adds(void) { fetch_operand(); add_operand(0); } static void Addt(void) { int shift; shift = t_register & 15; fetch_operand(); operand <<= shift; add_operand(0); } static void Adlk(void) { long_immediate_with_shift(); add_operand(0); } static void Adrk(void) { ar[arp] += instruction & 0xFF; } static void And(void) { fetch_operand(); accumulator += operand; } static void Andk(void) { long_immediate_with_shift(); accumulator &= operand; } static void Apac(void) { operand = shifted_p(); add_operand(0); } static void B(void) { cb(1); } static void Bacc(void) { cbs(1, (int) accumulator); } static void Banz(void) { cb(ar[arp]); } static void Bbnz(void) { cb(tc); } static void Bbz(void) { cb(!tc); } static void Bc(void) { cb(c); } static void Bgez(void) { cb(accumulator >= 0); } static void Bgz(void) { cb(accumulator > 0); } static void Bioz(void) { cb(bio); } static void Bit(void) { int shift; shift = 15 - ((instruction >> 8) & 15); fetch_operand(); tc = (int) ((operand >> shift) & 1); } static void Bitt(void) { int shift; shift = 15 - (t_register & 15); fetch_operand(); tc = (int) ((operand >> shift) & 1); } static void Blez(void) { cb(accumulator <= 0); } static void Blkd(void) { if (!repeating) pfc = read_program_memory(pc++); store_result(read_data_memory(pfc++)); } static void Blkp(void) { if (!repeating) pfc = read_program_memory(pc++); store_result(read_program_memory(pfc++)); } static void Blz(void) { cb(accumulator < 0); } static void Bnc(void) { cb(!c); } static void Bnv(void) { cb(!ov); ov = 0; } static void Bnz(void) { cb(accumulator != 0); } static void Bv(void) { cb(ov); ov = 0; } static void Bz(void) { cb(accumulator == 0); } static void Cala(void) { c25_hardware_push(pc); pc = (int) accumulator; branch_destination = pc; } static void Call(void) { c25_hardware_push(pc + 1); pc = read_program_memory(pc); branch_destination = pc; Mar(); } static void Cmpl(void) { accumulator = ~accumulator; } static void Cmpr(void) { unsigned u, v; u = ar[arp]; v = ar[0]; switch (instruction & 3) { case 0: tc = (u == v); break; case 1: tc = (u < v); break; case 2: tc = (u > v); break; case 3: tc = (u != v); break; } } static void Cnfd(void) { memblk *p; cnf = 0; /* if there is a PROG block at 0xFF??, make it DATA at 0x02?? */ if ((p = search_for_block(1, 0xFF)) != NULL) { p->prog_data = 0; p->high_addr = 0x02; } } static void Cnfp(void) { memblk *p; cnf = 1; /* if there is a DATA block at 0x02??, make it PROG at 0xFF?? */ if ((p = search_for_block(0, 0x02)) != NULL) { p->prog_data = 1; p->high_addr = 0xFF; } } static void Dint(void) { intm = 1; } static void Dmov(void) { int a; a = get_address(); check_dmov_okay(a, "DMOV"); write_data_memory(a + 1, read_data_memory(a)); } static void Eint(void) { intm = 0; } static void Fort(void) { fo = instruction & 1; } static void Idle(void) { intm = 0; idle_mode = 1; } static void In(void) { port_addr = (instruction >> 8) & 15; store_result(ports[port_addr]); } static void Lac(void) { fetch_operand(); sign_extend(&operand); shift_operand(); accumulator = operand; } static void Lack(void) { accumulator = instruction & 0xFF; } static void Lact(void) { int shift; shift = t_register & 15; fetch_operand(); sign_extend(&operand); operand <<= shift; accumulator = operand; } static void Lalk(void) { long_immediate_with_shift(); accumulator = operand; sign_extend(&accumulator); } static void Lar(void) { fetch_operand(); ar[(instruction >> 8) & 7] = (int) operand; } static void Lark(void) { ar[(instruction >> 8) & 7] = instruction & 0xFF; } static void Larp(void) { arb = arp; arp = instruction & 7; } static void Ldp(void) { fetch_operand(); dp = (int) (operand & 0x1FF); } static void Ldpk(void) { dp = instruction & 0x1FF; } static void Lph(void) { fetch_operand(); p_register = (p_register & 0xFFFFL) | ((operand << 16) & 0xFFFF0000L); } static void Lrlk(void) { ar[(instruction >> 8) & 7] = read_program_memory(pc++); } static void Lst(void) { fetch_operand(); arp = (int) ((operand >> 13) & 7); ov = read_bit(operand, 12); ovm = read_bit(operand, 11); intm = read_bit(operand, 9); dp = (int) (operand & 0x1FF); } static void Lst1(void) { fetch_operand(); arb = (int) ((operand >> 13) & 7); arp = arb; cnf = read_bit(operand, 12); tc = read_bit(operand, 11); sxm = read_bit(operand, 10); c = read_bit(operand, 9); hm = read_bit(operand, 6); fsm = read_bit(operand, 5); xf = read_bit(operand, 4); fo = read_bit(operand, 3); txm = read_bit(operand, 2); pm = (int) (operand & 3); } static void Lt(void) { fetch_operand(); t_register = (int) operand; } static void Lta(void) { Lt(); Apac(); } static void Ltd(void) { int a; a = get_address(); check_dmov_okay(a, "LTD"); t_register = read_data_memory(a); write_data_memory(a + 1, read_data_memory(a)); Apac(); } static void Ltp(void) { Lt(); Pac(); } static void Lts(void) { Lt(); Spac(); } static void Mac(void) { if (!repeating) pfc = read_program_memory(pc++); Apac(); Lt(); p_register = t_register; p_register *= read_program_memory(pfc++); } static void Macd(void) { int a; if (!repeating) pfc = read_program_memory(pc++); Apac(); a = get_address(); check_dmov_okay(a, "MACD"); t_register = read_data_memory(a); p_register = t_register; p_register *= read_program_memory(pfc++); write_data_memory(a + 1, read_data_memory(a)); return; } static void Mar(void) { get_address(); } static void Mpy(void) { fetch_operand(); p_register = operand * t_register; } static void Mpya(void) { Apac(); Mpy(); } static void Mpyk(void) { operand = instruction & 0x1FFF; if (instruction & 0x1000) operand |= 0xFFFFE000; p_register = operand * t_register; } static void Mpys(void) { Spac(); Mpy(); } static void Mpyu(void) { unsigned long t, d; fetch_operand(); d = operand; t = t_register; p_register = d * t; } static void Neg(void) { c = (accumulator == 0L); if (accumulator == SIGN_BIT) { if (ovm) accumulator = ~SIGN_BIT; ov = 1; } else accumulator = -accumulator; } static void Nop(void) { /* fine just like this */ } static void Norm(void) { if (accumulator == 0) tc = 1; else { if (read_bit(accumulator, 31) == read_bit(accumulator, 30)) { tc = 0; accumulator <<= 1; Mar(); } else tc = 1; } } static void Or(void) { fetch_operand(); accumulator |= operand; } static void Ork(void) { long_immediate_with_shift(); accumulator |= operand; } static void Out(void) { fetch_operand(); port_addr = (instruction >> 8) & 15; ports[port_addr] = (int) operand; } static void Pac(void) { accumulator = shifted_p(); } static void Pop(void) { accumulator = c25_hardware_pop(); } static void Popd(void) { store_result(c25_hardware_pop()); } static void Pshd(void) { fetch_operand(); c25_hardware_push((int) operand); } static void Push(void) { c25_hardware_push((int) accumulator); } static void Rc(void) { c = 0; } static void Ret(void) { pc = c25_hardware_pop(); branch_destination = pc; } static void Rfsm(void) { fsm = 0; } static void Rhm(void) { hm = 0; } static void Rol(void) { if (accumulator & SIGN_BIT) { accumulator = (accumulator << 1) + c; c = 1; } else { accumulator = (accumulator << 1) + c; c = 0; } } static void Ror(void) { if (accumulator & 1) { accumulator = (accumulator >> 1) + (c ? SIGN_BIT : 0); c = 1; } else { accumulator = (accumulator >> 1) + (c ? SIGN_BIT : 0); c = 0; } } static void Rovm(void) { ovm = 0; } static void Rpt(void) { fetch_operand(); rptc = (int) operand; repeat_instruction(); } static void Rptk(void) { rptc = (int) (instruction & 0xFF); repeat_instruction(); } static void Rsxm(void) { sxm = 0; } static void Rtc(void) { tc = 0; } static void Rtxm(void) { txm = 0; } static void Rxf(void) { xf = 0; } static void Sach(void) { operand = accumulator; operand <<= (instruction >> 8) & 7; store_result((int) (operand >> 16)); } static void Sacl(void) { operand = accumulator; operand <<= (instruction >> 8) & 7; store_result((int) operand); } static void Sar(void) { int r; r = ar[(instruction >> 8) & 7]; store_result(r); } static void Sblk(void) { long_immediate_with_shift(); sub_operand(0); } static void Sbrk(void) { ar[arp] -= instruction & 0xFF; } static void Sc(void) { c = 1; } static void Sfl(void) { accumulator <<= 1; } static void Sfr(void) { if (sxm && (accumulator & SIGN_BIT)) accumulator = SIGN_BIT | (accumulator >> 1); else accumulator >>= 1; } static void Sfsm(void) { fsm = 1; } static void Shm(void) { hm = 1; } static void Sovm(void) { ovm = 1; } static void Spac(void) { operand = shifted_p(); sub_operand(0); } static void Sph(void) { operand = shifted_p(); store_result((int) (operand >> 16)); } static void Spl(void) { operand = shifted_p(); store_result((int) operand); } static void Spm(void) { pm = instruction & 3; } static void Sqra(void) { Apac(); Lt(); p_register = t_register; p_register *= p_register; } static void Sqrs(void) { Spac(); Lt(); p_register = t_register; p_register *= p_register; } static void Sst(void) { int st0; st0 = (arp << 13) & 0xE000; set_bit(st0, ov, 12); set_bit(st0, ovm, 11); set_bit(st0, intm, 9); st0 |= dp & 0x1FF; store_result(st0); } static void Sst1(void) { int st1; st1 = (arb << 13) & 0xE000; set_bit(st1, cnf, 12); set_bit(st1, tc, 11); set_bit(st1, sxm, 10); set_bit(st1, c, 9); set_bit(st1, hm, 6); set_bit(st1, fsm, 5); set_bit(st1, xf, 4); set_bit(st1, fo, 3); set_bit(st1, txm, 2); st1 |= pm & 3; store_result(st1); } static void Ssxm(void) { sxm = 1; } static void Stc(void) { tc = 1; } static void Stxm(void) { txm = 1; } static void Sub(void) { fetch_operand(); sign_extend(&operand); shift_operand(); sub_operand(0); } static void Subb(void) { fetch_operand(); sub_operand(c); } static void Subc(void) { long int alu_out; old_accum = accumulator; fetch_operand(); shift_operand(); alu_out = accumulator - operand; if (alu_out >= 0) { c = (alu_out & SIGN_BIT) ? 1 : 0; accumulator = (alu_out << 1) + 1; } else { c = (accumulator & SIGN_BIT) ? 1 : 0; accumulator = accumulator << 1; } if (detect_overflow(operand)) ov = 1; } static void Subh(void) { int old_c; c = old_c; fetch_operand(); operand = ((operand << 16) & 0xFFFF0000L); sub_operand(0); c |= old_c; } static void Subk(void) { operand = instruction & 0xFF; sub_operand(0); } static void Subs(void) { fetch_operand(); sub_operand(0); } static void Subt(void) { int shift; shift = t_register & 15; fetch_operand(); operand <<= shift; sub_operand(0); } static void Sxf(void) { xf = 1; } static void Tblr(void) { if (!repeating) pfc = (int) accumulator; store_result(read_program_memory(pfc++)); } static void Tblw(void) { if (!repeating) pfc = (int) accumulator; fetch_operand(); *program_memory_address(pfc++) = (int) operand; } static void Trap(void) { c25_interrupt(TRAP); } static void Xor(void) { fetch_operand(); accumulator ^= operand; } static void Xork(void) { long_immediate_with_shift(); accumulator ^= operand; } static void Zac(void) { accumulator = 0; } static void Zalh(void) { fetch_operand(); accumulator = operand << 16; } static void Zalr(void) { fetch_operand(); accumulator = (operand << 16) + 0x8000L; } static void Zals(void) { fetch_operand(); accumulator = operand & 0x0000FFFFL; } /* ======================================================================= */ /* Loading Stuff */ /* ======================================================================= */ static int char_to_digit(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'A' && c <= 'F') return c + 10 - 'A'; if (c >= 'a' && c <= 'f') return c + 10 - 'a'; sprintf(toprint, "Wierd character in hex file!\n"); __write(toprint); return 0; } static int extract_byte(char *s, int *p) { int sum; sum = char_to_digit(s[(*p)++]) << 4; sum += char_to_digit(s[(*p)++]); return sum; } static int extract_int(char *s, int *p) { int sum; sum = extract_byte(s, p) << 8; sum += extract_byte(s, p); return sum; } void load_hex_files(char *word) { int a, i, j, bhi, blo, nbytes; char *p; memblk *q, *r; for (i = 0; i < (int) strlen(word); i++) word[i] = toupper(word[i]); sprintf(fname, "%s.HI", word); fhi = fopen(fname, "r"); if (fhi == NULL) { sprintf("Can't read file %s\n", fname); return; } sprintf(fname, "%s.LO", word); flo = fopen(fname, "r"); if (flo == NULL) { sprintf(toprint, "Can't read file %s\n", fname); __write(toprint); return; } if (strstr(word, ".HEX") != NULL) goto SixteenBits; if ((p = strchr(word, '.')) != NULL) *p = '\0'; /* if there is already memory in use, free() that all up */ q = first_memblk; while (q != NULL) { r = q->next; free(q); q = r; } first_memblk = NULL; warn_progmem_writes = 0; while (!feof(fhi)) { fgets(fhiline, 80, fhi); fgets(floline, 80, flo); j = 1; nbytes = extract_byte(fhiline, &j); a = extract_int(fhiline, &j); j += 2; /* filler */ for (i = 0; i < nbytes; i++) { bhi = extract_byte(fhiline, &j); j -= 2; blo = extract_byte(floline, &j); write_program_memory(a++, ((bhi & 0xFF) << 8) | (blo & 0xFF)); } } warn_progmem_writes = 1; c25_reset(); return; SixteenBits: fhi = fopen(word, "r"); if (fhi == NULL) { sprintf(toprint, "Can't read file %s\n", word); __write(toprint); return; } /* if there is already memory in use, free() that all up */ q = first_memblk; while (q != NULL) { r = q->next; free(q); q = r; } first_memblk = NULL; warn_progmem_writes = 0; while (!feof(fhi)) { fgets(fhiline, 80, fhi); j = 1; nbytes = extract_byte(fhiline, &j); a = extract_int(fhiline, &j); extract_byte(fhiline, &j); /* filler */ for (i = 0; i < nbytes / 2; i++) write_program_memory(a++, extract_int(fhiline, &j)); } warn_progmem_writes = 1; c25_reset(); } /* ======================================================================= */ /* Reports */ /* ======================================================================= */ static void print_binary(char *name, int x, int n) { int mask = 1 << (n - 1); __write(name); __write(":"); while (mask) { if (x & mask) __write("1"); else __write("0"); mask >>= 1; } sprintf(toprint, "(%d) ", x); __write(toprint); } static void print_bit(char *name, int x) { __write(name); __write(":"); if (x) __write("1 "); else __write("0 "); } void short_report(void) { int i; __write("PC:"); phex(pc); sprintf(toprint, " Instructions executed: %ld Processor cycles: %ld\n", steps_taken, cycles); __write(toprint); i = read_program_memory(pc); __write("Instruction: "); phex(i); __write(" "); if ((i = lookup(i)) != -1) __write(opcodes[i].opname); else __write("ILLEGAL OPCODE"); if (idle_mode) __write(" (idling)"); __write("\n"); } void long_report(void) { int i; print_matching_symbols(pc); short_report(); __write("ACC:"); plhex(accumulator); print_binary("ARP", arp, 3); __write("\n"); __write("ARs: "); for (i = 0; i < 8; i++) phex(ar[i]); __write("\n"); __write("Hardware stack: "); for (i = _sp - 1; i >= 0; i--) phex(_stack[i]); if (_sp == 0) __write("empty"); __write("\n"); /* ST0 */ print_bit("OV", ov); print_bit("OVM", ovm); print_bit("INTM", intm); print_binary("DP", dp, 9); __write("\n"); /* ST1 */ print_binary("ARB", arb, 3); print_bit("CNF", cnf); print_bit("TC", tc); print_bit("SXM", sxm); print_bit("C", c); print_bit("HM", hm); print_bit("FSM", fsm); print_bit("XF", xf); print_bit("FO", fo); print_bit("TXM", txm); print_binary("PM", pm, 2); __write("\n"); __write("T:"); phex(t_register); __write("P:"); plhex(p_register); __write("\n"); __write("DRR:"); phex(drr); __write("DXR:"); phex(dxr); __write("TIM:"); phex(tim); __write("PRD:"); phex(prd); __write("IMR:"); phex(imr); __write("GREG:"); phex(greg); __write("\n"); } /* ======================================================================= */ /* Breakpoints */ /* ======================================================================= */ static int find_breakpoint(int d) { int i; for (i = 0; i < number_breakpoints; i++) if (breakpoint_list[i] == d) return i; return -1; } void add_breakpoint(int a) { if (find_breakpoint(a) != -1) return; if (number_breakpoints == MAX_NUM_BRKPTS) { __write("No more room for breakpoints!\n"); return; } breakpoint_list[number_breakpoints++] = a; } void delete_breakpoint(int a) { a = find_breakpoint(a); if (a == -1) return; breakpoint_list[a] = breakpoint_list[--number_breakpoints]; } void clear_all_breakpoints(void) { number_breakpoints = 0; } int go_til_breakpoint(long int n) { int p; unsigned long int limit; limit = steps_taken + n; advance(); while ((p = find_breakpoint(pc)) == -1 && !kbhit() && (steps_taken < limit || n == -1)) advance(); if (kbhit()) return getch(); if (p != -1) return -1; return -2; }