diff --git a/Makefile b/Makefile index 2154a21..80809dc 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,17 @@ +CC = clang +CFLAGS = -O3 -flto -Wno-deprecated-declarations + all: shoebill -shoebill: make_gui +shoebill: make_gui debugger make_gui: make_core xcodebuild -project gui/Shoebill.xcodeproj SYMROOT=build +debugger: make_core + $(MAKE) -C debugger + make_core: $(MAKE) -C core -j 4 diff --git a/core/Makefile b/core/Makefile index 45c21d1..c9609d2 100644 --- a/core/Makefile +++ b/core/Makefile @@ -1,13 +1,13 @@ CC = clang -CFLAGS = -O3 -flto -ggdb -Wno-deprecated-declarations +CFLAGS = -O3 -ggdb -flto -Wno-deprecated-declarations # CFLAGS = -O0 -ggdb -Wno-deprecated-declarations DEPS = core_api.h coff.h mc68851.h redblack.h shoebill.h Makefile macro.pl NEED_DECODER = cpu dis NEED_PREPROCESSING = adb fpu mc68851 mem via -NEED_NOTHING = atrap_tab coff exception floppy macii_symbols redblack scsi toby_frame_buffer video core_api filesystem debug_server alloc_pool +NEED_NOTHING = atrap_tab coff exception floppy macii_symbols redblack scsi video core_api filesystem alloc_pool # Object files that can be compiled directly from the source OBJ_NEED_NOTHING = $(patsubst %,$(TEMP)/%.o,$(NEED_NOTHING)) @@ -73,7 +73,7 @@ $(TEMP)/dis_decoder_guts.c: $(TEMP)/decoder_gen $(DEPS) # Compile the decoder generator $(TEMP)/decoder_gen: decoder_gen.c $(DEPS) - $(CC) $(CFLAGS) decoder_gen.c -o $(TEMP)/decoder_gen + $(CC) decoder_gen.c -o $(TEMP)/decoder_gen $(TEMP): diff --git a/core/adb.c b/core/adb.c index deb385a..e725aa5 100644 --- a/core/adb.c +++ b/core/adb.c @@ -81,7 +81,7 @@ void adb_start_service_request() { - printf("adb_start_service_request: pending_requests = 0x%02x\n", shoe.adb.pending_service_requests); + //printf("adb_start_service_request: pending_requests = 0x%02x\n", shoe.adb.pending_service_requests); if (shoe.adb.pending_service_requests) { shoe.adb.service_request = 1; @@ -245,7 +245,7 @@ static void adb_handle_state_zero(uint8_t command_byte, uint8_t is_poll) // "Com shoe.adb.poll = 0; - via->regb |= VIA_REGB_ADB_STATUS; + via->regb_input |= VIA_REGB_ADB_STATUS; via_raise_interrupt(1, IFR_SHIFT_REG); } @@ -269,7 +269,7 @@ static void adb_handle_state_one (void) // "Even" state printf("adb_talk: "); if (shoe.adb.timeout) { shoe.adb.timeout = 0; - via->regb &= ~~VIA_REGB_ADB_STATUS; // adb_status_line cleared == timeout + via->regb_input &= ~~VIA_REGB_ADB_STATUS; // adb_status_line cleared == timeout via_raise_interrupt(1, IFR_SHIFT_REG); printf("timeout\n"); return ; @@ -288,7 +288,7 @@ static void adb_handle_state_one (void) // "Even" state printf("adb_listen: "); if (shoe.adb.timeout) { shoe.adb.timeout = 0; - via->regb &= ~~VIA_REGB_ADB_STATUS; // adb_status_line cleared == timeout + via->regb_input &= ~~VIA_REGB_ADB_STATUS; // adb_status_line cleared == timeout via_raise_interrupt(1, IFR_SHIFT_REG); printf("timeout\n"); return ; @@ -304,7 +304,7 @@ static void adb_handle_state_one (void) // "Even" state break; } - via->regb |= VIA_REGB_ADB_STATUS; // adb_status_line set == didn't-timeout + via->regb_input |= VIA_REGB_ADB_STATUS; // adb_status_line set == didn't-timeout via_raise_interrupt(1, IFR_SHIFT_REG); } @@ -317,11 +317,11 @@ static void adb_handle_state_two (void) // "Odd" state // If this transaction was part of a service request, clear the service_request flag now if (shoe.adb.service_request) { shoe.adb.service_request = 0; - via->regb &= ~~VIA_REGB_ADB_STATUS; // adb_status_line cleared == service request + via->regb_input &= ~~VIA_REGB_ADB_STATUS; // adb_status_line cleared == service request printf("(service request) "); } else - via->regb |= VIA_REGB_ADB_STATUS; // adb_status_line set == no-service request + via->regb_input |= VIA_REGB_ADB_STATUS; // adb_status_line set == no-service request switch (shoe.adb.command_type) { case adb_flush: diff --git a/core/coff.c b/core/coff.c index eb9db2a..5a57a09 100644 --- a/core/coff.c +++ b/core/coff.c @@ -76,7 +76,7 @@ coff_file* coff_parse(uint8_t *buf, uint32_t buflen) } // Allocate a coff_file and copy in the header - cf = (coff_file*)calloc(1, sizeof(coff_file)); + cf = (coff_file*)p_alloc(shoe.pool, sizeof(coff_file)); ptr = rawhead; cf->magic = be2native(&ptr, 2); cf->num_sections = be2native(&ptr, 2); @@ -98,17 +98,17 @@ coff_file* coff_parse(uint8_t *buf, uint32_t buflen) // pull out cf->opt_header bytes (a.out-format header, I guess?) if (cf->opt_header_len > 0) { - uint8_t *opt = malloc(cf->opt_header_len); + uint8_t *opt = p_alloc(shoe.pool, cf->opt_header_len); if (!_coff_buf_read(opt, cf->opt_header_len)) { printf("coff_parse: I ran out of data pulling the optional header (%u bytes)\n", cf->opt_header_len); - free(opt); + p_free(opt); goto fail; } cf->opt_header = opt; } // start pulling out sections - cf->sections = calloc(cf->num_sections, sizeof(coff_section)); + cf->sections = p_alloc(shoe.pool, cf->num_sections * sizeof(coff_section)); for (i=0; inum_sections; i++) { // read the header uint8_t rawsec[40]; @@ -158,10 +158,10 @@ coff_file* coff_parse(uint8_t *buf, uint32_t buflen) } // load the data and attach it to the section struct - data = malloc(cf->sections[i].sz); // FIXME: sz might not be a sane value + data = p_alloc(shoe.pool, cf->sections[i].sz); // FIXME: sz might not be a sane value if (!_coff_buf_read(data, cf->sections[i].sz)) { printf("coff_parse: I couldn't fread section %u (%s)'s data (%u bytes)\n", i+1, cf->sections[i].name, cf->sections[i].sz); - free(data); + p_free(data); goto fail; } cf->sections[i].data = data; @@ -174,7 +174,7 @@ coff_file* coff_parse(uint8_t *buf, uint32_t buflen) cf->func_tree = rb_new(); //printf("func_tree = %llx, *func_tree = %llx\n", cf->func_tree, *cf->func_tree); - cf->symbols = (coff_symbol*)calloc(sizeof(coff_symbol), cf->num_symbols); + cf->symbols = (coff_symbol*)p_alloc(shoe.pool, sizeof(coff_symbol) *cf->num_symbols); // Seek to the symbol table if (!_coff_buf_seek(cf->symtab_offset)) { @@ -208,7 +208,7 @@ coff_file* coff_parse(uint8_t *buf, uint32_t buflen) goto fail; } } - cf->symbols[i].name = malloc(j+1); + cf->symbols[i].name = p_alloc(shoe.pool, j+1); memcpy(cf->symbols[i].name, tmp_name, j); cf->symbols[i].name[j] = 0; _coff_buf_seek(cf->symtab_offset + (i+1)*18); @@ -252,17 +252,17 @@ coff_file* coff_parse(uint8_t *buf, uint32_t buflen) fail: if (cf) { if (cf->opt_header) { - free(cf->opt_header); + p_free(cf->opt_header); } if (cf->sections) { for (i=0; inum_sections; i++) { if (cf->sections[i].data) { - free(cf->sections[i].data); + p_free(cf->sections[i].data); } } - free(cf->sections); + p_free(cf->sections); } - free(cf); + p_free(cf); } return NULL; } @@ -270,12 +270,12 @@ fail: coff_file* coff_parse_from_path(const char *path) { FILE *f = fopen(path, "r"); - uint8_t *buf = malloc(1); + uint8_t *buf = p_alloc(shoe.pool, 1); uint32_t i=0, tmp; coff_file *coff; do { - buf = realloc(buf, i + 128*1024); + buf = p_realloc(buf, i + 128*1024); assert(buf); tmp = fread(buf+i, 1, 128*1024, f); i += tmp; @@ -285,7 +285,7 @@ coff_file* coff_parse_from_path(const char *path) coff = coff_parse(buf, i); - free(buf); + p_free(buf); return coff; } diff --git a/core/core_api.c b/core/core_api.c index 64734af..b36952c 100644 --- a/core/core_api.c +++ b/core/core_api.c @@ -34,136 +34,17 @@ #include "coff.h" #include "core_api.h" -/* -char *ring, *ring_tmp; -const uint32_t ring_len = 64 * 1024 * 1024; -uint32_t ring_i = 0; - -void print_mmu_rp(uint64_t rp) -{ - printf("lu=%u limit=0x%x sg=%u dt=%u addr=0x%08x\n", rp_lu(rp), rp_limit(rp), rp_sg(rp), rp_dt(rp), rp_addr(rp)); -} - -void printregs() -{ - sprintf(ring_tmp+strlen(ring_tmp), "[d0]%08x [d1]%08x [d2]%08x [d3]%08x\n", shoe.d[0], shoe.d[1], shoe.d[2], shoe.d[3]); - sprintf(ring_tmp+strlen(ring_tmp), "[d4]%08x [d5]%08x [d6]%08x [d7]%08x\n", shoe.d[4], shoe.d[5], shoe.d[6], shoe.d[7]); - sprintf(ring_tmp+strlen(ring_tmp), "[a0]%08x [a1]%08x [a2]%08x [a3]%08x\n", shoe.a[0], shoe.a[1], shoe.a[2], shoe.a[3]); - sprintf(ring_tmp+strlen(ring_tmp), "[a4]%08x [a5]%08x [a6]%08x [a7]%08x\n", shoe.a[4], shoe.a[5], shoe.a[6], shoe.a[7]); - sprintf(ring_tmp+strlen(ring_tmp), "[pc]%08x [sr]%c%c%c%c%c%c%c [tc]%08x\n", shoe.pc, - sr_s()?'S':'s', - sr_m()?'M':'m', - sr_x()?'X':'x', - sr_n()?'N':'n', - sr_z()?'Z':'z', - sr_v()?'V':'v', - sr_c()?'C':'c', - shoe.tc - ); - - sprintf(ring_tmp+strlen(ring_tmp), "[vbr]%08x\n", shoe.vbr); - - //printf("srp: "); - //print_mmu_rp(shoe.srp); - - //printf("crp: "); - //print_mmu_rp(shoe.crp); - - sprintf(ring_tmp+strlen(ring_tmp), "tc: e=%u sre=%u fcl=%u ps=%u is=%u (tia=%u tib=%u tic=%u tid=%u)\n\n", - tc_enable(), tc_sre(), tc_fcl(), tc_ps(), tc_is(), tc_tia(), tc_tib(), tc_tic(), tc_tid()); - -} - -void dump_ring() -{ - uint32_t i = ring_i+1; - - while (i != ring_i) { - fwrite(&ring[i], 1, 1, stdout); - i = (i+1) % ring_len; - } -} - -void ring_print(const char *str) -{ - uint32_t i; - for (i=0; str[i]; i++) { - ring[ring_i] = str[i]; - ring_i = (ring_i+1) % ring_len; - } -} - -void print_pc() -{ - char str[1024]; - uint8_t binary[64]; - uint32_t i; - uint32_t len; - const char *name = NULL; - - if ((shoe.pc >= 0x40000000) && (shoe.pc < 0x50000000)) { - uint32_t i, addr = shoe.pc % (shoe.physical_rom_size); - for (i=0; macii_rom_symbols[i].name; i++) { - if (macii_rom_symbols[i].addr > addr) { - break; - } - name = macii_rom_symbols[i].name; - } - } - else if (sr_s()) { // these symbols are only meaningful in supervisor mode - coff_symbol *symb = coff_find_func(shoe.coff, shoe.pc); - if (symb && strlen(symb->name)) - name = symb->name; - } - else - name = ""; - - if ((name == NULL) || (name[0] == 0)) - return; - if (strncmp("scsi", name, 4) != 0) - return ; - - const uint16_t old_abort = shoe.abort; - shoe.suppress_exceptions = 1; - - for (i=0; i<32; i++) { - binary[i] = (uint8_t) lget(shoe.pc+i, 1); - } - - disassemble_inst(binary, shoe.pc, str, &len); - - sprintf(ring_tmp, "*0x%08x %s [ ", shoe.pc, name ? name : ""); - for (i=0; irom_path, "r"); if (f == NULL) { @@ -491,7 +369,7 @@ static uint32_t _load_rom (shoebill_control_t *control, uint8_t **_rom_data, uin } for (rom_size = 0; rom_size < (2*1024*1024); rom_size += (64*1024)) { - rom_data = (uint8_t*)realloc(rom_data, rom_size + (64*1024)); + rom_data = (uint8_t*)p_realloc(rom_data, rom_size + (64*1024)); if (fread(rom_data + rom_size, 64*1024, 1, f) != 1) break; } @@ -514,7 +392,7 @@ static uint32_t _load_rom (shoebill_control_t *control, uint8_t **_rom_data, uin goto fail; } - rom_data = realloc(rom_data, rom_size); + // rom_data = p_realloc(rom_data, rom_size); assert(rom_data); *_rom_size = rom_size; @@ -524,7 +402,7 @@ static uint32_t _load_rom (shoebill_control_t *control, uint8_t **_rom_data, uin return 1; fail: - if (rom_data) free(rom_data); + if (rom_data) p_free(rom_data); if (f) fclose(f); return 0; } @@ -697,7 +575,7 @@ uint32_t shoebill_initialize(shoebill_control_t *control) goto fail; coff = coff_parse(kernel_data, kernel_size); - free(kernel_data); + free(kernel_data); // kernel_data was allocated with malloc() if (coff == NULL) { sprintf(control->error_msg, "Can't open that A/UX kernel [%s]\n", @@ -718,13 +596,13 @@ uint32_t shoebill_initialize(shoebill_control_t *control) } shoe.physical_rom_size = rom_size; - shoe.physical_rom_base = valloc(rom_size+8); // +8 because of physical_get hack + shoe.physical_rom_base = p_alloc(shoe.pool, rom_size+8); // +8 because of physical_get hack memcpy(shoe.physical_rom_base, rom_data, rom_size); - free(rom_data); + p_free(rom_data); rom_data = NULL; shoe.physical_mem_size = control->ram_size; - shoe.physical_mem_base = valloc(control->ram_size+8); // +8 because of physical_get hack + shoe.physical_mem_base = p_alloc(shoe.pool, control->ram_size+8); // +8 because of physical_get hack memset(shoe.physical_mem_base, 0, shoe.physical_mem_size); // Initialize Macintosh lomem variables that A/UX actually cares about @@ -746,40 +624,49 @@ uint32_t shoebill_initialize(shoebill_control_t *control) * (Can't fail after this point) */ - // FIXME: Don't do this! Rewrite the via timers! - gettimeofday(&shoe.start_time, NULL); - shoe.total_ticks = 0; + /* + * FIXME: to implement clean resetting, everything with a global structure needs + * an initialization function. Starting here with via/pram... + */ + init_via_state(); + // Put the adb chip in state 3 (idle) + // FIXME: put this in a "init_adb_state()"-type function shoe.adb.state = 3; pthread_mutex_init(&shoe.adb.lock, NULL); + set_sr(0x2000); shoe.pc = pc; memcpy(shoe.scsi_devices, disks, 8 * sizeof(scsi_device_t)); - pthread_mutex_init(&shoe.cpu_thread_lock, NULL); pthread_mutex_init(&shoe.via_clock_thread_lock, NULL); - - pthread_mutex_lock(&shoe.cpu_thread_lock); pthread_mutex_lock(&shoe.via_clock_thread_lock); - - pthread_create(&control->cpu_thread_pid, NULL, _cpu_thread, NULL); - // pthread_create(&control->cpu_thread_pid, NULL, debug_cpu_thread, NULL); pthread_create(&control->via_thread_pid, NULL, via_clock_thread, NULL); + /* + * control->debug_mode is a hack - the debugger implements its own CPU thread + */ + pthread_mutex_init(&shoe.cpu_thread_lock, NULL); + pthread_mutex_lock(&shoe.cpu_thread_lock); + if (!control->debug_mode) + pthread_create(&control->cpu_thread_pid, NULL, _cpu_thread, NULL); + return 1; fail: - if (rom_data) free(rom_data); + if (rom_data) p_free(rom_data); for (i=0; i<7; i++) if (disks[i].f) fclose(disks[i].f); - if (shoe.physical_rom_base) free(shoe.physical_rom_base); - if (shoe.physical_mem_base) free(shoe.physical_mem_base); + if (shoe.physical_rom_base) p_free(shoe.physical_rom_base); + if (shoe.physical_mem_base) p_free(shoe.physical_mem_base); + + p_free_pool(shoe.pool); + memset(&shoe, 0, sizeof(global_shoebill_context_t)); - // No way to free *coff yet return 0; } diff --git a/core/core_api.h b/core/core_api.h index 5fedc97..70afb74 100644 --- a/core/core_api.h +++ b/core/core_api.h @@ -98,6 +98,8 @@ typedef struct { pthread_t cpu_thread_pid, via_thread_pid; + _Bool debug_mode; + char error_msg[8192]; } shoebill_control_t; diff --git a/core/cpu.c b/core/cpu.c index 24a30be..8e90b6a 100644 --- a/core/cpu.c +++ b/core/cpu.c @@ -59,39 +59,32 @@ static const _cc_func evaluate_cc[16] = { #define nextlong() ({const uint32_t L=lget(shoe.pc,4); if (shoe.abort) {return;}; shoe.pc+=4; L;}) #define verify_supervisor() {if (!sr_s()) {throw_privilege_violation(); return;}} -~newmacro(inst, 2, { - # This macro encapsulates an instruction implementation - my ($name, $code) = @$args; - - my $out = "void inst_$name () {\n" . $code . "}"; - return $out; -}) -~inst(callm, { +static void inst_callm(void) { assert(!"callm: error, not implemented\n"); -}) +} -~inst(chk2_cmp2, { +static void inst_chk2_cmp2 (void) { assert(!"chk2_cmp2: error: not implemented\n"); -}) +} -~inst(illegal, { +static void inst_illegal (void) { assert(!"illegal: error: not implemented\n"); -}) +} -~inst(move16, { +static void inst_move16 (void) { assert(!"move16: SHOULD NOT BE CALLED\n"); // shouldn't be called by 68020 decoder -}) +} -~inst(rtm, { +static void inst_rtm (void) { assert(!"rtm: error: not implemented\n"); -}) +} -~inst(tas, { +static void inst_tas (void) { assert(!"tas: error: not implemented\n"); -}) +} -~inst(trapcc, { +static void inst_trapcc (void) { ~decompose(shoe.op, 0101 cccc 11111 xyz); // (xyz) == (100) -> sz=0 @@ -104,14 +97,14 @@ static const _cc_func evaluate_cc[16] = { throw_frame_two(shoe.sr, next_pc, 7, shoe.orig_pc); else shoe.pc = next_pc; -}) +} -~inst(trapv, { +static void inst_trapv (void) { if (sr_v()) throw_frame_two(shoe.sr, shoe.pc, 7, shoe.orig_pc); -}) +} -~inst(asx_reg, { +static void inst_asx_reg (void) { ~decompose(shoe.op, 1110 ccc d ss i 00 rrr); const uint8_t sz = 1<>15); set_sr_z(R==0); } -}) +} // GCC returns garbage when you shift a value by >= its size: ((uint32_t)123)<<32) == garbage // So we'll use macros for risky shifts -#define shiftl(_v, _b) ({const uint32_t v=(_v), b=(_b); const uint32_t r=(b>=32)?0:(v<=32)?0:(v>>b); r;}) -~inst(lsx_reg, { + +#define shiftl(_v, _b) ((uint32_t) (((uint64_t)(_v)) << (_b))) +#define shiftr(_v, _b) ((uint32_t) (((uint64_t)(_v)) >> (_b))) + +static void inst_lsx_reg (void) { ~decompose(shoe.op, 1110 ccc d ss i 01 rrr); const uint8_t sz = 1<>15); set_sr_z(R==0); } -}) +} // FIXME: rox_reg and roxx_reg can be made O(1) -~inst(roxx_reg, { +static void inst_roxx_reg (void) { ~decompose(shoe.op, 1110 ccc d ss i 10 rrr); const uint8_t sz = 1<>15)&1); set_sr_z((quotient_32 & 0xffff) == 0); set_sr_v(quotient_32 >> 16); -}) +} -~inst(divs, { +static void inst_divs (void) { ~decompose(shoe.op, 1000 rrr 111 MMMMMM); + // uncommitted_ea_read_pc is uninitialized for EA modes that don't change the PC, + // but we might need it if we need to throw a divide-by-zero exception, + // so initialize it here, just in case. + shoe.uncommitted_ea_read_pc = shoe.pc; + call_ea_read(M, 2); const int32_t dividend = (int32_t)shoe.d[r]; @@ -424,22 +427,22 @@ static const _cc_func evaluate_cc[16] = { set_sr_n((u_quotient_32>>15)&1); set_sr_z((u_quotient_32 & 0xffff) == 0); set_sr_v(u_quotient_32 >> 16); -}) +} -~inst(bkpt, { +static void inst_bkpt (void) { assert(!"Hey! inst_bkpt isn't implemented!\n"); -}) +} -~inst(swap, { +static void inst_swap (void) { ~decompose(shoe.op, 0100 1000 0100 0 rrr); shoe.d[r] = (shoe.d[r]>>16) | (shoe.d[r]<<16); set_sr_c(0); set_sr_v(0); set_sr_z(shoe.d[r]==0); set_sr_n(mib(shoe.d[r], 4)); -}) +} -~inst(abcd, { +static void inst_abcd (void) { ~decompose(shoe.op, 1100 xxx 10000 m yyy); uint8_t packed_x, packed_y; const uint8_t extend = sr_x() ? 1 : 0; @@ -489,9 +492,9 @@ static const _cc_func evaluate_cc[16] = { set_d(x, packed_sum, 1); } -}) +} -~inst(muls, { +static void inst_muls (void) { ~decompose(shoe.op, 1100 rrr 011 MMMMMM); call_ea_read(M, 2); @@ -513,10 +516,10 @@ static const _cc_func evaluate_cc[16] = { set_sr_v(0); set_sr_z(result == 0); set_sr_n(mib(result, 4)); -}) +} /* short form unsigned multiply */ -~inst(mulu, { +static void inst_mulu (void) { ~decompose(shoe.op, 1100 rrr 011 MMMMMM); call_ea_read(M, 2); @@ -532,9 +535,9 @@ static const _cc_func evaluate_cc[16] = { set_sr_v(0); set_sr_z(result == 0); set_sr_n(mib(result, 4)); -}) +} -~inst(exg, { +static void inst_exg (void) { ~decompose(shoe.op, 1100 xxx 1 ppppp yyy); if (p == ~b(01000)) { // data reg mode @@ -556,18 +559,18 @@ static const _cc_func evaluate_cc[16] = { // I'm not sure whether decode.c will map opcodes with other modes here assert(!"inst_exg: bad op mode"); } -}) +} -~inst(stop, { +static void inst_stop (void) { verify_supervisor(); const uint16_t ext = nextword(); set_sr(ext); shoe.cpu_thread_notifications |= SHOEBILL_STATE_STOPPED; -}) +} -~inst(rtr, { +static void inst_rtr (void) { const uint16_t ccr = lget(shoe.a[7], 2); if (shoe.abort) return ; @@ -579,9 +582,9 @@ static const _cc_func evaluate_cc[16] = { // We don't need to use sr_set() here because only changing the condition codes shoe.sr = (shoe.sr & 0xff00) | (ccr & 0x00ff); shoe.pc = pc; -}) +} -~inst(rtd, { +static void inst_rtd (void) { const int16_t disp = nextword(); const uint32_t new_pc = lget(shoe.a[7], 4); if (shoe.abort) return ; @@ -589,9 +592,9 @@ static const _cc_func evaluate_cc[16] = { shoe.pc = new_pc; shoe.a[7] += 4; shoe.a[7] += disp; -}) +} -~inst(rte, { +static void inst_rte (void) { verify_supervisor(); const uint16_t sr = lget(shoe.a[7], 2); @@ -633,9 +636,9 @@ static const _cc_func evaluate_cc[16] = { break; } -}) +} -~inst(move_usp, { +static void inst_move_usp (void) { verify_supervisor(); ~decompose(shoe.op, 0100 1110 0110 d rrr); @@ -648,9 +651,9 @@ static const _cc_func evaluate_cc[16] = { shoe.usp = shoe.a[r]; load_stack_pointer(); } -}) +} -~inst(and, { +static void inst_and (void) { ~decompose(shoe.op, 1100 rrr dss MMMMMM); const uint8_t sz = 1<>7); // printf("dat = %x, shoe.d[%u] = %x\n", dat, r, shoe.d[r]); // printf("I'm called, right?\n"); -}) +} -~inst(add, { +static void inst_add (void) { ~decompose(shoe.op, 1101 rrr d ss MMMMMM); const uint8_t sz = 1<, Dn // -> source // Dn -> dest @@ -855,9 +858,9 @@ static const _cc_func evaluate_cc[16] = { set_sr_n(Rm); set_sr_v((!Sm && Dm && !Rm) || (Sm && !Dm && Rm)); set_sr_c((Sm && !Dm) || (Rm && !Dm) || (Sm && Rm)); -}) +} -~inst(cmpi, { +static void inst_cmpi (void) { ~decompose(shoe.op, 0000 1100 ss MMMMMM); const uint8_t sz = 1< cc // Dn, ea ~decompose(shoe.op, 1011 rrr o11 MMMMMM); @@ -905,9 +908,9 @@ static const _cc_func evaluate_cc[16] = { set_sr_n(Rm); set_sr_v((!Sm && Dm && !Rm) || (Sm && !Dm && Rm)); set_sr_c((Sm && !Dm) || (Rm && !Dm) || (Sm && Rm)); -}) +} -~inst(cmpm, { +static void inst_cmpm (void) { ~decompose(shoe.op, 1011 xxx 1 ss 001 yyy); const uint8_t sz = 1 << s; @@ -943,9 +946,9 @@ static const _cc_func evaluate_cc[16] = { set_sr_n(Rm); set_sr_v((!Sm && Dm && !Rm) || (Sm && !Dm && Rm)); set_sr_c((Sm && !Dm) || (Rm && !Dm) || (Sm && Rm)); -}) +} -~inst(eor, { +static void inst_eor (void) { ~decompose(shoe.op, 1011 rrr 1ss MMMMMM); const uint8_t sz = 1<>3) == 1)) { @@ -1088,9 +1097,9 @@ static const _cc_func evaluate_cc[16] = { set_sr_n(Rm); set_sr_z(ea_z(1<> s; call_ea_read(M, sz); call_ea_read_commit(M, sz); - if (b) { // word-size, sign extend shoe.dat + if (s) { // word-size, sign extend shoe.dat const int16_t dat = shoe.dat; shoe.a[r] = (int32_t)dat; } else { shoe.a[r] = shoe.dat; } -}) +} -~inst(move_d_to_d, { +static void inst_move_d_to_d (void) { ~decompose(shoe.op, 00 ab RRR 000 000 rrr); // r=source, R=dest const uint8_t sz = 1<<(a+(!b)); // (1=byte, 3=word, 2=long) @@ -1144,9 +1153,9 @@ static const _cc_func evaluate_cc[16] = { set_sr_c(0); set_sr_n(mib(val, sz)); set_sr_z(val == 0); -}) +} -~inst(move_from_d, { +static void inst_move_from_d (void) { ~decompose(shoe.op, 00 ab RRR MMM 000 rrr); // r=source, MR=dest const uint8_t sz = 1<<(a+(!b)); // (1=byte, 3=word, 2=long) @@ -1159,9 +1168,9 @@ static const _cc_func evaluate_cc[16] = { shoe.dat = val; call_ea_write((M << 3) | R, sz); -}) +} -~inst(move_to_d, { +static void inst_move_to_d (void) { ~decompose(shoe.op, 00 ab rrr 000 mmmmmm); // m=source, r=dest const uint8_t sz = 1<<(a+(!b)); // (1=byte, 3=word, 2=long) @@ -1173,9 +1182,9 @@ static const _cc_func evaluate_cc[16] = { set_sr_n(ea_n(sz)); set_sr_z(ea_z(sz)); set_d(r, shoe.dat, sz); -}) +} -~inst(move, { +static void inst_move (void) { ~decompose(shoe.op, 00 ab RRR MMM mmm rrr); // mr=source, MR=dest const uint8_t sz = 1<<(a+(!b)); // (1=byte, 3=word, 2=long) @@ -1213,9 +1222,9 @@ static const _cc_func evaluate_cc[16] = { set_sr(new_sr); } } -}) +} -~inst(not, { +static void inst_not (void) { ~decompose(shoe.op, 0100 0110 ss MMMMMM); const uint8_t sz = 1<>3) == 3) shoe.a[M & 7] += sz; -}) +} -~inst(cas, { +static void inst_cas (void) { assert(!"inst_cas: error: not implemented!"); -}) +} -~inst(cas2, { +static void inst_cas2 (void) { assert(!"inst_cas2: error: not implemented!"); -}) +} -~inst(move_to_sr, { +static void inst_move_to_sr (void) { verify_supervisor(); ~decompose(shoe.op, 0100 0110 11 MMMMMM); call_ea_read(M, 2); // sr is 2 bytes call_ea_read_commit(M, 2); set_sr(shoe.dat); -}) +} -~inst(move_from_sr, { +static void inst_move_from_sr (void) { verify_supervisor(); ~decompose(shoe.op, 0100 0000 11 MMMMMM); shoe.dat = shoe.sr; call_ea_write(M, 2); -}) +} -~inst(neg, { +static void inst_neg (void) { ~decompose(shoe.op, 0100 0100 ss MMMMMM); const uint8_t sz = 1<> n)&1)); -}) +} -~inst(pea, { +static void inst_pea (void) { ~decompose(shoe.op, 0100 1000 01 MMMMMM); // fetch the EA call_ea_addr(M); @@ -1736,14 +1745,15 @@ static const _cc_func evaluate_cc[16] = { if (shoe.abort) return ; // decrement the stack pointer if lset didn't abort shoe.a[7] -= 4; -}) +} -~inst(subx, { +static void inst_subx (void) { ~decompose(shoe.op, 1001 yyy 1 ss 00 m xxx); const uint8_t sz = 1< short, s==1 => long @@ -2181,30 +2191,30 @@ abort: //shoe.a[M&7] += sz; return ; -}) +} -~inst(nbcd, { +static void inst_nbcd (void) { assert(!"inst_nbcd: fixme: I'm not implemented!\n"); -}) +} -~inst(eori_to_ccr, { +static void inst_eori_to_ccr (void) { const uint16_t val = 0xff & nextword(); const uint16_t new_sr = shoe.sr ^ val; set_sr(new_sr); -}) +} -~inst(eori_to_sr, { +static void inst_eori_to_sr (void) { verify_supervisor(); const uint16_t new_sr = shoe.sr ^ nextword(); set_sr(new_sr); -}) +} -~inst(movep, { +static void inst_movep (void) { assert(!"inst_movep: fixme: I'm not implemented!\n"); -}) +} void write_bitfield(const uint32_t width, const uint32_t offset, const uint32_t M, const uint32_t ea, const uint32_t raw_field) @@ -2333,7 +2343,7 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin return field; } -~inst(bfextu, { +static void inst_bfextu (void) { const uint16_t ext = nextword(); ~decompose(shoe.op, 1110 1001 11 MMMMMM); ~decompose(ext, 0 rrr Ffffff Wwwwww); @@ -2357,9 +2367,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin set_sr_v(0); set_sr_n(field >> (width-1)); set_sr_z(field == 0); -}) +} -~inst(bfchg, { +static void inst_bfchg (void) { const uint16_t ext = nextword(); ~decompose(shoe.op, 1110 1011 11 MMMMMM); ~decompose(ext, 0 000 Ffffff Wwwwww); @@ -2383,9 +2393,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin set_sr_v(0); set_sr_n(field >> (width-1)); set_sr_z(field == 0); -}) +} -~inst(bfexts, { +static void inst_bfexts (void) { const uint16_t ext = nextword(); ~decompose(shoe.op, 1110 1011 11 MMMMMM); ~decompose(ext, 0 rrr Ffffff Wwwwww); @@ -2413,9 +2423,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin set_sr_v(0); set_sr_n(mib); set_sr_z(field == 0); -}) +} -~inst(bfclr, { +static void inst_bfclr (void) { const uint16_t ext = nextword(); ~decompose(shoe.op, 1110 1011 11 MMMMMM); ~decompose(ext, 0 000 Ffffff Wwwwww); @@ -2439,9 +2449,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin set_sr_v(0); set_sr_n(field >> (width-1)); set_sr_z(field == 0); -}) +} -~inst(bfset, { +static void inst_bfset (void) { const uint16_t ext = nextword(); ~decompose(shoe.op, 1110 1011 11 MMMMMM); ~decompose(ext, 0 000 Ffffff Wwwwww); @@ -2465,9 +2475,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin set_sr_v(0); set_sr_n(field >> (width-1)); set_sr_z(field == 0); -}) +} -~inst(bftst, { +static void inst_bftst (void) { const uint16_t ext = nextword(); ~decompose(shoe.op, 1110 1000 11 MMMMMM); ~decompose(ext, 0 000 Ffffff Wwwwww); @@ -2489,9 +2499,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin set_sr_v(0); set_sr_n(field >> (width-1)); set_sr_z(field == 0); -}) +} -~inst(bfffo, { +static void inst_bfffo (void) { const uint16_t ext = nextword(); ~decompose(shoe.op, 1110 1110 11 MMMMMM); ~decompose(ext, 0 rrr Ffffff Wwwwww); @@ -2517,9 +2527,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin set_sr_v(0); set_sr_n(field >> (width-1)); set_sr_z(field == 0); -}) +} -~inst(bfins, { +static void inst_bfins (void) { const uint16_t ext = nextword(); ~decompose(shoe.op, 1110 1011 11 MMMMMM); ~decompose(ext, 0 rrr Ffffff Wwwwww); @@ -2544,9 +2554,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin set_sr_v(0); set_sr_n(field >> (width-1)); // set according to the inserted value set_sr_z(field == 0); -}) +} -~inst(btst_reg, { +static void inst_btst_reg (void) { ~decompose(shoe.op, 0000 rrr 100 MMMMMM); if ((M>>3)==0) { // if the dest is a data reg, handle specially @@ -2557,9 +2567,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin call_ea_read(M, 1); call_ea_read_commit(M, 1); set_sr_z(! ((shoe.dat >> (shoe.d[r] % 8)) & 1)); -}) +} -~inst(bchg_reg, { +static void inst_bchg_reg (void) { ~decompose(shoe.op, 0000 rrr 101 MMMMMM); // The LSB bit is idx:0, MSB is idx:7 or :31 @@ -2582,9 +2592,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin call_ea_write(M, 1); set_sr_z(z); -}) +} -~inst(bclr_reg, { +static void inst_bclr_reg (void) { ~decompose(shoe.op, 0000 rrr 111 MMMMMM); const uint8_t is_data_reg = (M>>3) == 0; @@ -2597,9 +2607,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin shoe.dat &= ~~(1 << shift); call_ea_write(M, sz); -}) +} -~inst(bclr_immediate, { +static void inst_bclr_immediate (void) { ~decompose(shoe.op, 0000 1000 11 MMMMMM); const uint16_t ext = nextword(); ~decompose(ext, 00000000 bbbbbbbb); @@ -2614,9 +2624,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin shoe.dat &= ~~(1 << shift); call_ea_write(M, sz); -}) +} -~inst(bset_reg, { +static void inst_bset_reg (void) { ~decompose(shoe.op, 0000 rrr 111 MMMMMM); const uint8_t is_data_reg = (M>>3)==0; @@ -2629,9 +2639,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin shoe.dat |= (1 << shift); call_ea_write(M, sz); -}) +} -~inst(bset_immediate, { +static void inst_bset_immediate (void) { ~decompose(shoe.op, 0000 1000 11 MMMMMM); const uint16_t ext = nextword(); ~decompose(ext, 00000000 bbbbbbbb); @@ -2646,9 +2656,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin shoe.dat |= (1 << shift); call_ea_write(M, sz); -}) +} -~inst(bchg_immediate, { +static void inst_bchg_immediate (void) { ~decompose(shoe.op, 0000 1000 01 MMMMMM); const uint16_t ext = nextword(); ~decompose(ext, 00000000 bbbbbbbb); @@ -2663,9 +2673,9 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin shoe.dat ^= (1 << shift); call_ea_write(M, sz); -}) +} -~inst(ext, { +static void inst_ext (void) { ~decompose(shoe.op, 0100 100 ooo 000 rrr); switch (o) { case ~b(010): { // byte -> word @@ -2689,35 +2699,35 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin // if the LSb of o is 1, then result size == long set_sr_z(get_d(r, 2+2*(o&1))==0); set_sr_n(mib(shoe.d[r], 2+2*(o&1))); -}) +} -~inst(andi_to_sr, { +static void inst_andi_to_sr (void) { verify_supervisor(); const uint16_t ext = nextword(); set_sr(shoe.sr & ext); -}) +} -~inst(andi_to_ccr, { +static void inst_andi_to_ccr (void) { const uint16_t ext = nextword(); set_sr(shoe.sr & (ext & 0xff)); -}) +} -~inst(ori_to_sr, { +static void inst_ori_to_sr (void) { verify_supervisor(); const uint16_t ext = nextword(); set_sr(shoe.sr | ext); -}) +} -~inst(ori_to_ccr, { +static void inst_ori_to_ccr (void) { const uint16_t ext = nextword(); set_sr(shoe.sr | (ext & 0xff)); -}) +} -~inst(mc68851_decode, { +static void inst_mc68851_decode (void) { ~decompose(shoe.op, 1111 000 a b c MMMMMM); // prestore or psave @@ -2782,19 +2792,18 @@ uint32_t extract_bitfield(const uint32_t width, const uint32_t offset, const uin return ; } assert(!"never get here"); -}) +} -void dump_ring(); -~inst(unknown, { +static void inst_unknown (void) { printf("Unknown instruction (0x%04x)!\n", shoe.op); /*if (shoe.op == 0x33fe) { dump_ring(); assert(!"dumped"); }*/ throw_illegal_instruction(); -}) +} -~inst(a_line, { +static void inst_a_line (void) { /*if (shoe.op == 0xA9EB || shoe.op == 0xA9EC) { shoe.suppress_exceptions = 1; @@ -2827,7 +2836,7 @@ void dump_ring(); }*/ throw_illegal_instruction(); -}) +} void trap_debug() { @@ -2888,7 +2897,7 @@ void trap_debug() shoe.suppress_exceptions = 0; } -~inst(trap, { +static void inst_trap (void) { ~decompose(shoe.op, 0100 1110 0100 vvvv); const uint32_t vector_num = 32 + v; @@ -2913,7 +2922,7 @@ void trap_debug() fail: assert(!"trap - push_a7 raised shoe.abort\n"); // I can't handle this yet -}) +} #include "inst_decoder_guts.c" diff --git a/core/debug_server.c b/core/debug_server.c deleted file mode 100644 index 29b4cf0..0000000 --- a/core/debug_server.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2014, Peter Rutenbar - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../core/shoebill.h" -#include "../core/coff.h" - -#define DEBUG_MODE_STOPPED 0 -#define DEBUG_MODE_RUNNING 1 -#define DEBUG_MODE_STEP 2 - -#define SHOEBILL_DEBUG_PORT 0xfded -static int _start_debug_server(void) -{ - struct sockaddr_in addr; - int sock = socket(AF_INET, SOCK_STREAM, 0); - - memset(&addr, 0, sizeof(addr)); - addr.sin_len = sizeof(struct sockaddr_in); - addr.sin_family = AF_INET; - addr.sin_port = htons(SHOEBILL_DEBUG_PORT); - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - if (sock == -1) { - assert(!"can't socket"); - } - else if (bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)) != 0) { - assert(!"can't bind"); - // return -1; - } - else if (listen(sock, 1) != 0) { - assert(!"can't listen"); - } - - return sock; -} - -void *debug_server_thread (void *arg) -{ - struct sockaddr_in addr; - socklen_t sin_size = sizeof(struct sockaddr_in); - uint8_t *inbuf = calloc(0x10000, 1); - uint8_t *outbuf = calloc(0x10000, 1); - int sock = _start_debug_server(); - int clientfd = accept(sock, (struct sockaddr*)&addr, &sin_size); - - shoe.dbg.connected = 1; - shoe.dbg.mode = DEBUG_MODE_RUNNING; - - - return NULL; -} - -void *debug_cpu_thread (void *arg) -{ - memset(&shoe.dbg, 0, sizeof(shoe.dbg)); - shoe.dbg.mode = DEBUG_MODE_STOPPED; - - pthread_t server_thread_pid; - pthread_create(&server_thread_pid, - NULL, - debug_server_thread, - NULL); - - /* - * The CPU only runs once the debugger is connected, and the - * emulator has started - */ - pthread_mutex_lock(&shoe.cpu_thread_lock); - while (!shoe.dbg.connected) - usleep(1000); - - while (1) { - if (shoe.dbg.mode == DEBUG_MODE_RUNNING) { - if (!shoe.dbg.ignore_interrupts && - (shoe.cpu_thread_notifications & 0xff)) { - process_pending_interrupt(); - } - - if (shoe.cpu_thread_notifications & SHOEBILL_STATE_STOPPED) { - continue; - } - - cpu_step(); - } - else if (shoe.dbg.mode == DEBUG_MODE_STOPPED) - pthread_yield_np(); - else if (shoe.dbg.mode == DEBUG_MODE_STEP) { - cpu_step(); - shoe.dbg.mode = DEBUG_MODE_STOPPED; - } - } -} - - - diff --git a/core/dis.c b/core/dis.c index 8a50570..002c221 100644 --- a/core/dis.c +++ b/core/dis.c @@ -794,24 +794,40 @@ void dis_movea () { } void dis_move () { - ~decompose(dis_op, 00 ss RRR MMM oooooo) + ~decompose(dis_op, 00 ss RRR MMM oooooo); // (oooooo = source EA), (MMMRRR = dest EA) - const uint8_t sizes[3] = {1, 4, 2}; - const char *sourceStr = decode_ea_rw(o, sizes[s-1]); - const char *destStr = decode_ea_rw((M<<3)|R, sizes[s-1]); - sprintf(dis.str, "move.%c %s,%s", "blw"[s-1], sourceStr, destStr); + const uint8_t sizes[4] = {0, 1, 4, 2}; + const char *sourceStr = decode_ea_rw(o, sizes[s]); + const char *destStr = decode_ea_rw((M<<3)|R, sizes[s]); + sprintf(dis.str, "move.%c %s,%s", "?blw"[s], sourceStr, destStr); } void dis_move_d_to_d () { - sprintf(dis.str, "move_d_to_d ???"); + ~decompose(dis_op, 00 ss DDD 000 000 SSS); + sprintf(dis.str, "move.%c d%u,d%u", "?blw"[s], S, D); } void dis_move_to_d () { - sprintf(dis.str, "move_to_d ???"); + ~decompose(dis_op, 00 ss rrr 000 MMMMMM); + const uint8_t sizes[4] = {0, 1, 4, 2}; + + sprintf(dis.str, + "move.%c %s,d%u", + "?blw"[s], + decode_ea_rw(M, sizes[s]), + r); } void dis_move_from_d () { - sprintf(dis.str, "move_from_d ???"); + ~decompose(dis_op, 00 ss RRR MMM 000 rrr); + const uint8_t sizes[4] = {0, 1, 4, 2}; + + sprintf(dis.str, + "move.%c d%u,%s", + "?blw"[s], + r, + decode_ea_rw((M<<3) | R, sizes[s])); + } void dis_scc () { diff --git a/core/mem.c b/core/mem.c index df2a870..7699447 100644 --- a/core/mem.c +++ b/core/mem.c @@ -46,8 +46,26 @@ void _physical_get_ram (void) else addr = (uint64_t*)&shoe.physical_mem_base[shoe.physical_addr % shoe.physical_mem_size]; + /*if ((shoe.physical_addr >= 0x100) && (shoe.physical_addr < (0x4000+256))) { + uint32_t i, val = 0; + _Bool uninit = 0; + for (i=0; i> bits; + + if ((shoe.physical_addr >= 256) && (shoe.physical_addr < 0x4000)) { + printf("LOMEM get: *0x%08x = 0x%x\n", shoe.physical_addr, (uint32_t)shoe.physical_dat); + } } void _physical_get_rom (void) @@ -61,13 +79,8 @@ void _physical_get_rom (void) void _physical_get_io (void) { switch (shoe.physical_addr & 0x5003ffff) { - case 0x50000000 ... 0x50001fff: // VIA1 - via_reg_read(); - // printf("physical_get: got read to VIA1 (%x & 0x5003ffff = %x)\n", shoe.physical_addr, shoe.physical_addr & 0x5003ffff); - return ; - case 0x50002000 ... 0x50003fff: // VIA2 - via_reg_read(); - // printf("physical_get: got read to VIA2\n"); + case 0x50000000 ... 0x50003fff: // VIA1 + VIA2 + via_read_raw(); return ; case 0x50004000 ... 0x50005fff: {// SCC //printf("physical_get: got read to SCC\n"); @@ -77,8 +90,6 @@ void _physical_get_io (void) return ; } case 0x50006000 ... 0x50007fff: // SCSI (pseudo-DMA with DRQ?) - //printf("physical_get: got read to SCSI low\n"); - //assert(!"physical_get: got read to SCSI low"); assert(shoe.logical_size == 4); shoe.physical_dat = scsi_dma_read_long(); return ; @@ -88,11 +99,12 @@ void _physical_get_io (void) case 0x50012000 ... 0x50013fff: // SCSI (pseudo-DMA with no DRQ?) assert(shoe.logical_size == 1); shoe.physical_dat = scsi_dma_read(); - // printf("physical_get: got read to SCSI hi\n"); - // assert(!"physical_get: got read to SCSI hi\n"); return ; case 0x50014000 ... 0x50015fff: // Sound //printf("physical_get: got read to sound\n"); + printf("soundsound read : register 0x%04x sz=%u\n", + shoe.physical_addr - 0x50014000, shoe.physical_size); + shoe.physical_dat = 0; return ; case 0x50016000 ... 0x50017fff: // SWIM (IWM?) // printf("physical_get: got read to IWM\n"); @@ -157,6 +169,10 @@ void _physical_set_ram (void) else addr = &shoe.physical_mem_base[shoe.physical_addr]; + if ((shoe.physical_addr >= 0x100) && (shoe.physical_addr < (0x8000))) { + printf("LOMEM set: *0x%08x = 0x%x\n", shoe.physical_addr, (uint32_t)chop(shoe.physical_dat, shoe.physical_size)); + } + const uint32_t sz = shoe.physical_size; switch (sz) { case 1: @@ -195,13 +211,8 @@ void _physical_set_rom (void) void _physical_set_io (void) { switch (shoe.physical_addr & 0x5003ffff) { - case 0x50000000 ... 0x50001fff: // VIA1 - via_reg_write(); - // printf("physical_set: got write to VIA1\n"); - return ; - case 0x50002000 ... 0x50003fff: // VIA2 - via_reg_write(); - // printf("physical_set: got write to VIA2\n"); + case 0x50000000 ... 0x50003fff: // VIA1 + VIA2 + via_write_raw(); return ; case 0x50004000 ... 0x50005fff: // SCC //printf("physical_set: got write to SCC\n"); @@ -216,11 +227,11 @@ void _physical_set_io (void) case 0x50012000 ... 0x50013fff: // SCSI (pseudo-DMA with no DRQ?) assert(shoe.physical_size == 1); scsi_dma_write(shoe.physical_dat); - //printf("physical_set: got write to SCSI hi\n"); - //assert(!"physical_set: got write to SCSI hi\n"); return ; case 0x50014000 ... 0x50015fff: // Sound - printf("physical_set: got write to sound\n"); + printf("soundsound write: register 0x%04x sz=%u dat=0x%x\n", + shoe.physical_addr - 0x50014000, shoe.physical_size, (uint32_t)shoe.physical_dat); + // printf("physical_set: got write to sound\n"); return ; case 0x50016000 ... 0x50017fff: // SWIM (IWM?) //printf("physical_set: got write to IWM\n"); @@ -339,7 +350,7 @@ static void translate_logical_addr() uint8_t desc_size = 1; // And the root pointer descriptor is always 8 bytes (1==8 bytes, 0==4 bytes) uint8_t used_bits = tc_is(); // Keep track of how many bits will be the effective "page size" // (If the table search terminates early (before used_bits == ts_ps()), - // then this will be the effective page size. That is, the number of bits + // then (32 - used_bits) will be the effective page size. That is, the number of bits // we or into the physical addr from the virtual addr) desc_addr = -1; // address of the descriptor (-1 -> register) @@ -801,275 +812,581 @@ static void ea_decode_extended() } -void ea_read() +// Data register direct mode +void _ea_000_read (void) +{ + shoe.dat = get_d(shoe.mr & 7, shoe.sz); +} +void _ea_000_write (void) +{ + set_d(shoe.mr & 7, shoe.dat, shoe.sz); +} + + +// address register direct mode +void _ea_001_read (void) +{ + shoe.dat = get_a(shoe.mr & 7, shoe.sz); +} +void _ea_001_write (void) +{ + assert(shoe.sz==4); + shoe.a[shoe.mr & 7] = shoe.dat; +} + + +// address register indirect mode +void _ea_010_read (void) +{ + shoe.dat = lget(shoe.a[shoe.mr & 7], shoe.sz); +} +void _ea_010_write (void) +{ + lset(shoe.a[shoe.mr & 7], shoe.sz, shoe.dat); +} +void _ea_010_addr (void) +{ + shoe.dat = shoe.a[shoe.mr & 7]; +} + + +// address register indirect with postincrement mode +void _ea_011_read (void) +{ + shoe.dat = lget(shoe.a[shoe.mr & 7], shoe.sz); +} +void _ea_011_read_commit (void) +{ + const uint8_t reg = shoe.mr & 7; + shoe.a[reg] += (((reg==7) && (shoe.sz==1)) ? 2 : shoe.sz); +} +void _ea_011_write (void) +{ + const uint8_t reg = shoe.mr & 7; + const uint8_t delta = ((reg==7) && (shoe.sz==1)) ? 2 : shoe.sz; + + lset(shoe.a[reg], shoe.sz, shoe.dat); + if (!shoe.abort) + shoe.a[reg] += delta; +} + + +// address register indirect with predecrement mode +void _ea_100_read (void) +{ + const uint8_t reg = shoe.mr & 7; + const uint8_t delta = ((reg==7) && (shoe.sz==1))?2:shoe.sz; + shoe.dat = lget(shoe.a[reg]-delta, shoe.sz); +} +void _ea_100_read_commit (void) +{ + const uint8_t reg = shoe.mr & 7; + shoe.a[reg] -= (((reg==7) && (shoe.sz==1)) ? 2 : shoe.sz); +} +void _ea_100_write (void) +{ + const uint8_t reg = shoe.mr & 7; + const uint8_t delta = ((reg==7) && (shoe.sz==1)) ? 2 : shoe.sz; + + lset(shoe.a[reg] - delta, shoe.sz, shoe.dat); + if (!shoe.abort) + shoe.a[reg] -= delta; +} + + +// address register indirect with displacement mode +void _ea_101_read (void) { - const uint8_t mode = (shoe.mr>>3)&7, reg = (shoe.mr&7); shoe.uncommitted_ea_read_pc = shoe.pc; - switch (mode) { - case 0: { // Data register direct mode - shoe.dat = get_d(reg, shoe.sz); - return ; - } - case 1: { // address register direct mode - shoe.dat = get_a(reg, shoe.sz); - return ; - } - case 2: { // address register indirect mode - shoe.dat = lget(shoe.a[reg], shoe.sz); - return ; - } - case 3: { // address register indirect with postincrement mode - shoe.dat = lget(shoe.a[reg], shoe.sz); - // printf("ea_read(): %u %u not implemented\n", mode, reg); - return ; - } - case 4: { // address register indirect with predecrement mode - const uint8_t delta = ((reg==7) && (shoe.sz==1))?2:shoe.sz; - shoe.dat = lget(shoe.a[reg]-delta, shoe.sz); - return ; - } - case 5: { // address register indirect with displacement mode - const int16_t disp = nextword(shoe.uncommitted_ea_read_pc); - shoe.dat = lget(shoe.a[reg]+disp, shoe.sz); - return ; - } - case 6: { - ea_decode_extended(); - if (shoe.abort) return ; - shoe.dat = lget(shoe.extended_addr, shoe.sz); - return ; - } - case 7: { - switch (reg) { - case 0: { // absolute short addressing mode - const int32_t addr = (int16_t)nextword(shoe.uncommitted_ea_read_pc); - shoe.dat = lget((uint32_t)addr, shoe.sz); - return ; - } - case 1: { // absolute long addressing mode - const uint32_t addr = nextlong(shoe.uncommitted_ea_read_pc); - shoe.dat = lget(addr, shoe.sz); - return ; - } - case 2: { // program counter indirect with displacement mode - const uint32_t base_pc = shoe.uncommitted_ea_read_pc; - const uint16_t u_disp = nextword(shoe.uncommitted_ea_read_pc); - const int16_t disp = (int16_t)u_disp; - - shoe.dat = lget(base_pc + disp, shoe.sz); - return ; - } - case 3: { // (program counter ...) - ea_decode_extended(); - if (shoe.abort) return ; - shoe.dat = lget(shoe.extended_addr, shoe.sz); - return ; - } - case 4: { // immediate data - if (shoe.sz==1) { - shoe.dat = nextword(shoe.uncommitted_ea_read_pc) & 0xff; - } else if (shoe.sz == 2) { - shoe.dat = nextword(shoe.uncommitted_ea_read_pc); - } else if (shoe.sz == 4) { - shoe.dat = nextlong(shoe.uncommitted_ea_read_pc); - } else if (shoe.sz == 8) { - const uint64_t q = nextlong(shoe.uncommitted_ea_read_pc); - shoe.dat = (q<<32) | nextlong(shoe.uncommitted_ea_read_pc); - } - return ; - } - default: - throw_illegal_instruction(); - return ; - } - } - } + const int16_t disp = nextword(shoe.uncommitted_ea_read_pc); + shoe.dat = lget(shoe.a[shoe.mr & 7] + disp, shoe.sz); } - -void ea_read_commit() +void _ea_101_read_commit (void) { - const uint8_t mode = (shoe.mr>>3)&7, reg = (shoe.mr&7); - switch (mode) { - case 0: // Data register direct mode - case 1: // address register direct mode - case 2: // address register indirect mode - return ; // nothing to do - - case 3: { // address register indirect with postincrement mode - const uint8_t delta = ((reg==7) && (shoe.sz==1))?2:shoe.sz; - shoe.a[reg] += delta; - return ; - } - case 4: { // address register indirect with predecrement mode - const uint8_t delta = ((reg==7) && (shoe.sz==1))?2:shoe.sz; - shoe.a[reg] -= delta; - return ; - } - case 5: { // address register indirect with displacement mode - shoe.pc += 2; // this mode fetches one word - return ; - } - case 6: { - // shoe.extended_len was set in the previous ea_read() call. - shoe.pc += shoe.extended_len; - return ; - } - case 7: { - switch (reg) { - case 0: { // absolute short addressing mode - shoe.pc+=2; - return ; - } - case 1: { // absolute long addressing mode - shoe.pc+=4; - return ; - } - case 2: { // program counter indirect with displacement mode - shoe.pc+=2; - return ; - } - case 3: { // (program counter ...) - // shoe.extended_len was set in the previous ea_read() call. - shoe.pc += shoe.extended_len; - return ; - } - case 4: { // immediate data - if (shoe.sz==1) shoe.pc += 2; - else shoe.pc += shoe.sz; - return ; - } - default: - throw_illegal_instruction(); - return ; - } - } - } + shoe.pc += 2; } - -void ea_write() +void _ea_101_write (void) { - const uint8_t mode = (shoe.mr>>3)&7, reg = (shoe.mr&7); - switch (mode) { - case 0: { // Data register direct mode - set_d(reg, shoe.dat, shoe.sz); - return ; - } - case 1: { // address register direct mode - assert(shoe.sz==4); - shoe.a[reg] = shoe.dat; - return ; - } - case 2: { // address register indirect mode - lset(shoe.a[reg], shoe.sz, shoe.dat); - return ; - } - case 3: { // address register indirect with postincrement mode - const uint8_t delta = ((reg==7) && (shoe.sz==1))?2:shoe.sz; - - lset(shoe.a[reg], shoe.sz, shoe.dat); - if (!shoe.abort) - shoe.a[reg] += delta; - return ; - } - case 4: { // address register indirect with predecrement mode - const uint8_t delta = ((reg==7) && (shoe.sz==1))?2:shoe.sz; - lset(shoe.a[reg]-delta, shoe.sz, shoe.dat); - if (!shoe.abort) - shoe.a[reg] -= delta; - return ; - } - case 5: { // address register indirect with displacement mode - const uint16_t u_disp = nextword(shoe.pc); - const int16_t disp = (int16_t)u_disp; // sign-extend word to long - lset(shoe.a[reg]+disp, shoe.sz, shoe.dat); - return ; - } - case 6: { - ea_decode_extended(); - if (shoe.abort) return ; - - lset(shoe.extended_addr, shoe.sz, shoe.dat); - if (shoe.abort) return ; - - shoe.pc += shoe.extended_len; - return ; - } - case 7: { - switch (reg) { - case 0: { // absolute short addressing mode - const int32_t addr = (int16_t)nextword(shoe.pc); - lset((uint32_t)addr, shoe.sz, shoe.dat); - return ; - } - case 1: { // absolute long addressing mode - const uint32_t addr = nextlong(shoe.pc); - lset(addr, shoe.sz, shoe.dat); - // printf("ea_write(): %u %u not implemented\n", mode, reg); - return ; - } - } - } - // fall through - default: - throw_illegal_instruction(); - return ; - } + const int16_t disp = nextword(shoe.pc); + lset(shoe.a[shoe.mr & 7] + disp, shoe.sz, shoe.dat); } - -void ea_addr() +void _ea_101_addr (void) { - const uint8_t mode = (shoe.mr>>3)&7, reg = (shoe.mr&7); - switch (mode) { - case 2: { // address register indirect mode - shoe.dat = shoe.a[reg]; - return ; - } - case 5: { // address register indirect with displacement mode - int16_t disp = nextword(shoe.pc); - shoe.dat = shoe.a[reg] + disp; - return ; - } - case 6: { - ea_decode_extended(); - if (shoe.abort) return ; - shoe.dat = shoe.extended_addr; + const int16_t disp = nextword(shoe.pc); + shoe.dat = shoe.a[shoe.mr & 7] + disp; +} + + +// memory/address register indirect with index +void _ea_110_read (void) +{ + ea_decode_extended(); + if (!shoe.abort) + shoe.dat = lget(shoe.extended_addr, shoe.sz); + shoe.uncommitted_ea_read_pc = shoe.pc + shoe.extended_len; +} +void _ea_110_read_commit (void) +{ + shoe.pc = shoe.uncommitted_ea_read_pc; +} +void _ea_110_write (void) +{ + ea_decode_extended(); + if (!shoe.abort) { + lset(shoe.extended_addr, shoe.sz, shoe.dat); + if (!shoe.abort) shoe.pc += shoe.extended_len; - return ; - } - case 7: { - switch (reg) { - case 0: { // absolute short addressing mode - int32_t addr = (int16_t)nextword(shoe.pc); - shoe.dat = (uint32_t)addr; - return ; - } - case 1: { // absolute long addressing mode - const uint32_t addr = nextlong(shoe.pc); - shoe.dat = addr; - return ; - } - case 2: { // program counter indirect with displacement mode - const uint32_t oldpc = shoe.pc; - const uint16_t displacement = nextword(shoe.pc); - shoe.dat = oldpc + (int16_t)displacement; - return ; - } - case 3: { // (program counter ...) - ea_decode_extended(); - if (shoe.abort) return ; - shoe.dat = shoe.extended_addr; - shoe.pc += shoe.extended_len; - return ; - } - } - } - default: - throw_illegal_instruction(); - return ; + } +} +void _ea_110_addr (void) +{ + ea_decode_extended(); + if (!shoe.abort) { + shoe.dat = shoe.extended_addr; + shoe.pc += shoe.extended_len; } } +// absolute short addressing mode +void _ea_111_000_read (void) +{ + shoe.uncommitted_ea_read_pc = shoe.pc; + const int32_t addr = (int16_t)nextword(shoe.uncommitted_ea_read_pc); + shoe.dat = lget((uint32_t)addr, shoe.sz); +} +void _ea_111_000_read_commit (void) +{ + shoe.pc += 2; +} +void _ea_111_000_write (void) +{ + const int32_t addr = (int16_t)nextword(shoe.pc); + lset((uint32_t)addr, shoe.sz, shoe.dat); +} +void _ea_111_000_addr (void) +{ + const int32_t addr = (int16_t)nextword(shoe.pc); + shoe.dat = (uint32_t)addr; +} + + +// absolute long addressing mode +void _ea_111_001_read (void) +{ + shoe.uncommitted_ea_read_pc = shoe.pc; + const uint32_t addr = nextlong(shoe.uncommitted_ea_read_pc); + shoe.dat = lget(addr, shoe.sz); +} +void _ea_111_001_read_commit (void) +{ + shoe.pc += 4; +} +void _ea_111_001_write (void) +{ + const uint32_t addr = nextlong(shoe.pc); + lset(addr, shoe.sz, shoe.dat); +} +void _ea_111_001_addr (void) +{ + const uint32_t addr = nextlong(shoe.pc); + shoe.dat = addr; +} + +// program counter indirect with displacement mode +void _ea_111_010_read (void) +{ + const uint32_t base_pc = shoe.pc; + shoe.uncommitted_ea_read_pc = base_pc; + const int16_t disp = nextword(shoe.uncommitted_ea_read_pc); + shoe.dat = lget(base_pc + disp, shoe.sz); +} +void _ea_111_010_read_commit (void) +{ + shoe.pc += 2; +} +void _ea_111_010_addr (void) +{ + const uint32_t oldpc = shoe.pc; + const int16_t displacement = nextword(shoe.pc); + shoe.dat = oldpc + displacement; +} + + +// (program counter ...) +void _ea_111_011_read (void) +{ + ea_decode_extended(); + if (!shoe.abort) + shoe.dat = lget(shoe.extended_addr, shoe.sz); + shoe.uncommitted_ea_read_pc = shoe.pc + shoe.extended_len; +} +void _ea_111_011_read_commit (void) +{ + shoe.pc = shoe.uncommitted_ea_read_pc; +} +void _ea_111_011_addr (void) +{ + ea_decode_extended(); + if (!shoe.abort) { + shoe.dat = shoe.extended_addr; + shoe.pc += shoe.extended_len; + } +} + + +// immediate data +void _ea_111_100_read (void) +{ + if (shoe.sz == 1) { + shoe.uncommitted_ea_read_pc = shoe.pc + 2; + shoe.dat = lget(shoe.pc, 2) & 0xff; + } + else { + shoe.uncommitted_ea_read_pc = shoe.pc + shoe.sz; + shoe.dat = lget(shoe.pc, shoe.sz); + } +} +void _ea_111_100_read_commit (void) +{ + shoe.pc = shoe.uncommitted_ea_read_pc; +} + + +// illegal EA mode +void _ea_illegal (void) +{ + throw_illegal_instruction(); +} + +// nothing to do +void _ea_nop (void) +{ +} + + +const _ea_func ea_read_jump_table[64] = { + // Data register direct mode + _ea_000_read, + _ea_000_read, + _ea_000_read, + _ea_000_read, + _ea_000_read, + _ea_000_read, + _ea_000_read, + _ea_000_read, + // address register direct mode + _ea_001_read, + _ea_001_read, + _ea_001_read, + _ea_001_read, + _ea_001_read, + _ea_001_read, + _ea_001_read, + _ea_001_read, + // address register indirect mode + _ea_010_read, + _ea_010_read, + _ea_010_read, + _ea_010_read, + _ea_010_read, + _ea_010_read, + _ea_010_read, + _ea_010_read, + // address register indirect with postincrement mode + _ea_011_read, + _ea_011_read, + _ea_011_read, + _ea_011_read, + _ea_011_read, + _ea_011_read, + _ea_011_read, + _ea_011_read, + // address register indirect with predecrement mode + _ea_100_read, + _ea_100_read, + _ea_100_read, + _ea_100_read, + _ea_100_read, + _ea_100_read, + _ea_100_read, + _ea_100_read, + // address register indirect with displacement mode + _ea_101_read, + _ea_101_read, + _ea_101_read, + _ea_101_read, + _ea_101_read, + _ea_101_read, + _ea_101_read, + _ea_101_read, + // memory/address register indirect with index + _ea_110_read, + _ea_110_read, + _ea_110_read, + _ea_110_read, + _ea_110_read, + _ea_110_read, + _ea_110_read, + _ea_110_read, + // absolute short addressing mode + _ea_111_000_read, + // absolute long addressing mode + _ea_111_001_read, + // program counter indirect with displacement mode + _ea_111_010_read, + // program counter indirect with index + _ea_111_011_read, + // immediate + _ea_111_100_read, + // The rest are illegal EA modes + _ea_illegal, + _ea_illegal, + _ea_illegal +}; + +const _ea_func ea_read_commit_jump_table[64] = { + // Data register direct mode + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + // address register direct mode + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + // address register indirect mode + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + _ea_nop, + // address register indirect with postincrement mode + _ea_011_read_commit, + _ea_011_read_commit, + _ea_011_read_commit, + _ea_011_read_commit, + _ea_011_read_commit, + _ea_011_read_commit, + _ea_011_read_commit, + _ea_011_read_commit, + // address register indirect with predecrement mode + _ea_100_read_commit, + _ea_100_read_commit, + _ea_100_read_commit, + _ea_100_read_commit, + _ea_100_read_commit, + _ea_100_read_commit, + _ea_100_read_commit, + _ea_100_read_commit, + // address register indirect with displacement mode + _ea_101_read_commit, + _ea_101_read_commit, + _ea_101_read_commit, + _ea_101_read_commit, + _ea_101_read_commit, + _ea_101_read_commit, + _ea_101_read_commit, + _ea_101_read_commit, + // memory/address register indirect with index + _ea_110_read_commit, + _ea_110_read_commit, + _ea_110_read_commit, + _ea_110_read_commit, + _ea_110_read_commit, + _ea_110_read_commit, + _ea_110_read_commit, + _ea_110_read_commit, + // absolute short addressing mode + _ea_111_000_read_commit, + // absolute long addressing mode + _ea_111_001_read_commit, + // program counter indirect with displacement mode + _ea_111_010_read_commit, + // program counter indirect with index + _ea_111_011_read_commit, + // immediate + _ea_111_100_read_commit, + // The rest are illegal EA modes + NULL, + NULL, + NULL +}; + +const _ea_func ea_write_jump_table[64] = { + // Data register direct mode + _ea_000_write, + _ea_000_write, + _ea_000_write, + _ea_000_write, + _ea_000_write, + _ea_000_write, + _ea_000_write, + _ea_000_write, + // address register direct mode + _ea_001_write, + _ea_001_write, + _ea_001_write, + _ea_001_write, + _ea_001_write, + _ea_001_write, + _ea_001_write, + _ea_001_write, + // address register indirect mode + _ea_010_write, + _ea_010_write, + _ea_010_write, + _ea_010_write, + _ea_010_write, + _ea_010_write, + _ea_010_write, + _ea_010_write, + // address register indirect with postincrement mode + _ea_011_write, + _ea_011_write, + _ea_011_write, + _ea_011_write, + _ea_011_write, + _ea_011_write, + _ea_011_write, + _ea_011_write, + // address register indirect with predecrement mode + _ea_100_write, + _ea_100_write, + _ea_100_write, + _ea_100_write, + _ea_100_write, + _ea_100_write, + _ea_100_write, + _ea_100_write, + // address register indirect with displacement mode + _ea_101_write, + _ea_101_write, + _ea_101_write, + _ea_101_write, + _ea_101_write, + _ea_101_write, + _ea_101_write, + _ea_101_write, + // memory/address register indirect with index + _ea_110_write, + _ea_110_write, + _ea_110_write, + _ea_110_write, + _ea_110_write, + _ea_110_write, + _ea_110_write, + _ea_110_write, + // absolute short addressing mode + _ea_111_000_write, + // absolute long addressing mode + _ea_111_001_write, + // program counter indirect with displacement mode + _ea_illegal, + // program counter indirect with index + _ea_illegal, + // immediate + _ea_illegal, + // The rest are illegal EA modes + _ea_illegal, + _ea_illegal, + _ea_illegal +}; + + +const _ea_func ea_addr_jump_table[64] = { + // Data register direct mode + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + // address register direct mode + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + // address register indirect mode + _ea_010_addr, + _ea_010_addr, + _ea_010_addr, + _ea_010_addr, + _ea_010_addr, + _ea_010_addr, + _ea_010_addr, + _ea_010_addr, + // address register indirect with postincrement mode + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + // address register indirect with predecrement mode + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + _ea_illegal, + // address register indirect with displacement mode + _ea_101_addr, + _ea_101_addr, + _ea_101_addr, + _ea_101_addr, + _ea_101_addr, + _ea_101_addr, + _ea_101_addr, + _ea_101_addr, + // memory/address register indirect with index + _ea_110_addr, + _ea_110_addr, + _ea_110_addr, + _ea_110_addr, + _ea_110_addr, + _ea_110_addr, + _ea_110_addr, + _ea_110_addr, + // absolute short addressing mode + _ea_111_000_addr, + // absolute long addressing mode + _ea_111_001_addr, + // program counter indirect with displacement mode + _ea_111_010_addr, + // program counter indirect with index + _ea_111_011_addr, + // immediate + _ea_illegal, + // The rest are illegal EA modes + _ea_illegal, + _ea_illegal, + _ea_illegal +}; + + diff --git a/core/old_debugger.c b/core/old_debugger.c deleted file mode 100644 index f2161c7..0000000 --- a/core/old_debugger.c +++ /dev/null @@ -1,1240 +0,0 @@ -/* - * Copyright (c) 2013, Peter Rutenbar - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "../shoebill.h" -#include "../coff.h" - -struct dbg_state_t dbg_state; - -void print_mmu_rp(uint64_t rp) -{ - printf("lu=%u limit=0x%x sg=%u dt=%u addr=0x%08x\n", rp_lu(rp), rp_limit(rp), rp_sg(rp), rp_dt(rp), rp_addr(rp)); -} - -void printregs() -{ - printf("[d0]%08x [d1]%08x [d2]%08x [d3]%08x\n", shoe.d[0], shoe.d[1], shoe.d[2], shoe.d[3]); - printf("[d4]%08x [d5]%08x [d6]%08x [d7]%08x\n", shoe.d[4], shoe.d[5], shoe.d[6], shoe.d[7]); - printf("[a0]%08x [a1]%08x [a2]%08x [a3]%08x\n", shoe.a[0], shoe.a[1], shoe.a[2], shoe.a[3]); - printf("[a4]%08x [a5]%08x [a6]%08x [a7]%08x\n", shoe.a[4], shoe.a[5], shoe.a[6], shoe.a[7]); - printf("[pc]%08x [sr]%c%c%c%c%c%c%c [tc]%08x\n", shoe.pc, - sr_s()?'S':'s', - sr_m()?'M':'m', - sr_x()?'X':'x', - sr_n()?'N':'n', - sr_z()?'Z':'z', - sr_v()?'V':'v', - sr_c()?'C':'c', - shoe.tc - ); - - printf("[vbr]%08x\n", shoe.vbr); - - printf("srp: "); - print_mmu_rp(shoe.srp); - - printf("crp: "); - print_mmu_rp(shoe.crp); - - printf("tc: e=%u sre=%u fcl=%u ps=%u is=%u (tia=%u tib=%u tic=%u tid=%u)\n", - tc_enable(), tc_sre(), tc_fcl(), tc_ps(), tc_is(), tc_tia(), tc_tib(), tc_tic(), tc_tid()); - - printf("\n"); -} - -void print_pc() -{ - char str[1024]; - uint8_t binary[32]; - uint32_t i; - uint32_t len; - const char *name = NULL; - - if ((shoe.pc >= 0x40000000) && (shoe.pc < 0x50000000)) { - uint32_t i, addr = shoe.pc % (shoe.physical_rom_size); - for (i=0; macii_rom_symbols[i].name; i++) { - if (macii_rom_symbols[i].addr > addr) { - break; - } - name = macii_rom_symbols[i].name; - } - } - else if (sr_s()) { // these symbols are only meaningful in supervisor mode - coff_symbol *symb = coff_find_func(shoe.coff, shoe.pc); - if (symb && strlen(symb->name)) - name = symb->name; - } - else { - if ((shoe.pc >= 0x10000000) && (shoe.pc < 0x20000000)) { - uint32_t i, addr = shoe.pc % (shoe.physical_rom_size); - for (i=0; macii_rom_symbols[i].name; i++) { - if (macii_rom_symbols[i].addr > addr) { - break; - } - name = macii_rom_symbols[i].name; - } - } - else { - coff_symbol *symb = coff_find_func(shoe.launch, shoe.pc); - if (symb) - name = symb->name; - } - } - - const uint16_t old_abort = shoe.abort; - shoe.suppress_exceptions = 1; - - for (i=0; i<32; i++) { - binary[i] = (uint8_t) lget(shoe.pc+i, 1); - } - - disassemble_inst(binary, shoe.pc, str, &len); - - printf("*0x%08x %s [ ", shoe.pc, name ? name : ""); - for (i=0; inext) { - if (shoe.pc == cur->addr) { - printf("Hit breakpoint %llu *0x%08x\n", cur->num, shoe.pc); - dbg_state.running = 0; - return ; - } - } - - if (shoe.dbg) { - // printf("*0x1ff01074 = %llx\n", lget(0x1ff01074, 4)); - print_pc(); - printregs(); - } - -// if ((shoe.pc >= 0x40000000) && (shoe.pc < 0x50000000)) { -// //print_pc(); -// //printregs(); -// } -// else { -// coff_symbol *symb = coff_find_func(shoe.coff, shoe.pc); -// if ((symb && (strcmp(symb->name, "scsitask")==0)) || -// /*(symb && (strcmp(symb->name, "scsiget")==0)) || -// (symb && (strcmp(symb->name, "scsi_out")==0)) || -// (symb && (strcmp(symb->name, "scsireq")==0)) || -// (symb && (strcmp(symb->name, "scsi_vio")==0)) || -// (symb && (strcmp(symb->name, "binit")==0)) ||*/ -// (symb && (strcmp(symb->name, "realvtopte")==0)) || -// (symb && (strcmp(symb->name, "realvtop")==0)) || -// (symb && (strcmp(symb->name, "realsvtop")==0)) || /* -// (symb && (strcmp(symb->name, "sdcmd")==0)) || -// (symb && (strcmp(symb->name, "sdread")==0)) || -// (symb && (strcmp(symb->name, "gdpartinit")==0)) || -// (symb && (strcmp(symb->name, "scsi_in")==0)) || -// (symb && (strcmp(symb->name, "gddriveinit")==0)) || -// (symb && (strcmp(symb->name, "vio_init")==0)) || -// (symb && (strcmp(symb->name, "get_psr")==0)) || -// (symb && (strcmp(symb->name, "scsisched")==0)) || -// (symb && (strcmp(symb->name, "choosetask")==0)) || */ -// (symb && (strcmp(symb->name, "scsiselect")==0))) { -// print_pc(); -// printregs(); -// } -// else if ((shoe.pc > (0x0014ea02-32)) && (shoe.pc < (0x0014ea02+32))) { -// print_pc(); -// printregs(); -// } -// } -} - - -char *cli_prompt_callback(EditLine *el) -{ - return "~ "; -} - -// Hack to clear line after ^C. el_reset() screws up tty when called from the signal handler. -void ch_reset(EditLine *el, int mclear); - -void signal_callback(int sig) -{ - EditLine *el = dbg_state.el; - (void) signal(SIGINT, signal_callback); - (void) signal(SIGWINCH, signal_callback); - - switch (sig) { - case SIGWINCH: - el_resize(el); - break ; - case SIGINT: - if (dbg_state.running) { - dbg_state.running = 0; - } - else { - printf("\n"); - ch_reset(el, 0); - el_set(el, EL_REFRESH); - } - break ; - } - - return ; -} - -void verb_backtrace_handler (const char *line) -{ - const uint32_t old_abort = shoe.abort; - shoe.suppress_exceptions = 1; - shoe.abort = 0; - - // link - // push a6 to a7 - // set a6 = a7 - // set a7 = a7 - (some stack space) - - // jsr - // push return pointer to a7 - - // call - // set a7 = a7 - (some stack space) - // push arguments to a7 - // push return pointer to a7 - // (jump to function) - // push - - // bt algorithm - // set a7 = a6 - // pop a7 -> a6 - // pop a7 -> return pointer - - - uint32_t i, j, a7, a6 = shoe.a[6]; - coff_symbol *symb; - - if (sr_s()) { - symb = coff_find_func(shoe.coff, shoe.pc); - printf("%u: *0x%08x %s+%u\n", 0, shoe.pc, (symb && strlen(symb->name))?symb->name:"?", shoe.pc - symb->value); - } - else - printf("%u: *0x%08x\n", 0, shoe.pc); - - for (i=1; 1; i++) { - a7 = a6; - const uint32_t last_a6 = lget(a7, 4); - const uint32_t last_pc = lget(a7+4, 4); - - if ((last_a6 - a6) <= 1000) { - printf(" {"); - for (j = a6+8; j < last_a6; j+=4) { - uint32_t data = lget(j, 4); - printf("%x, ", data); - } - printf("}\n"); - } - - if (sr_s()) { - symb = coff_find_func(shoe.coff, last_pc); - printf("%u: *0x%08x %s+%u\n", i, last_pc, (symb && strlen(symb->name))?symb->name:"?", last_pc - symb->value); - } - else - printf("%u: *0x%08x\n", i, last_pc); - - if ((last_a6 - a6) > 1000) { - break; - } - - a6 = last_a6; - } - - shoe.suppress_exceptions = 0; - shoe.abort = old_abort; -} - -void verb_break_handler (const char *line) -{ - errno = 0; - const uint32_t addr = (uint32_t) strtoul(line, NULL, 0); - - if (errno) { - printf("errno: %d\n", errno); - return ; - } - - dbg_breakpoint_t *brk = calloc(sizeof(dbg_breakpoint_t), 1); - brk->next = NULL; - brk->addr = addr; - brk->num = dbg_state.breakpoint_counter++; - - dbg_breakpoint_t **cur = &dbg_state.breakpoints; - while (*cur) - cur = &(*cur)->next; - *cur = brk; - - printf("Set breakpoint %llu = *0x%08x\n", brk->num, brk->addr); -} - -void verb_delete_handler (const char *line) -{ - errno = 0; - uint64_t num = strtoull(line, NULL, 0); - - if (errno) { - printf("errno: %d\n", errno); - return ; - } - - dbg_breakpoint_t **cur = &dbg_state.breakpoints; - while (*cur) { - if ((*cur)->num == num) { - dbg_breakpoint_t *victim = *cur; - *cur = (*cur)->next; - free(victim); - return ; - } - cur = &(*cur)->next; - } - - printf("No such breakpoint (#%llu)\n", num); -} - -void verb_help_handler (const char *line) -{ - printf("Help help help\n"); -} - -void verb_quit_handler (const char *line) -{ - printf("Quitting\n"); - fflush(stdout); - exit(0); -} - -void verb_continue_handler (const char *line) -{ - dbg_state.running = 1; - while (dbg_state.running) { - stepper(); - } - print_pc(); -} - -void verb_stepi_handler (const char *line) -{ - shoe.stopped = 0; - dbg_state.running = 1; - cpu_step(); - dbg_state.running = 0; - print_pc(); -} - -void verb_registers_handler (const char *line) -{ - printregs(); -} - -void verb_trace_toggle_handler (const char *line) -{ - shoe.dbg = !shoe.dbg; -} - -void verb_examine_handler (const char *line) -{ - uint32_t addr = (uint32_t)strtoul(line, NULL, 0); - uint32_t old_suppress = shoe.suppress_exceptions; - - shoe.suppress_exceptions = 1; - printf("(uint32_t)*0x%08x = 0x%08x\n", addr, (uint32_t)lget(addr, 4)); - shoe.suppress_exceptions = old_suppress; - -} - -void verb_lookup_handler (const char *line) -{ - char *sym_name = malloc(strlen(line)+1); - - sscanf(line, "%s", sym_name); - coff_symbol *symb = coff_find_symbol(shoe.coff, sym_name); - - free(sym_name); - - if (symb == NULL) { - printf("Couldn't find \"%s\"\n", sym_name); - return ; - } - - printf("%s = *0x%08x\n", symb->name, symb->value); -} - -struct verb_handler_table_t { - const char *name; - void (*func)(const char *); -} verb_handler_table[] = -{ - {"quit", verb_quit_handler}, - {"help", verb_help_handler}, - {"registers", verb_registers_handler}, - {"continue", verb_continue_handler}, - {"stepi", verb_stepi_handler}, - {"backtrace", verb_backtrace_handler}, - {"bt", verb_backtrace_handler}, - {"break", verb_break_handler}, - {"delete", verb_delete_handler}, - {"lookup", verb_lookup_handler}, - {"trace", verb_trace_toggle_handler}, - {"x", verb_examine_handler} -}; - -void execute_verb (const char *line) -{ - char verb[128]; - uint32_t max_len=0, max_i=0; - const char *remainder; - uint32_t i, matches = 0, match_i; - - if (sscanf(line, "%127s", verb) != 1) - return ; - - // Skip past the verb - for (remainder = line; *remainder && !isspace(*remainder); remainder++) ; - - // Skip past the space between the verb and the arguments - for (; *remainder && isspace(*remainder); remainder++) ; - - const uint32_t verb_len = strlen(verb); - for (i=0; i < (sizeof(verb_handler_table) / sizeof(struct verb_handler_table_t)); i++) { - const uint32_t i_len = strlen(verb_handler_table[i].name); - - // If it's a perfect match, - if (strcasecmp(verb, verb_handler_table[i].name)==0) { - verb_handler_table[i].func(remainder); - return ; - } - - // Otherwise, see if it's a partial match - if ((i_len >= verb_len) && strncasecmp(verb, verb_handler_table[i].name, verb_len)==0) { - matches++; - match_i = i; - } - } - - // Only execute the verb if it's an unambiguous match (matches == 1) - if (matches == 1) { - verb_handler_table[match_i].func(remainder); - return ; - } - - printf(" %s?\n", verb); -} - -void *ui_thread (void *arg) -{ - EditLine *el; - History *hist; - HistEvent histev; - - const char *buf; - int num; - - hist = history_init(); - history(hist, &histev, H_SETSIZE, 10000); // Remember 10000 previous user inputs - - el = el_init("Shoebill", stdin, stdout, stderr); - dbg_state.el = el; - - el_set(el, EL_SIGNAL, 0); - el_set(el, EL_PROMPT, cli_prompt_callback); - el_set(el, EL_EDITOR, "emacs"); - el_set(el, EL_HIST, history, hist); - - (void) signal(SIGINT, signal_callback); - (void) signal(SIGWINCH, signal_callback); - - while ((buf = el_gets(el, &num)) != NULL) { - if (strcmp(buf, "\n")!=0) { - execute_verb(buf); - history(hist, &histev, H_ENTER, buf); - } - } - - el_end(el); - history_end(hist); - return NULL; -} - -uint8_t *loadrom (char *path, uint32_t *len) -{ - FILE *f = fopen(path, "r"); - uint8_t *buf = calloc(1024, 1024); - uint32_t i, sz, expected, checksum; - - if (!f) { - printf("Couldn't open %s\n", path); - return NULL; - } - - for (sz=0; sz < (1024*1024); sz += (64*1024)) { - printf("sz = %u\n", sz); - if (fread(buf + sz, 64*1024, 1, f) != 1) { - break; - } - } - printf("sz = %u (done)\n", sz); - - fclose(f); - - if (sz == 0) { - printf("loadrom: empty rom file\n"); - free(buf); - return NULL; - } - - for (i=0, expected=0; i<4; i++) - expected = (expected << 8) + buf[i]; - - for (i=4, checksum=0; i < sz; i+=2) { - uint16_t word = (buf[i]<<8) + buf[i+1]; - checksum += word; - } - - if (checksum != expected) { - printf("Bad checksum (computed %08x, expected %08x)\n", checksum, expected); - free(buf); - return NULL; - } - - *len = sz; - return buf; -} - -struct __attribute__ ((__packed__)) kernel_info { - // Auto data - uint32_t auto_magic; - uint32_t auto_id[16]; - uint32_t auto_version[16]; - uint32_t auto_command; - - uint16_t root_ctrl; - uint8_t root_drive; - uint8_t root_cluster; - - struct __attribute__ ((__packed__)) sect_info { - uint32_t vstart; - uint32_t pstart; - uint32_t size; - } si[3]; - - uint16_t machine_type; // Gestalt, I think? The "machine_type" for a quadra 950 doesn't match its gestalt, though. - uint32_t drive_queue_offset; - uint16_t ki_flags; - uint8_t ki_version; // always 1 - uint8_t root_partition; - uint16_t swap_ctrl; - uint8_t swap_drive; - uint8_t swap_partition; -}; - -void init_kernel_info() -{ - struct kernel_info ki, *p; - uint32_t i; - - p = (struct kernel_info*)0x00003c00; - - shoe.d[0] = 0x536d7201; - shoe.a[0] = (uint32_t)p; - - /* ----- Setup kernel info structure ----- */ - - ki.auto_magic = 0x50696773; // 'Pigs' (Pigs in space?) - - for (i=0; i<16; i++) { - ki.auto_id[i] = 0x0000ffff; - ki.auto_version[i] = 0; - } - - ki.auto_id[0xa] = 0x50; // Macintosh II video card has an auto_id of 5 (I guess?) - ki.auto_id[0xb] = 0x5; // Macintosh II video card has an auto_id of 5 (I guess?) - - ki.auto_command = 0; // AUTO_RUN - - ki.root_ctrl = 0; - ki.root_drive = 0; - ki.root_cluster = 0; - - for (i = 0; i < shoe.coff->num_sections; i++) { - coff_section *s = &shoe.coff->sections[i]; - uint8_t sect; - - if (strcmp(s->name, ".text") == 0) - sect = 0; - else if (strcmp(s->name, ".data") == 0) - sect = 1; - else if (strcmp(s->name, ".bss") == 0) - sect = 2; - else - continue; - - ki.si[sect].vstart = s->v_addr; - ki.si[sect].pstart = s->p_addr; - ki.si[sect].size = s->sz; - } - - ki.machine_type = 4; // Macintosh II? - - // +4 because the DrvQEl structure has a hidden "flags" field 4 bytes below the pointer - ki.drive_queue_offset = sizeof(struct kernel_info) + 4; - - ki.ki_flags = 1; // KI_VERBOSE - ki.ki_version = 1; - ki.root_partition = 0; - ki.swap_ctrl = 0; - ki.swap_drive = 0; - ki.swap_partition = 1; - - /* ----- Copy ki into memory ----- */ -#define ki_pset(_f, _s) {pset((uint32_t)&p->_f, _s, ki._f); printf("Setting 0x%08x to %x\n", (uint32_t)&p->_f, ki._f);} - ki_pset(auto_magic, 4); - for (i=0; i<16; i++) { - ki_pset(auto_id[i], 4); - ki_pset(auto_version[i], 4); - } - ki_pset(auto_command, 4); - - ki_pset(root_ctrl, 2); - ki_pset(root_drive, 1); - ki_pset(root_cluster, 1); - - for (i=0; i<3; i++) { - ki_pset(si[i].vstart, 4); - ki_pset(si[i].pstart, 4); - ki_pset(si[i].size, 4); - } - - ki_pset(machine_type, 2); - ki_pset(drive_queue_offset, 4); - ki_pset(ki_flags, 2); - ki_pset(ki_version, 1); - ki_pset(root_partition, 1); - ki_pset(swap_ctrl, 2); - ki_pset(swap_drive, 1); - ki_pset(swap_partition, 1); - - // Fake drive queue - /*uint8_t dummy[0x14*2] = { - // 00 08 01 00 00 00 00 14 00 01 00 08 FF D9 00 00 CE AD 00 2C - 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0x08, 0xFF, 0xD9, 0x00, 0x00, 0x0f, 0x71, 0x00, 0x01, - 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0xFF, 0xDF, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00 - };*/ - - uint8_t dummy[0x14*2] = { - // 00 08 01 00 00 00 00 14 00 01 00 08 FF D9 00 00 CE AD 00 2C - 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0x08, 0xFF, 0xD9, 0x00, 0x00, 0, 0, 0, 0, - 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0xFF, 0xDF, 0x00, 0x00, 0, 0, 0, 0 - }; - - for (i=0; i<(0x14*2); i++) - pset(((uint32_t)p) + sizeof(struct kernel_info) + i, 1, dummy[i]); - - // FIXME: *really* implement drive queue -} - -void init_macintosh_globals() -{ - uint8_t buf[0x1000]; - - memset(buf, 0xBB, 0x1000); - - uint32_t i; - for (i=0; i<0x1000; i++) - pset(i, 1, buf[i]); - - - #define hwCbSCSI (1<<15) - #define hwCbClock (1<<14) - #define hwCbExPRAM (1<<13) - #define hwCbFPU (1<<12) - #define hwCbMMU (1<<11) - #define hwCbADB (1<<10) - #define hwCbAUX (1<<9) - // uint16_t HWCfgFlags = hwCbSCSI | hwCbClock | hwCbFPU | hwCbMMU | hwCbADB | hwCbAUX; - - uint16_t HWCfgFlags = hwCbSCSI | hwCbClock | hwCbFPU | hwCbMMU | hwCbADB; - - pset(0xb22, 2, HWCfgFlags); // HWCfgFlags - - pset(0x12f, 1, 0x02); // CPUFlag = 0x02 (MC68020) - pset(0x31a, 4, 0x00ffffff); // Lo3Bytes (always 0x00ffffff) - - pset(0x28e, 2, 0x3fff); // ROM85 (always 0x3fff, I think?) - - - pset(0xdd8, 4, 0); // universal info ptr. is allowed to be null on Mac II, (I THINK) - pset(0x1d4, 4, 0x50000000); // VIA (via1 ptr) - pset(0x1d8, 4, 0x50004000); // SCC - - /*pset(0x8ce, 1, 1); // CrsrNew (set to 1?) - pset(0x8cd, 1, 0); // CrsrBusy (0 -> Not presently busy) - pset(0x8d0, 2, 0); // CrsrState - pset(0x8cf, 1, 0xff); // CrsrCouple ?? - pset(0x8d6, 4, 0xffffffff); // MouseMask - pset(0x8da, 4, 0); // MouseOffset - pset(0x8d3, 1, 6); // CrsrScale - */ - - // 21e -> KbdType - // dd8 -> UnivInfoPtr - // d00 -> TimeDBRA - // d02 -> TimeSCCDB - // FIXME: add 0x21e, 0xdd8, 0x28e, 0xd00, 0xd02 - - // Do this after setting lomem mac stuff, because this structure is more important. - init_kernel_info(); -} - -uint32_t init_state (coff_file *coff, uint8_t *rom, uint32_t romsize) -{ - uint32_t i, j, pc = 0xffffffff; - - fpu_setup_jump_table(); - - shoe.coff = coff; - shoe.launch = coff_parser("priv/launch"); - - shoe.physical_mem_size = 32 * 1024 * 1024; - shoe.physical_rom_size = romsize; - - shoe.physical_mem_base = valloc(shoe.physical_mem_size); - shoe.physical_rom_base = valloc(romsize); - - memset(shoe.physical_mem_base, 0, shoe.physical_mem_size); - memcpy(shoe.physical_rom_base, rom, romsize); - - for (i=0; i<16; i++) { - shoe.slots[i].slotnum = i; - shoe.slots[i].connected = 0; - shoe.slots[i].glut_window_id = -1; - } - - // Install TFB at slot B - /*{ - shoe.slots[0xb].connected = 1; - shoe.slots[0xb].read_func = nubus_tfb_read_func; - shoe.slots[0xb].write_func = nubus_tfb_write_func; - nubus_tfb_init(0xb); - }*/ - - { - shoe.slots[0xa].connected = 1; - shoe.slots[0xa].read_func = nubus_video_read_func; - shoe.slots[0xa].write_func = nubus_video_write_func; - // nubus_video_init(0xa, 1440, 900); - nubus_video_init(0xa, 800, 600); - } - - - // Initialize relevant Mac globals - // (Do this before copying COFF segments, in case they overwrite these globals) - init_macintosh_globals(); - - /* Copy COFF segments into memory */ - for (i = 0; i < coff->num_sections; i++) { - coff_section *s = &coff->sections[i]; - - // Don't load a "copy" segment - if (s->flags & coff_copy) - continue; - - if ((s->flags & coff_text) || (s->flags & coff_data)) { - /* copy text or data section */ - - for (j = 0; j < s->sz; j++) - pset(s->p_addr+j, 1, s->data[j]); - - if (strcmp(s->name, "pstart") == 0) - pc = s->p_addr; - } - else if (s->flags & coff_bss) { - /* Create an empty .bss segment */ - - for (j = 0; j < s->sz; j++) - pset(s->p_addr+j, 1, 0); - } - } - - if (pc == 0xffffffff) { - printf("init_state: this unix doesn't contain a pstart segment\n"); - return 0; - } - - set_sr(0x2000); - shoe.pc = pc; - - // Start the VIA clocks - gettimeofday(&shoe.start_time, NULL); - shoe.total_ticks = 0; - - // Put the adb chip in state 3 (idle) - shoe.adb.state = 3; - pthread_mutex_init(&shoe.adb.lock, NULL); - - for (i=0; i<8; i++) { - shoe.scsi_devices[i].scsi_id = i; - shoe.scsi_devices[i].block_size = 0; - shoe.scsi_devices[i].num_blocks = 0; - shoe.scsi_devices[i].image_path = "dummy"; - shoe.scsi_devices[i].f = NULL; - } - - // Hacky load scsi disk at id 0 - - /*shoe.scsi_devices[0].scsi_id = 0; - shoe.scsi_devices[0].block_size = 512; - shoe.scsi_devices[0].num_blocks = 656544; - shoe.scsi_devices[0].image_path = "priv/Apple_UNIX_3.iso"; - shoe.scsi_devices[0].f = fopen(shoe.scsi_devices[0].image_path, "r+"); - assert(shoe.scsi_devices[0].f);*/ - - shoe.scsi_devices[0].scsi_id = 0; - shoe.scsi_devices[0].block_size = 512; - shoe.scsi_devices[0].num_blocks = 195912; //205561; - shoe.scsi_devices[0].image_path = "priv/aux2.img"; - shoe.scsi_devices[0].f = fopen(shoe.scsi_devices[0].image_path, "r+"); - assert(shoe.scsi_devices[0].f); - - shoe.scsi_devices[1].scsi_id = 1; - shoe.scsi_devices[1].block_size = 512; - shoe.scsi_devices[1].num_blocks = 1048576; - shoe.scsi_devices[1].image_path = "priv/blank.img"; - shoe.scsi_devices[1].f = fopen(shoe.scsi_devices[1].image_path, "r+"); - assert(shoe.scsi_devices[1].f); - - /*shoe.scsi_devices[6].scsi_id = 6; - shoe.scsi_devices[6].block_size = 512; - shoe.scsi_devices[6].num_blocks = 1280032; //205561; - shoe.scsi_devices[6].image_path = "priv/macii_fs.img"; - shoe.scsi_devices[6].f = fopen(shoe.scsi_devices[6].image_path, "r+"); - assert(shoe.scsi_devices[6].f);*/ - - /* In the future, we'll need to setup that booter struct for A/UX. */ - - // HACK HACK HACK - // Not sure why, but it seems that on non-RBV systems, A/UX version >= 1.1.1 does memcpy(0x0, 0x50000, 0x4000), blowing away all the lomem stuff - // So copy lomem stuff to 0x50000 - - for (i=0; i<0x4000; i++) { - uint8_t c = pget(i, 1); - pset(0x50000 + i, 1, c); - } - - shoe.a[0] += 0x50000; // A/UX thinks kernel_info should live at 0x50000 + (normal kernel_info addr). - - return 1; -} - - -#define KEY_SHIFT 1 - -const struct { - uint8_t code; - char c; - uint8_t modifiers; -} key_codes[] = { - {0x0, 'A', 0}, - {0x1, 'S', 0}, - {2, 'D', 0}, - {3, 'F', 0}, - {4, 'H', 0}, - {5, 'G', 0}, - {6, 'Z', 0}, - {7, 'X', 0}, - {8, 'C', 0}, - {9, 'V', 0}, - // {0xa ?? - {0xb, 'B', 0}, - {0xc, 'Q', 0}, - {0xd, 'W', 0}, - {0xe, 'E', 0}, - {0xf, 'R', 0}, - {0x10, 'Y', 0}, - {0x11, 'T', 0}, - - {0x12, '1', 0}, - {0x12, '!', KEY_SHIFT}, - - - {0x13, '2', 0}, - {0x13, '@', KEY_SHIFT}, - - {0x14, '3', 0}, - {0x14, '#', KEY_SHIFT}, - - {0x15, '4', 0}, - {0x15, '$', KEY_SHIFT}, - - {0x16, '6', 0}, - {0x16, '^', KEY_SHIFT}, - - {0x17, '5', 0}, - {0x17, '%', KEY_SHIFT}, - - {0x18, '=', 0}, - {0x18, '+', KEY_SHIFT}, - - {0x19, '9', 0}, - {0x19, '(', KEY_SHIFT}, - - {0x1a, '7', 0}, - {0x1a, '&', KEY_SHIFT}, - - {0x1b, '-', 0}, - {0x1b, '_', KEY_SHIFT}, - - {0x1c, '8', 0}, - {0x1c, '*', KEY_SHIFT}, - - {0x1d, '0', 0}, - {0x1d, ')', KEY_SHIFT}, - - {0x1e, ']', 0}, - {0x1e, '}', KEY_SHIFT}, - - {0x1f, 'O', 0}, - {0x20, 'U', 0}, - - {0x21, '[', 0}, - {0x21, '{', KEY_SHIFT}, - - {0x22, 'I', 0}, - {0x23, 'P', 0}, - - {0x24, '\n', 0}, - {0x24, '\r', 0}, - - {0x25, 'L', 0}, - {0x26, 'J', 0}, - - {0x27, '"', KEY_SHIFT}, - {0x27, '\'', 0}, - - {0x28, 'K', 0}, - - {0x29, ';', 0}, - {0x29, ':', KEY_SHIFT}, - - {0x2a, '\\', 0}, - {0x2a, '|', KEY_SHIFT}, - - {0x2b, ',', 0}, - {0x2b, '<', KEY_SHIFT}, - - {0x2c, '/', 0}, - {0x2c, '?', 0}, - - {0x2d, 'N', 0}, - {0x2e, 'M', 0}, - - {0x2f, '.', 0}, - {0x2f, '>', KEY_SHIFT}, - - {0x30, '\t', 0}, - {0x31, ' ', 0}, - - {0x32, '`', 0}, - {0x32, '~', KEY_SHIFT}, - - {0x33, '\b', 0}, - {0x33, 0x7f, 0}, - // {0x34, ?? - // {0x35 // escape char - // 0x36 // ctrl - // 0x37 // command - // 0x38 // shift - // 0x39 // caps lock - // 0x3a // option - // 0x3b // left arrow - // 0x3c // right arrow - // 0x3d // down arrow - // 0x3e // up arrow - - {0, 0, 0}, -}; - -static uint8_t lookup_key(char c) -{ - uint32_t i; - uint8_t upper=toupper(c); - - for (i=0; key_codes[i].c; i++) { - if (key_codes[i].c == upper) - return key_codes[i].code; - - } - - return 0xff; -} - -static uint8_t lookup_special(int special) -{ - switch (special) { - case GLUT_KEY_UP: return 0x3e; - case GLUT_KEY_DOWN: return 0x3d; - case GLUT_KEY_LEFT: return 0x3b; - case GLUT_KEY_RIGHT: return 0x3c; - default: return 0xff; - } -} - -static void keyboard_add_entry(uint8_t code, uint8_t up) -{ - uint8_t up_mask = up ? 0x80 : 0; - uint32_t i; - int modifiers = glutGetModifiers(); - - assert(pthread_mutex_lock(&shoe.adb.lock) == 0); - - if ((shoe.key.key_i+1) < KEYBOARD_STATE_MAX_KEYS) { - if (modifiers & GLUT_ACTIVE_SHIFT) { - shoe.key.keys[shoe.key.key_i].code_a = 0x38; - shoe.key.keys[shoe.key.key_i].code_b = 0xff; - shoe.key.key_i++; - } - else if (shoe.key.down_modifiers & GLUT_ACTIVE_SHIFT) { - shoe.key.keys[shoe.key.key_i].code_a = 0x80 | 0x38; - shoe.key.keys[shoe.key.key_i].code_b = 0xff; - shoe.key.key_i++; - } - shoe.key.keys[shoe.key.key_i].code_a = code | up_mask; - shoe.key.keys[shoe.key.key_i].code_b = 0xff; - shoe.key.key_i++; - } - - shoe.key.down_modifiers = modifiers; - - adb_request_service_request(2); - - pthread_mutex_unlock(&shoe.adb.lock); -} - -void global_mouse_func (int button, int state, int x, int y) -{ - //if (button != GLUT_LEFT_BUTTON) - // return ; - - assert(pthread_mutex_lock(&shoe.adb.lock) == 0); - - shoe.mouse.button_down = (state == GLUT_DOWN); - shoe.mouse.changed = 1; - - adb_request_service_request(3); - - pthread_mutex_unlock(&shoe.adb.lock); - - // printf("mouse_func: setting service request\n"); -} - -static void move_mouse (int x, int y, uint8_t button_down) -{ - printf("%s: lock\n", __func__); fflush(stdout); - assert(pthread_mutex_lock(&shoe.adb.lock) == 0); - - int32_t delta_x = x - shoe.mouse.old_x; - int32_t delta_y = y - shoe.mouse.old_y; - - shoe.mouse.old_x = x; - shoe.mouse.old_y = y; - - shoe.mouse.delta_x += delta_x; - shoe.mouse.delta_y += delta_y; - shoe.mouse.button_down = button_down; - shoe.mouse.changed = 1; - - adb_request_service_request(3); - printf("%s: unlock\n", __func__); fflush(stdout); - pthread_mutex_unlock(&shoe.adb.lock); - - // printf("move_mouse: setting service request\n"); -} - -void global_motion_func (int x, int y) -{ - move_mouse(x, y, 1); -} - -void global_passive_motion_func (int x, int y) -{ - move_mouse(x, y, 0); -} - -void global_keyboard_up_func (unsigned char c, int x, int y) -{ - uint8_t code = lookup_key(c); - if (code != 0xff) - keyboard_add_entry(code, 1); -} - -void global_keyboard_down_func (unsigned char c, int x, int y) -{ - uint8_t code = lookup_key(c); - if (code != 0xff) - keyboard_add_entry(code, 0); -} - -void global_special_up_func (int special, int x, int y) -{ - const uint8_t code = lookup_special(special); - if (code != 0xff) - keyboard_add_entry(code, 1); -} - -void global_special_down_func (int special, int x, int y) -{ - const uint8_t code = lookup_special(special); - if (code != 0xff) - keyboard_add_entry(code, 0); -} - -void timer_func (int arg) -{ - glutTimerFunc(15, timer_func, 0); // 66.67hz is the usual refresh interval (right?) - - uint32_t slotnum; - for (slotnum = 0; slotnum < 16; slotnum++) { - if (shoe.slots[slotnum].glut_window_id == -1) - continue; - - glutSetWindow(shoe.slots[slotnum].glut_window_id); - glutPostRedisplay(); - } -} - -//void _macii_load_video_rom(const char *path); -int main (int argc, char **argv) -{ - coff_file *coff; - uint32_t romsize; - uint8_t *rom; - pthread_t pid; - - //_macii_load_video_rom("tfb_rom"); - - rom = loadrom("priv/macii.rom", &romsize); - if (rom == NULL) - return 0; - //printf(") - - /*if (romsize != (256 * 1024)) { - printf("Bogus rom size (%u bytes)\n", romsize); - return 0; - }*/ - - coff = coff_parser("priv/unix"); - if (coff == NULL) { - printf("main: coff_parser() failed to load \"unix\"\n"); - return 0; - } - - int dummyargc = 1; - glutInit(&dummyargc, argv); - - if (!init_state(coff, rom, romsize)) - return 0; - free(rom); - - pthread_create(&pid, NULL, ui_thread, NULL); - - glutTimerFunc(15, timer_func, 0); - glutMainLoop(); - while (1) sleep(1); - return 0; -} - diff --git a/core/redblack.c b/core/redblack.c index 059da52..dc8ef32 100644 --- a/core/redblack.c +++ b/core/redblack.c @@ -33,7 +33,7 @@ // (just return an empty black leaf pointer) rb_tree* rb_new() { - return calloc(sizeof(rb_tree), 1); + return p_alloc(shoe.pool, sizeof(rb_tree)); } // Insert a new key/value into the tree @@ -43,7 +43,7 @@ uint8_t rb_insert(rb_tree *root, rb_key_t key, rb_value_t value, rb_value_t *old { // Special edge case: insert the root node if tree's empty if (*root == NULL) { - *root = calloc(sizeof(rb_node), 1); + *root = p_alloc(shoe.pool, sizeof(rb_node)); (*root)->key = key; (*root)->value = value; return 0; @@ -66,7 +66,7 @@ uint8_t rb_insert(rb_tree *root, rb_key_t key, rb_value_t value, rb_value_t *old } // insert - *cur = calloc(sizeof(rb_node), 1); + *cur = p_alloc(shoe.pool, sizeof(rb_node)); (*cur)->parent = parent; (*cur)->key = key; (*cur)->value = value; @@ -252,16 +252,16 @@ void _rb_free (rb_node *node) { if (!node) return ; _rb_free(node->right); - if (node->right) free(node->right); + if (node->right) p_free(node->right); _rb_free(node->left); - if (node->left) free(node->left); + if (node->left) p_free(node->left); } // Free all the nodes (and the rb_tree ptr itself) void rb_free (rb_tree *tree) { _rb_free(*tree); - free(*tree); - free(tree); + p_free(*tree); + p_free(tree); } diff --git a/core/shoebill.h b/core/shoebill.h index 9243c49..d6c1990 100644 --- a/core/shoebill.h +++ b/core/shoebill.h @@ -100,7 +100,7 @@ // set the status register, swapping a7 if necessary #define set_sr(newsr) { \ make_stack_pointers_valid(); \ - shoe.sr = newsr & 0xf71f; \ + shoe.sr = (newsr) & 0xf71f; \ load_stack_pointer(); \ } @@ -196,9 +196,27 @@ typedef struct { } adb_state_t; typedef struct { - uint8_t ifr, ier, rega, regb, ddrb, ddra, sr; + uint8_t ifr, ier, ddrb, ddra, sr, acr, pcr; + // uint8_t rega, regb; + uint16_t t1c, t2c, t1l; + uint8_t rega_input, regb_input; + uint8_t rega_output, regb_output; + long double t1_last_set, t2_last_set; } via_state_t; +#define PRAM_READ 1 +#define PRAM_WRITE 2 +typedef struct { + uint8_t data[256]; + uint8_t last_bits; + + // FSM + uint8_t command[8]; + uint8_t byte, mode, command_i, bit_i; +} pram_state_t; + +void init_via_state(); + typedef struct { uint8_t scsi_id; uint32_t num_blocks, block_size; @@ -254,7 +272,6 @@ typedef struct { void (*write_func)(uint32_t, uint32_t, uint32_t, uint8_t); void *ctx; uint8_t slotnum, connected, interrupts_enabled; - int32_t glut_window_id; long double interrupt_rate, last_fired; } nubus_card_t; @@ -276,7 +293,7 @@ typedef struct { typedef struct { -#define SHOEBILL_STATE_STOPPED (1<<9) +#define SHOEBILL_STATE_STOPPED (1<<8) // bits 0-6 are CPU interrupt priorities // bit 8 indicates that STOP was called @@ -286,14 +303,6 @@ typedef struct { pthread_mutex_t via_clock_thread_lock; pthread_mutex_t cpu_freeze_lock; - // -- PMMU caching structures --- -#define PMMU_CACHE_KEY_BITS 10 -#define PMMU_CACHE_SIZE (1< no pending interrupt, >0 -> interrupt priority (autovector)) - via_state_t via[2]; - adb_state_t adb; - keyboard_state_t key; - mouse_state_t mouse; - iwm_state_t iwm; - - nubus_card_t slots[16]; - // video_state_t video; + // -- EA state -- + uint32_t uncommitted_ea_read_pc; // set by ea_read(). It's the PC that ea_read_commit will set. + uint64_t dat; // the raw input/output for the transaction + uint32_t extended_addr; // EA returned by ea_decode_extended() + uint32_t extended_len; // number of instruction bytes used by ea_decode_extended() + uint8_t sz; // the size of the EA transaction + uint8_t mr; // a 6-bit mode/reg pair // -- Registers -- uint32_t d[8]; @@ -430,27 +442,27 @@ typedef struct { long double fp[8]; // 80 bit floating point general registers + // -- Interrupts/VIA chips -- - // -- EA state -- - uint32_t uncommitted_ea_read_pc; // set by ea_read(). It's the PC that ea_read_commit will set. - uint64_t dat; // the raw input/output for the transaction - uint32_t extended_addr; // EA returned by ea_decode_extended() - uint32_t extended_len; // number of instruction bytes used by ea_decode_extended() - uint8_t sz; // the size of the EA transaction - uint8_t mr; // a 6-bit mode/reg pair + via_state_t via[2]; + adb_state_t adb; + keyboard_state_t key; + mouse_state_t mouse; + iwm_state_t iwm; + + nubus_card_t slots[16]; via_clock_t via_clocks; - struct timeval start_time; // when the emulator started (for computing timer interrupts) uint64_t total_ticks; // how many 60hz ticks have been generated coff_file *coff; // Data/symbols from the unix kernel - coff_file *launch; // FIXME: delete me: coff symbols from aux 1.1.1 launch binary - scsi_device_t scsi_devices[8]; // SCSI devices + pram_state_t pram; + debugger_state_t dbg; alloc_pool_t *pool; } global_shoebill_context_t; @@ -520,11 +532,17 @@ void logical_set (void); lset_fc((addr), (s), (val), sr_s() ? 5 : 1) \ } +typedef void (*_ea_func) (void); +extern const _ea_func ea_read_jump_table[64]; +extern const _ea_func ea_read_commit_jump_table[64]; +extern const _ea_func ea_write_jump_table[64]; +extern const _ea_func ea_addr_jump_table[64]; + +#define ea_read() ea_read_jump_table[shoe.mr]() +#define ea_read_commit() ea_read_commit_jump_table[shoe.mr]() +#define ea_write() ea_write_jump_table[shoe.mr]() +#define ea_addr() ea_addr_jump_table[shoe.mr]() -void ea_read(); -void ea_read_commit(); -void ea_write(); -void ea_addr(); #define call_ea_read(M, s) {shoe.mr=(M);shoe.sz=(s);ea_read();if (shoe.abort) return;} #define call_ea_write(M, s) {shoe.mr=(M);shoe.sz=(s);ea_write();if (shoe.abort) return;} @@ -549,9 +567,6 @@ void ea_addr(); desc_addr = (_addr); \ desc_level++; \ } -// if (shoe.dbg) \ -// printf("desc_addr *0x%08x = 0x%llx\n", (uint32_t)(_addr), desc); \ -// } // dis.c functions @@ -589,11 +604,10 @@ void scsi_dma_write(uint8_t byte); void scsi_dma_write_long(uint32_t dat); // via1 & via2 (+ CPU interrupts) -void check_time(); void via_raise_interrupt(uint8_t vianum, uint8_t ifr_bit); void process_pending_interrupt(); -void via_reg_read(); -void via_reg_write(); +void via_read_raw(); +void via_write_raw(); void *via_clock_thread(void *arg); // VIA registers diff --git a/core/via.c b/core/via.c index e8cd979..d450eab 100644 --- a/core/via.c +++ b/core/via.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "../core/shoebill.h" char *via_reg_str[16] = { @@ -66,8 +67,8 @@ void via_raise_interrupt(uint8_t vianum, uint8_t ifr_bit) // Only if the bit is enabled in IER do we raise a cpu interrupt if (via->ier & (1 << ifr_bit)) set_pending_interrupt(vianum); - else - printf("didn't set pending interrupt\n"); + //else + // printf("didn't set pending interrupt\n"); } @@ -184,6 +185,7 @@ void process_pending_interrupt () #define VIA_REGB_DONE 8 + // VIA registers #define VIA_ORB 0 #define VIA_ORA 1 @@ -202,75 +204,413 @@ void process_pending_interrupt () #define VIA_IER 14 #define VIA_ORA_AUX 15 -uint16_t counter; +// Interrupt flag register bits +#define VIA_IFR_CA2 (1<<0) +#define VIA_IFR_CA1 (1<<1) +#define VIA_IFR_SHIFT_REG (1<<2) +#define VIA_IFR_CB2 (1<<3) +#define VIA_IFR_CB1 (1<<4) +#define VIA_IFR_T2 (1<<5) +#define VIA_IFR_T1 (1<<6) +#define VIA_IFR_IRQ (1<<7) -void via_reg_read () +static long double _now (void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + long double secs = tv.tv_sec; + long double usecs = tv.tv_usec; + + return secs + (usecs / 1000000.0); +} + +static void handle_pram_write_byte (void) +{ + pram_state_t *pram = &shoe.pram; + + printf("PRAMPRAM: wrote_byte 0x%02x\n", pram->byte); + + pram->mode = PRAM_READ; + pram->byte = 0; +} + +static void handle_pram_read_byte (void) +{ + pram_state_t *pram = &shoe.pram; + + assert(pram->command_i < 8); + pram->command[pram->command_i++] = pram->byte; + + printf("PRAMPRAM: read_byte: 0x%02x\n", pram->byte); + + // If this is a pram-read/write... + if ((pram->command[0] & 0x78) == 0x38) { + const _Bool isget = pram->command[0] >> 7; + const uint8_t addr = (pram->command[0] << 5) | ((pram->command[1] >> 2) & 0x1f); + + if ((pram->command_i == 3) && !isget) { // complete set command + pram->mode = PRAM_READ; // stay in read-mode + pram->data[addr] = pram->command[2]; + + FILE *f = fopen("pram.dump", "w"); + if (f) { + fwrite(pram->data, 256, 1, f); + fclose(f); + } + + printf("PRAMPRAM: setting pram addr 0x%02x = 0x%02x\n", addr, pram->command[2]); + + pram->byte = 0; + pram->command_i = 0; + + return ; + } + else if ((pram->command_i == 2) && isget) { // complete get command + pram->mode = PRAM_WRITE; // switch to write-mode + pram->byte = pram->data[addr]; + pram->command_i = 0; + + printf("PRAMPRAM: fetching pram addr 0x%02x (= 0x%02x)\n", addr, pram->byte); + + return ; + } + else { // incomplete command, keep reading + assert(pram->command_i < 4); + pram->mode = PRAM_READ; // keep reading + + return ; + } + } + + // if this is clock-read/write + else if (~bmatch(pram->command[0], x 00x xx 01)) { + const _Bool isget = pram->command[0] >> 7; + const uint8_t addr = (pram->command[0] >> 2) & 3; + const _Bool mysterybit = (pram->command[0] >> 4) & 1; // FIXME: What does this do? + + if ((pram->command_i == 2) && !isget) { // complete set command + pram->mode = PRAM_READ; // stay in read-mode + + printf("PRAMPRAM: setting time byte %u to 0x%02x (mysterybit=%u)\n", addr, pram->command[1], mysterybit); + + pram->byte = 0; + pram->command_i = 0; + return ; + } + else if ((pram->command_i == 1) && isget) { // complete get command + const uint32_t now = time(NULL) + 0x7c25b080; + //uint32_t now = 0xafd56d80; // Tue, 24 Jun 1997 12:26:40 GMT + const uint8_t now_byte = now >> (8*addr); + + pram->mode = PRAM_WRITE; + pram->byte = now_byte; + pram->command_i = 0; + + printf("PRAMPRAM: fetching time byte %u of 0x%08x (mysterybit=%u)\n", addr, now, mysterybit); + return ; + } + else { // incomplete command, keep reading + assert(pram->command_i < 3); + pram->mode = PRAM_READ; + + return ; + } + } + + // This is mystery command # 2 + else if (pram->command[0] == 0x35) { + // Arrives in pairs of two bytes + if (pram->command_i == 2) { + printf("PRAMPRAM: mystery command 2 0x%02x 0x%02x (?))\n", pram->command[0], pram->command[1]); + + pram->mode = PRAM_READ; + pram->command_i = 0; + return ; + } + else { // keep reading + assert(pram->command_i < 3); + pram->mode = PRAM_READ; + + return ; + } + + } + + + printf("PRAMPRAM: don't understand this command\n"); + pram->command_i = 0; + pram->mode = PRAM_READ; +} + +static void handle_pram_state_change (void) +{ + pram_state_t *pram = &shoe.pram; + + // If rtcClock or rtcEnable changed, then the state machine needs updating + if (pram->last_bits == (shoe.via[0].regb_output & shoe.via[0].ddrb & 6)) + return ; + + printf("PRAMPRAM: pram->last_bits = %u, (shoe.via[0].regb & 6) = %u\n", pram->last_bits, (shoe.via[0].regb_output & shoe.via[0].ddrb & 6)); + + // it doesn't matter what the last rtcData value was + const _Bool last_rtcClock = (pram->last_bits >> 1) & 1; + const _Bool last_rtcEnable = (pram->last_bits >> 2) & 1; + + const _Bool rtcData = shoe.via[0].regb_output & 1; + const _Bool rtcClock = (shoe.via[0].regb_output >> 1) & 1; + const _Bool rtcEnable = (shoe.via[0].regb_output >> 2) & 1; + + printf("PRAMPRAM: bits changed %u%ux -> %u%u%u\n", last_rtcEnable, last_rtcClock, rtcEnable, rtcClock, rtcData); + + if (rtcEnable) { + // rtcEnable==true => the RTC chip is enabled and we are talking to it + // Not sure what happens when you toggle data/clock bits while rtcEnable is asserted... + if (last_rtcEnable) + printf("PRAMPRAM: toggled bits while rtcEnable was asserted!\n"); + goto done; + } + + if (!rtcEnable && last_rtcEnable) { + // if rtcEnable went from hi to low, then reset all the state stuff + pram->mode = PRAM_READ; + pram->command_i = 0; // the current command byte we're working on + pram->bit_i = 0; // the current bit num we're reading/writing + pram->byte = 0; // the current byte we're reading/writing + memset(pram->command, 0, 8); + goto done; + } + + + switch (pram->mode) { + case PRAM_READ: { + // if rtcClock goes from low to hi, then rtcData represents a new bit + if (rtcClock && !last_rtcClock) { + pram->byte <<= 1; + pram->byte |= rtcData; + pram->bit_i++; + } + + if ((shoe.via[0].ddrb & 1) == 0) { + // This is input-mode -- should be output-mode + printf("PRAMPRAM: BOGUS MODE ddrb&1 == 0\n"); + } + + + if (pram->bit_i >= 8) { + pram->bit_i = 0; + handle_pram_read_byte(); + } + goto done; + } + + case PRAM_WRITE: { + // if rtcClock goes from hi to low, load in the new rtcData bit + if (!rtcClock && last_rtcClock) { + const uint8_t newData = (pram->byte >> (7 - pram->bit_i)) & 1; + shoe.via[0].regb_input &= 0xfe; + shoe.via[0].regb_input |= newData; + } + + // if B goes from low to hi, skip to the next bit + if (rtcClock && !last_rtcClock) + pram->bit_i++; + + assert((shoe.via[0].ddrb & 1) == 0); + + if (pram->bit_i >= 8) { + pram->bit_i = 0; + handle_pram_write_byte(); + } + goto done; + } + + default: + assert(!"can't get here"); + } + +done: + + // Remember the last state of the bits + pram->last_bits = (shoe.via[0].regb_output & shoe.via[0].ddrb & 6); +} + +void init_via_state (void) +{ + /* -- Zero everything -- */ + + memset(&shoe.pram, 0, sizeof(pram_state_t)); + memset(&shoe.via, 0, 2 * sizeof(via_state_t)); + + // Jeez, keep this straight! + // DDR 0 -> input (from pins to OS) + // 1 -> output (from OS to pins) + + /* -- Initialize VIA1 -- */ + + /* VIA 1 reg A + * Bit 7 - input - vSCCWrReq + * Bit 6 - input - CPU.ID1 + * Bit 5 - output - vHeadSel + * Bit 4 - output - vOverlay + * Bit 3 - output - vSync + * Bit 2-0 unused + */ + shoe.via[0].ddra = 0b00111000; + + /* VIA 1 reg B + * Bit 7 - output - vSndEnb + * Bit 6 - unused + * Bit 5 - output - vFDesk2 + * Bit 4 - output - vFDesk1 + * Bit 3 - input - vFDBInt + * Bit 2 - output - rTCEnb + * Bit 1 - output - rtcClk + * Bit 0 - in/out - rtcData (initialize to output) + */ + shoe.via[0].ddrb = 0b10110111; // A/UX apparently neglects to initialize ddra/b + + /* -- Initialize VIA2 -- */ + + /* VIA 2 reg A + * Bit 7 - unused + * Bit 6 - unused + * Bit 5 - Interrupt for slot 15 + * ... + * Bit 0 - Interrupt for slot 9 + */ + shoe.via[1].ddra = 0x00; // via2/rega consists of input pins for nubus interrupts + shoe.via[1].rega_input = 0b00111111; // no nubus interrupts currently asserted + + /* VIA 2 reg B + * Bit 7 - output - v2VBL + * Bit 6 - input - v2SNDEXT + * Bit 5 - input - v2TM0A (nubus transfer what??) + * Bit 4 - input - v2TM1A + * Bit 3 - output - AMU/PMMU control + * Bit 2 - output - v2PowerOff + * Bit 1 - output - v2BusLk + * Bit 0 - output - v2cdis + */ + shoe.via[1].ddrb = 0b10001111; + // FIXME: apparently via2/regb bit 7 is tied to VIA1, and driven by timer T1, to + // generate 60.15hz interrupts on VIA1 + // emulate this more accurately! + + /* -- Initialize PRAM -- */ + + pram_state_t *pram = &shoe.pram; + pram->mode = PRAM_READ; + + FILE *f = fopen("pram.dump", "r"); + if (f) { + fread(pram->data, 256, 1, f); + fclose(f); + } +} + +#define E_CLOCK 783360 +#define HALF_E_CLOCK (E_CLOCK / 2) + +#define _via_get_delta_counter(last_set) ({ \ + const long double delta_t = now - (last_set); \ + const long double delta_ticks = fmodl((delta_t * (long double)E_CLOCK), 0x10000); \ + /* The VIA timers decrement by 2 for every E_CLOCK tick */ \ + const uint16_t delta_counter = ((uint16_t)delta_ticks) << 1; \ + printf("_via_get_delta_counter: now = %Lf delta_t = %Lf delta_ticks = %Lf delta_counter = %u\n", now, delta_t, delta_ticks, delta_counter); \ + delta_counter; \ +}) + +// from the pins' perspective +#define VIA_REGA_PINS(n) ((shoe.via[(n)-1].rega_output & shoe.via[(n)-1].ddra) | \ + (shoe.via[(n)-1].rega_input & (~~shoe.via[(n)-1].ddra))) + +#define VIA_REGB_PINS(n) ((shoe.via[(n)-1].regb_output & shoe.via[(n)-1].ddrb) | \ + (shoe.via[(n)-1].regb_input & (~~shoe.via[(n)-1].ddrb))) + +static uint8_t via_read_reg(const uint8_t vianum, const uint8_t reg, const long double now) { - const uint8_t vianum = (shoe.physical_addr >= 0x50002000) ? 2 : 1; - const uint8_t reg = (shoe.physical_addr >> 9) & 15; via_state_t *via = &shoe.via[vianum - 1]; printf("via_reg_read: reading from via%u reg %s (%u)\n", vianum, via_reg_str[reg], reg); switch (reg) { + case VIA_ACR: + return via->acr; + + case VIA_PCR: + return via->pcr; + case VIA_IER: // According to the eratta, bit 7 is always set during a read - shoe.physical_dat = via->ier | 0x80; - break ; + return via->ier | 0x80; + case VIA_IFR: { // Figure out whether any enabled interrupts are set, and set IRQ accordingly const uint8_t irq = (via->ifr & via->ier & 0x7f) ? 0x80 : 0x0; - shoe.physical_dat = (via->ifr & 0x7f) | irq; - break ; + return (via->ifr & 0x7f) | irq; } case VIA_SR: - shoe.physical_dat = via->sr; - break; - - case VIA_ORB: - shoe.physical_dat = via->regb; - break; + return via->sr; + + case VIA_ORB: { + /* + * FIXME: this is not exactly correct. + * if input latching is enabled, then the value of input pins + * is held in escrow until a CB1 transition occurs. I'm not doing that. + */ + printf("via_reg_read: FYI: regb_output=0x%02x regb_input=0x%02x ddrb=0x%02x combined=0x%02x\n", + shoe.via[vianum-1].regb_output, shoe.via[vianum-1].regb_input, via->ddrb, VIA_REGB_PINS(vianum)); + return VIA_REGB_PINS(vianum); + } case VIA_ORA_AUX: - case VIA_ORA: - //if ((vianum==2) && !(via->ifr & (1<rega = 0x3f; - shoe.physical_dat = via->rega; - break; + case VIA_ORA: { + /* + * FIXME: This is not exactly correct either, and it behaves differently from regb + * Reading regA never returns the contents of the output register directly, + * it returns the the value of the pins - unless input latching is enabled, + * then it holds the pin values in escrow until a CA1 transition occurs. + * I'm just returning the value of the "pins" + */ + return VIA_REGA_PINS(vianum); + } case VIA_DDRB: - shoe.physical_dat = via->ddrb; - break; + return via->ddrb; case VIA_DDRA: - shoe.physical_dat = via->ddra; - break; + return via->ddra; + + case VIA_T2C_HI: { + const uint16_t counter = via->t2c - _via_get_delta_counter(via->t2_last_set); + return counter >> 8; + } + case VIA_T2C_LO: { + const uint16_t counter = via->t2c - _via_get_delta_counter(via->t2_last_set); + via->ifr &= ~~VIA_IFR_T2; // Read from T2C_LOW clears TIMER 2 interrupt + return (uint8_t)counter; + } - case VIA_T2C_LO: - // XXX: A/UX 3.0.1 tries to precisely time a huge dbra loop - // using via timer2. It won't accept any result shorter than - // 0x492, and hypothetically, this emulator could execute the - // loop faster than that (although not currently). So this is - // a super dumb hack that always returns a delta-t of 0x492 - // between sequential reads from t2c. - // (oh, also, a/ux 3.0.1 cleverly reads from both t2c_lo and _hi - // simultaneously by doing a word-size read at VIA+0x11ff) - counter -= 0x492; - shoe.physical_dat = 0xffff & ((counter >> 8) | (counter << 8)); - break; + case VIA_T1C_LO: + via->ifr &= ~~VIA_IFR_T1; // Read from T1C_LOW clears TIMER 1 interrupt + return 0; // FIXME - default: - printf("via_reg_read: (unhandled!)\n"); - break; + case VIA_T1C_HI: + return 0; // FIXME + + case VIA_T1L_LO: + return 0; // FIXME + + case VIA_T1L_HI: + return 0; // FIXME } + assert(!"never get here"); } -void via_reg_write() +static void via_write_reg(const uint8_t vianum, const uint8_t reg, const uint8_t data, const long double now) { - const uint8_t vianum = (shoe.physical_addr >= 0x50002000) ? 2 : 1; - const uint8_t reg = (shoe.physical_addr >> 9) & 15; - const uint8_t data = (uint8_t)shoe.physical_dat; via_state_t *via = &shoe.via[vianum - 1]; printf("via_reg_write: writing 0x%02x to via%u reg %s (%u)\n", (uint8_t)shoe.physical_dat, vianum, via_reg_str[reg], reg); @@ -300,25 +640,49 @@ void via_reg_write() break; case VIA_ORB: { - via->regb = data; + + // The OS should only be able to "set" the bits that are marked as "output" in ddra/b + + // FIXME: we need separate ORA/ORB and IRA/IRB registers + + /*const uint8_t ddr_mask = via->ddrb; + const uint8_t data_sans_input = data & ddr_mask; + const uint8_t reg_sans_output = via->regb & (~~ddr_mask); + via->regb = data_sans_input | reg_sans_output; + // via->regb = data;*/ + via->regb_output = data; if (vianum == 1) { - const uint8_t adb_state = (data >> 4) & 3; + const uint8_t adb_state = (data >> 4) & 3; // just assume that the corresponding ddrb bits are marked "output" if (shoe.adb.state != adb_state) { const uint8_t old_state = shoe.adb.state; shoe.adb.state = adb_state; adb_handle_state_change(old_state, adb_state); } + + handle_pram_state_change(); } break; } case VIA_ORA_AUX: - case VIA_ORA: - via->rega = data; + case VIA_ORA: { + // The OS should only be able to "set" the bits that are marked as "output" in ddra/b + + // FIXME: we need separate ORA/ORB and IRA/IRB registers + + /*const uint8_t ddr_mask = via->ddra; + const uint8_t data_sans_input = data & ddr_mask; + const uint8_t reg_sans_output = via->rega & (~~ddr_mask); + via->rega = data_sans_input | reg_sans_output; + // via->rega = data;*/ + + via->rega_output = data; + break; + } case VIA_DDRB: via->ddrb = data; @@ -328,55 +692,90 @@ void via_reg_write() via->ddra = data; break; - default: - printf("via_reg_read: (unhandled!)\n"); + case VIA_ACR: + via->acr = data; + break; + + case VIA_PCR: + via->pcr = data; + break; + + case VIA_T2C_LO: + break; + + case VIA_T2C_HI: + via->ifr &= ~~VIA_IFR_T2; // Write to T2C_HI clears TIMER 2 interrupt + break; + + case VIA_T1C_LO: + break; + + case VIA_T1C_HI: + via->ifr &= ~~VIA_IFR_T1; // Write to T1C_HI clears TIMER 1 interrupt + break; + + case VIA_T1L_LO: + break; + + case VIA_T1L_HI: break; } } -// FIXME: check_time() is bad and needs rewritten -void check_time() +void via_write_raw (void) { - struct timeval now, delta_tv; - const uint32_t hz = 10; + const uint8_t vianum = ((shoe.physical_addr >> 13) & 1) + 1; + const uint8_t reg = (shoe.physical_addr >> 9) & 15; - // return ; - - gettimeofday(&now, NULL); - - delta_tv.tv_sec = now.tv_sec - shoe.start_time.tv_sec; - if (now.tv_usec < shoe.start_time.tv_usec) { - delta_tv.tv_sec--; - delta_tv.tv_usec = (now.tv_usec + 1000000) - shoe.start_time.tv_usec; + if (shoe.physical_size == 1) { + const long double now = ((reg >= VIA_T1C_LO) && (reg <= VIA_T2C_HI)) ? _now() : 0.0; + // Common case: writing to only one register + + via_write_reg(vianum, reg, (uint8_t)shoe.physical_dat, now); + } + else if ((shoe.physical_size == 2) && ((shoe.physical_addr & 0x1ff) == 0x1ff)) { + const long double now = ((reg >= VIA_T1C_LO) && ((reg+1) <= VIA_T2C_HI)) ? _now() : 0.0; + // Uncommon case: writing to two registers simultaneously + + printf("via_write_raw: writing to two registers simultaneously %u and %u\n", reg, reg+1); + + assert(reg != 15); // If A/UX is trying to write to two VIA chips simultanously, that's not cool + + via_write_reg(vianum, reg, (uint8_t)(shoe.physical_dat >> 8), now); + via_write_reg(vianum, reg+1, (uint8_t)shoe.physical_dat, now); } else - delta_tv.tv_usec = now.tv_usec - shoe.start_time.tv_usec; - - uint64_t delta = delta_tv.tv_sec * 1000; - delta += delta_tv.tv_usec / 1000; - - uint64_t ticks = delta / hz; - if (ticks <= shoe.total_ticks) - return ; - - shoe.total_ticks = ticks; - //printf("ticks = %llu\n", ticks); - - via_raise_interrupt(1, IFR_CA1); - // - shoe.via[1].rega = 0b00111101; - via_raise_interrupt(2, IFR_CA1); + assert("Writing multiple bytes to the same VIA register!"); + } -static long double _now (void) +void via_read_raw (void) { - struct timeval tv; - gettimeofday(&tv, NULL); + const uint8_t vianum = ((shoe.physical_addr >> 13) & 1) + 1; + const uint8_t reg = (shoe.physical_addr >> 9) & 15; - long double secs = tv.tv_sec; - long double usecs = tv.tv_usec; - - return secs + (usecs / 1000000.0); + if (shoe.physical_size == 1) { + const long double now = ((reg >= VIA_T1C_LO) && (reg <= VIA_T2C_HI)) ? _now() : 0.0; + + // Common case: reading only one register + shoe.physical_dat = via_read_reg(vianum, reg, now); + } + else if ((shoe.physical_size == 2) && ((shoe.physical_addr & 0x1ff) == 0x1ff)) { + const long double now = ((reg >= VIA_T1C_LO) && ((reg+1) <= VIA_T2C_HI)) ? _now() : 0.0; + + // Uncommon case: reading from two registers simultaneously + + printf("via_read_raw: reading from two registers simultaneously %u and %u\n", reg, reg+1); + + assert(reg != 15); // If A/UX is trying to read from two VIA chips simultaneously, that's not cool + + uint16_t result = via_read_reg(vianum, reg, now); + result = (result << 8) | via_read_reg(vianum, reg+1, now); + shoe.physical_dat = result; + + } + else + assert(!"Reading multiple bytes from the same VIA register!"); } #define fire(s) ({assert((s) >= 0); if (earliest_next_timer > (s)) earliest_next_timer = (s);}) @@ -416,14 +815,14 @@ void *via_clock_thread(void *arg) via_raise_interrupt(1, IFR_CA2); - /*via_raise_interrupt(1, IFR_TIMER1); + via_raise_interrupt(1, IFR_TIMER1); via_raise_interrupt(1, IFR_TIMER2); via_raise_interrupt(2, IFR_TIMER1); - via_raise_interrupt(2, IFR_TIMER2);*/ + via_raise_interrupt(2, IFR_TIMER2); } // Check if any nubus cards have interrupt timers - shoe.via[1].rega = 0b00111111; + shoe.via[1].rega_input = 0b00111111; for (i=9; i<15; i++) { if (!shoe.slots[i].connected) continue; @@ -435,9 +834,9 @@ void *via_clock_thread(void *arg) if (shoe.slots[i].interrupts_enabled) { // shoe.via[1].rega = 0b00111111 & ~~(1<<(i-9)); - shoe.via[1].rega &= 0b00111111 & ~~(1<<(i-9)); + shoe.via[1].rega_input &= 0b00111111 & ~~(1<<(i-9)); via_raise_interrupt(2, IFR_CA1); - printf("Fired nubus interrupt %u\n", i); + // printf("Fired nubus interrupt %u\n", i); } } } diff --git a/core/video.c b/core/video.c index ced29af..692a470 100644 --- a/core/video.c +++ b/core/video.c @@ -95,10 +95,11 @@ void nubus_video_init(void *_ctx, uint8_t slotnum, ctx->scanline_width = scanline_width; ctx->pixels = scanline_width * height; - ctx->direct_buf = valloc(ctx->pixels * sizeof(video_ctx_color_t)); - ctx->indexed_buf = valloc(ctx->pixels); - ctx->clut = malloc(256 * sizeof(video_ctx_color_t)); - ctx->rom = malloc(4096); + ctx->direct_buf = p_alloc(shoe.pool, ctx->pixels * sizeof(video_ctx_color_t)); + ctx->indexed_buf = p_alloc(shoe.pool, ctx->pixels); + + ctx->clut = p_alloc(shoe.pool, 256 * sizeof(video_ctx_color_t)); + ctx->rom = p_alloc(shoe.pool, 4096); // Set the depth and clut for B&W _switch_depth(ctx, 1); @@ -207,7 +208,7 @@ void nubus_video_write_func(const uint32_t rawaddr, const uint32_t size, if ((addr >> 16) == 0xf0) { switch ((addr & 0x0000ffff) >> 2) { case 0: {// Clear interrupt flag - shoe.via[1].rega |= (1 << (slotnum - 9)); + shoe.via[1].rega_input |= (1 << (slotnum - 9)); break; } case 1: { // Set depth diff --git a/debugger/Makefile b/debugger/Makefile new file mode 100644 index 0000000..367a99b --- /dev/null +++ b/debugger/Makefile @@ -0,0 +1,12 @@ + +CC = clang +CFLAGS = -O0 -ggdb -flto -Wno-deprecated-declarations +LFLAGS = -L ../intermediates -lshoebill_core -framework GLUT -framework OpenGL -ledit + +all: debugger + +debugger: Makefile debugger.c ../intermediates/libshoebill_core.a + $(CC) $(CFLAGS) $(LFLAGS) debugger.c -o debugger + +clean: + rm -rf debugger diff --git a/debugger/debugger b/debugger/debugger new file mode 100755 index 0000000..339b16d Binary files /dev/null and b/debugger/debugger differ diff --git a/debugger/debugger.c b/debugger/debugger.c new file mode 100644 index 0000000..bbd58f9 --- /dev/null +++ b/debugger/debugger.c @@ -0,0 +1,923 @@ +/* + * Copyright (c) 2013, Peter Rutenbar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../core/core_api.h" +#include "../core/shoebill.h" +#include "../core/coff.h" + +rb_tree *keymap; + +struct dbg_state_t { + EditLine *el; + uint8_t running; + uint64_t breakpoint_counter; + dbg_breakpoint_t *breakpoints; + _Bool trace; +}; + +struct dbg_state_t dbg_state; + +void print_mmu_rp(uint64_t rp) +{ + printf("lu=%u limit=0x%x sg=%u dt=%u addr=0x%08x\n", rp_lu(rp), rp_limit(rp), rp_sg(rp), rp_dt(rp), rp_addr(rp)); +} + +void printregs() +{ + printf("[d0]%08x [d1]%08x [d2]%08x [d3]%08x\n", shoe.d[0], shoe.d[1], shoe.d[2], shoe.d[3]); + printf("[d4]%08x [d5]%08x [d6]%08x [d7]%08x\n", shoe.d[4], shoe.d[5], shoe.d[6], shoe.d[7]); + printf("[a0]%08x [a1]%08x [a2]%08x [a3]%08x\n", shoe.a[0], shoe.a[1], shoe.a[2], shoe.a[3]); + printf("[a4]%08x [a5]%08x [a6]%08x [a7]%08x\n", shoe.a[4], shoe.a[5], shoe.a[6], shoe.a[7]); + printf("[pc]%08x [sr]%c%c%c%c%c%c%c [tc]%08x\n", shoe.pc, + sr_s()?'S':'s', + sr_m()?'M':'m', + sr_x()?'X':'x', + sr_n()?'N':'n', + sr_z()?'Z':'z', + sr_v()?'V':'v', + sr_c()?'C':'c', + shoe.tc + ); + + printf("[vbr]%08x\n", shoe.vbr); + + printf("srp: "); + print_mmu_rp(shoe.srp); + + printf("crp: "); + print_mmu_rp(shoe.crp); + + printf("tc: e=%u sre=%u fcl=%u ps=%u is=%u (tia=%u tib=%u tic=%u tid=%u)\n", + tc_enable(), tc_sre(), tc_fcl(), tc_ps(), tc_is(), tc_tia(), tc_tib(), tc_tic(), tc_tid()); + + printf("\n"); +} + +void print_pc() +{ + char str[1024]; + uint8_t binary[32]; + uint32_t i; + uint32_t len; + const char *name = NULL; + + if ((shoe.pc >= 0x40000000) && (shoe.pc < 0x50000000)) { + uint32_t i, addr = shoe.pc % (shoe.physical_rom_size); + for (i=0; macii_rom_symbols[i].name; i++) { + if (macii_rom_symbols[i].addr > addr) { + break; + } + name = macii_rom_symbols[i].name; + } + } + else if (sr_s()) { // these symbols are only meaningful in supervisor mode + coff_symbol *symb = coff_find_func(shoe.coff, shoe.pc); + if (symb && strlen(symb->name)) + name = symb->name; + } + else { + if ((shoe.pc >= 0x10000000) && (shoe.pc < 0x20000000)) { + uint32_t i, addr = shoe.pc % (shoe.physical_rom_size); + for (i=0; macii_rom_symbols[i].name; i++) { + if (macii_rom_symbols[i].addr > addr) { + break; + } + name = macii_rom_symbols[i].name; + } + } + else { + name = ""; + } + } + + const uint16_t old_abort = shoe.abort; + shoe.suppress_exceptions = 1; + + for (i=0; i<32; i++) { + binary[i] = (uint8_t) lget(shoe.pc+i, 1); + } + + disassemble_inst(binary, shoe.pc, str, &len); + + printf("*0x%08x %s [ ", shoe.pc, name ? name : ""); + for (i=0; i a6 + // pop a7 -> return pointer + + + uint32_t i, j, a7, a6 = shoe.a[6]; + coff_symbol *symb; + + if (sr_s()) { + symb = coff_find_func(shoe.coff, shoe.pc); + printf("%u: *0x%08x %s+%u\n", 0, shoe.pc, (symb && strlen(symb->name))?symb->name:"?", shoe.pc - symb->value); + } + else + printf("%u: *0x%08x\n", 0, shoe.pc); + + for (i=1; 1; i++) { + a7 = a6; + const uint32_t last_a6 = lget(a7, 4); + const uint32_t last_pc = lget(a7+4, 4); + + if ((last_a6 - a6) <= 1000) { + printf(" {"); + for (j = a6+8; j < last_a6; j+=4) { + uint32_t data = lget(j, 4); + printf("%x, ", data); + } + printf("}\n"); + } + + if (sr_s()) { + symb = coff_find_func(shoe.coff, last_pc); + printf("%u: *0x%08x %s+%u\n", i, last_pc, (symb && strlen(symb->name))?symb->name:"?", last_pc - symb->value); + } + else + printf("%u: *0x%08x\n", i, last_pc); + + if ((last_a6 - a6) > 1000) { + break; + } + + a6 = last_a6; + } + + shoe.suppress_exceptions = 0; + shoe.abort = old_abort; +} + +void verb_break_handler (const char *line) +{ + errno = 0; + const uint32_t addr = (uint32_t) strtoul(line, NULL, 0); + + if (errno) { + printf("errno: %d\n", errno); + return ; + } + + dbg_breakpoint_t *brk = calloc(sizeof(dbg_breakpoint_t), 1); + brk->next = NULL; + brk->addr = addr; + brk->num = dbg_state.breakpoint_counter++; + + dbg_breakpoint_t **cur = &dbg_state.breakpoints; + while (*cur) + cur = &(*cur)->next; + *cur = brk; + + printf("Set breakpoint %llu = *0x%08x\n", brk->num, brk->addr); +} + +void verb_delete_handler (const char *line) +{ + errno = 0; + uint64_t num = strtoull(line, NULL, 0); + + if (errno) { + printf("errno: %d\n", errno); + return ; + } + + dbg_breakpoint_t **cur = &dbg_state.breakpoints; + while (*cur) { + if ((*cur)->num == num) { + dbg_breakpoint_t *victim = *cur; + *cur = (*cur)->next; + free(victim); + return ; + } + cur = &(*cur)->next; + } + + printf("No such breakpoint (#%llu)\n", num); +} + + +void verb_help_handler (const char *line) +{ + printf("Help help help\n"); +} + + +void verb_stepi_handler (const char *line) +{ + dbg_state.running = 1; + cpu_step(); + dbg_state.running = 0; + print_pc(); +} + +void verb_registers_handler (const char *line) +{ + printregs(); +} + +void verb_trace_toggle_handler (const char *line) +{ + dbg_state.trace = !dbg_state.trace; +} + +void verb_examine_handler (const char *line) +{ + uint32_t addr = (uint32_t)strtoul(line, NULL, 0); + uint32_t old_suppress = shoe.suppress_exceptions; + + shoe.suppress_exceptions = 1; + printf("(uint32_t)*0x%08x = 0x%08x\n", addr, (uint32_t)lget(addr, 4)); + shoe.suppress_exceptions = old_suppress; + +} + +void verb_lookup_handler (const char *line) +{ + char *sym_name = malloc(strlen(line)+1); + + sscanf(line, "%s", sym_name); + coff_symbol *symb = coff_find_symbol(shoe.coff, sym_name); + + free(sym_name); + + if (symb == NULL) { + printf("Couldn't find \"%s\"\n", sym_name); + return ; + } + + printf("%s = *0x%08x\n", symb->name, symb->value); +} + + +void stepper() +{ + dbg_breakpoint_t *cur; + + if (shoe.cpu_thread_notifications) { + + // If there's an interrupt pending + if (shoe.cpu_thread_notifications & 0xff) { + // process_pending_interrupt() may clear SHOEBILL_STATE_STOPPED + process_pending_interrupt(); + } + + if (shoe.cpu_thread_notifications & SHOEBILL_STATE_STOPPED) { + // I think it's safe to ignore STOP instructions... + } + } + + cpu_step(); + + if (dbg_state.trace) { + print_pc(); + printregs(); + } + + for (cur = dbg_state.breakpoints; cur != NULL; cur = cur->next) { + if (shoe.pc == cur->addr) { + printf("Hit breakpoint %llu *0x%08x\n", cur->num, shoe.pc); + dbg_state.running = 0; + return ; + } + } +} + +void verb_continue_handler (const char *line) +{ + dbg_state.running = 1; + while (dbg_state.running) { + stepper(); + } + print_pc(); +} + +void verb_quit_handler (const char *line) +{ + printf("Quitting\n"); + fflush(stdout); + exit(0); +} + +void verb_reset_handler (const char *line) +{ + p_free_pool(shoe.pool); + shoe.pool = NULL; +} + +struct verb_handler_table_t { + const char *name; + void (*func)(const char *); +} verb_handler_table[] = +{ + {"quit", verb_quit_handler}, + {"continue", verb_continue_handler}, + {"help", verb_help_handler}, + {"registers", verb_registers_handler}, + {"stepi", verb_stepi_handler}, + {"backtrace", verb_backtrace_handler}, + {"bt", verb_backtrace_handler}, + {"break", verb_break_handler}, + {"delete", verb_delete_handler}, + {"lookup", verb_lookup_handler}, + {"trace", verb_trace_toggle_handler}, + {"x", verb_examine_handler}, + {"reset", verb_reset_handler}, +}; + +void execute_verb (const char *line) +{ + char verb[128]; + uint32_t max_len=0, max_i=0; + const char *remainder; + uint32_t i, matches = 0, match_i; + + if (sscanf(line, "%127s", verb) != 1) + return ; + + // Skip past the verb + for (remainder = line; *remainder && !isspace(*remainder); remainder++) + ; + + // Skip past the space between the verb and the arguments + for (; *remainder && isspace(*remainder); remainder++) + ; + + const uint32_t verb_len = strlen(verb); + for (i=0; i < (sizeof(verb_handler_table) / sizeof(struct verb_handler_table_t)); i++) { + const uint32_t i_len = strlen(verb_handler_table[i].name); + + // If it's a perfect match, + if (strcasecmp(verb, verb_handler_table[i].name)==0) { + verb_handler_table[i].func(remainder); + return ; + } + + // Otherwise, see if it's a partial match + if ((i_len >= verb_len) && strncasecmp(verb, verb_handler_table[i].name, verb_len)==0) { + matches++; + match_i = i; + } + } + + // Only execute the verb if it's an unambiguous match (matches == 1) + if (matches == 1) { + verb_handler_table[match_i].func(remainder); + return ; + } + + printf(" %s?\n", verb); +} + +char *cli_prompt_callback(EditLine *el) +{ + return "~ "; +} + +// Hack to clear line after ^C. el_reset() screws up tty when called from the signal handler. +void ch_reset(EditLine *el, int mclear); + +void signal_callback(int sig) +{ + EditLine *el = dbg_state.el; + (void) signal(SIGINT, signal_callback); + (void) signal(SIGWINCH, signal_callback); + + switch (sig) { + case SIGWINCH: + el_resize(el); + break ; + case SIGINT: + if (dbg_state.running) { + dbg_state.running = 0; + } + else { + printf("\n"); + ch_reset(el, 0); + el_set(el, EL_REFRESH); + } + break ; + } + + return ; +} + +void *ui_thread (void *arg) +{ + EditLine *el; + History *hist; + HistEvent histev; + + const char *buf; + int num; + + hist = history_init(); + history(hist, &histev, H_SETSIZE, 10000); // Remember 10000 previous user inputs + + el = el_init("Shoebill", stdin, stdout, stderr); + dbg_state.el = el; + + el_set(el, EL_SIGNAL, 0); + el_set(el, EL_PROMPT, cli_prompt_callback); + el_set(el, EL_EDITOR, "emacs"); + el_set(el, EL_HIST, history, hist); + + (void) signal(SIGINT, signal_callback); + (void) signal(SIGWINCH, signal_callback); + + while ((buf = el_gets(el, &num)) != NULL) { + if (strcmp(buf, "\n")!=0) { + execute_verb(buf); + history(hist, &histev, H_ENTER, buf); + } + } + + el_end(el); + history_end(hist); + return NULL; +} + +static uint8_t lookup_special(int special) +{ + switch (special) { + case GLUT_KEY_UP: return 0x3e; + case GLUT_KEY_DOWN: return 0x3d; + case GLUT_KEY_LEFT: return 0x3b; + case GLUT_KEY_RIGHT: return 0x3c; + default: return 0xff; + } +} + +static uint32_t _get_modifiers (void) +{ + int glut_modifiers = glutGetModifiers(); + uint32_t result = 0; + + result |= (glut_modifiers & GLUT_ACTIVE_SHIFT) ? (1 << 17) : 0; + result |= (glut_modifiers & GLUT_ACTIVE_CTRL) ? (1 << 18) : 0; + result |= (glut_modifiers & GLUT_ACTIVE_ALT) ? (1 << 19) : 0; + + return result; +} + +void global_mouse_func (int button, int state, int x, int y) +{ + shoebill_mouse_click(state == GLUT_DOWN); + shoebill_mouse_move(x, y); +} + +void global_motion_func (int x, int y) +{ + shoebill_mouse_click(1); + shoebill_mouse_move(x, y); +} + +void global_passive_motion_func (int x, int y) +{ + shoebill_mouse_click(0); + shoebill_mouse_move(x, y); +} + +void global_keyboard_up_func (unsigned char c, int x, int y) +{ + void *_value; + if (rb_find(keymap, c, &_value)) { + const uint16_t value = (uint16_t)_value; + shoebill_key_modifier((value >> 8) | (_get_modifiers() >> 16)); + shoebill_key(0, value & 0xff); + } +} + +void global_keyboard_down_func (unsigned char c, int x, int y) +{ + void *_value; + if (rb_find(keymap, c, &_value)) { + const uint16_t value = (uint16_t)_value; + shoebill_key_modifier((value >> 8) | (_get_modifiers() >> 16)); + shoebill_key(1, value & 0xff); + } +} + +void global_special_up_func (int special, int x, int y) +{ + const uint8_t code = lookup_special(special); + if (code != 0xff) { + shoebill_key_modifier(_get_modifiers() >> 16); + shoebill_key(0, code); + } +} + +void global_special_down_func (int special, int x, int y) +{ + const uint8_t code = lookup_special(special); + if (code != 0xff) { + shoebill_key_modifier(_get_modifiers() >> 16); + shoebill_key(1, code); + } +} + +void timer_func (int arg) +{ + glutTimerFunc(15, timer_func, 0); // 15ms = 66.67hz + glutPostRedisplay(); +} + +static void _do_clut_translation(shoebill_card_video_t *ctx) +{ + uint32_t i; + + switch (ctx->depth) { + case 1: { + for (i=0; i < ctx->pixels/8; i++) { + const uint8_t byte = ctx->indexed_buf[i]; + ctx->direct_buf[i * 8 + 0] = ctx->clut[(byte >> 7) & 1]; + ctx->direct_buf[i * 8 + 1] = ctx->clut[(byte >> 6) & 1]; + ctx->direct_buf[i * 8 + 2] = ctx->clut[(byte >> 5) & 1]; + ctx->direct_buf[i * 8 + 3] = ctx->clut[(byte >> 4) & 1]; + ctx->direct_buf[i * 8 + 4] = ctx->clut[(byte >> 3) & 1]; + ctx->direct_buf[i * 8 + 5] = ctx->clut[(byte >> 2) & 1]; + ctx->direct_buf[i * 8 + 6] = ctx->clut[(byte >> 1) & 1]; + ctx->direct_buf[i * 8 + 7] = ctx->clut[(byte >> 0) & 1]; + } + break; + } + case 2: { + for (i=0; i < ctx->pixels/4; i++) { + const uint8_t byte = ctx->indexed_buf[i]; + ctx->direct_buf[i * 4 + 0] = ctx->clut[(byte >> 6) & 3]; + ctx->direct_buf[i * 4 + 1] = ctx->clut[(byte >> 4) & 3]; + ctx->direct_buf[i * 4 + 2] = ctx->clut[(byte >> 2) & 3]; + ctx->direct_buf[i * 4 + 3] = ctx->clut[(byte >> 0) & 3]; + } + break; + } + case 4: { + for (i=0; i < ctx->pixels/2; i++) { + const uint8_t byte = ctx->indexed_buf[i]; + ctx->direct_buf[i * 2 + 0] = ctx->clut[(byte >> 4) & 0xf]; + ctx->direct_buf[i * 2 + 1] = ctx->clut[(byte >> 0) & 0xf]; + } + break; + } + case 8: + for (i=0; i < ctx->pixels; i++) + ctx->direct_buf[i] = ctx->clut[ctx->indexed_buf[i]]; + break; + + default: + assert(!"unknown depth"); + } +} + +void _display_func (void) +{ + shoebill_card_video_t *video = (shoebill_card_video_t*)shoe.slots[9].ctx; + + _do_clut_translation(video); + + glDrawBuffer(GL_BACK); + glClear(GL_COLOR_BUFFER_BIT); + + glClearColor(0.0, 0.0, 0.0, 0.0); + + glViewport(0, 0, video->width, video->height); + glRasterPos2i(0, video->height); + glPixelStorei(GL_UNPACK_LSB_FIRST, GL_TRUE); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glPixelZoom(1.0, -1.0); + + glDrawPixels(video->width, + video->height, + GL_RGBA, + GL_UNSIGNED_BYTE, + video->direct_buf); + + glutSwapBuffers(); +} + +static void _init_keyboard_map (void) +{ + #define mapkeymod(u, a, m) do { \ + assert((a >> 7) == 0); \ + void *value = (void*)(((m) << 8)| (a)); \ + rb_insert(keymap, u, value, NULL); \ + } while (0) + + #define mapkey(_u, a) mapkeymod(_u, a, 0) + + keymap = rb_new(); + + // Letters + mapkey('a', 0x00); + mapkey('b', 0x0b); + mapkey('c', 0x08); + mapkey('d', 0x02); + mapkey('e', 0x0e); + mapkey('f', 0x03); + mapkey('g', 0x05); + mapkey('h', 0x04); + mapkey('i', 0x22); + mapkey('j', 0x26); + mapkey('k', 0x28); + mapkey('l', 0x25); + mapkey('m', 0x2e); + mapkey('n', 0x2d); + mapkey('o', 0x1f); + mapkey('p', 0x23); + mapkey('q', 0x0c); + mapkey('r', 0x0f); + mapkey('s', 0x01); + mapkey('t', 0x11); + mapkey('u', 0x20); + mapkey('v', 0x09); + mapkey('w', 0x0d); + mapkey('x', 0x07); + mapkey('y', 0x10); + mapkey('z', 0x06); + + // Numbers + mapkey('0', 0x1d); + mapkey('1', 0x12); + mapkey('2', 0x13); + mapkey('3', 0x14); + mapkey('4', 0x15); + mapkey('5', 0x17); + mapkey('6', 0x16); + mapkey('7', 0x1a); + mapkey('8', 0x1c); + mapkey('9', 0x19); + + // Top row symbols + mapkeymod(')', 0x1d, modShift); + mapkeymod('!', 0x12, modShift); + mapkeymod('@', 0x13, modShift); + mapkeymod('#', 0x14, modShift); + mapkeymod('$', 0x15, modShift); + mapkeymod('%', 0x17, modShift); + mapkeymod('^', 0x16, modShift); + mapkeymod('&', 0x1a, modShift); + mapkeymod('*', 0x1c, modShift); + mapkeymod('(', 0x19, modShift); + + // Other symbols (no shift) + mapkeymod('`', 0x32, 0); + mapkeymod('-', 0x1b, 0); + mapkeymod('=', 0x18, 0); + mapkeymod('[', 0x21, 0); + mapkeymod(']', 0x1e, 0); + mapkeymod('\\', 0x2a, 0); + mapkeymod(';', 0x29, 0); + mapkeymod('\'', 0x27, 0); + mapkeymod(',', 0x2b, 0); + mapkeymod('.', 0x2f, 0); + mapkeymod('/', 0x2c, 0); + + // Other symbols (with shift) + mapkeymod('~', 0x32, modShift); + mapkeymod('_', 0x1b, modShift); + mapkeymod('+', 0x18, modShift); + mapkeymod('{', 0x21, modShift); + mapkeymod('}', 0x1e, modShift); + mapkeymod('|', 0x2a, modShift); + mapkeymod(':', 0x29, modShift); + mapkeymod('"', 0x27, modShift); + mapkeymod('<', 0x2b, modShift); + mapkeymod('>', 0x2f, modShift); + mapkeymod('?', 0x2c, modShift); + + // Function keys + /*mapkey(NSF1FunctionKey, 0x7a); + mapkey(NSF2FunctionKey, 0x78); + mapkey(NSF3FunctionKey, 0x63); + mapkey(NSF4FunctionKey, 0x76); + mapkey(NSF5FunctionKey, 0x60); + mapkey(NSF6FunctionKey, 0x61); + mapkey(NSF7FunctionKey, 0x62); + mapkey(NSF8FunctionKey, 0x64); + mapkey(NSF9FunctionKey, 0x65); + mapkey(NSF10FunctionKey, 0x6d); + mapkey(NSF11FunctionKey, 0x67); + mapkey(NSF12FunctionKey, 0x6f); + mapkey(NSF13FunctionKey, 0x69); + mapkey(NSF14FunctionKey, 0x6b); + mapkey(NSF15FunctionKey, 0x71);*/ + + // Arrows + /*mapkey(NSUpArrowFunctionKey, 0x3e); + mapkey(NSDownArrowFunctionKey, 0x3d); + mapkey(NSRightArrowFunctionKey, 0x3c); + mapkey(NSLeftArrowFunctionKey, 0x3b);*/ + + // Delete + //mapkey(NSDeleteFunctionKey, 0x75); + mapkey(0x08, 0x33); + mapkey(0x7f, 0x33); + + // Enter, NL, CR + mapkey('\r', 0x24); + mapkey('\n', 0x24); + mapkey(0x03, 0x24); + + // Other keys + mapkey(0x1b, 0x35); // escape + mapkey(' ', 0x31); // space + mapkey('\t', 0x30); // tab +} + +static void _init_glut_video (void) +{ + shoebill_card_video_t *ctx = (shoebill_card_video_t*)shoe.slots[9].ctx; + + glutInitWindowSize(ctx->width, ctx->height); + glutCreateWindow("Shoebill"); + glutDisplayFunc(_display_func); + glutIgnoreKeyRepeat(1); + + + glutKeyboardFunc(global_keyboard_down_func); + glutKeyboardUpFunc(global_keyboard_up_func); + + glutSpecialFunc(global_special_down_func); + glutSpecialUpFunc(global_special_up_func); + + glutMouseFunc(global_mouse_func); + glutMotionFunc(global_motion_func); + glutPassiveMotionFunc(global_passive_motion_func); + + glutInitDisplayMode (GLUT_DOUBLE); + + glShadeModel(GL_FLAT); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glClearColor(0.1, 1.0, 0.1, 1.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, ctx->width, 0, ctx->height, -1.0, 1.0); + + glViewport(0, 0, ctx->width, ctx->height); + +} + +int main (int argc, char **argv) +{ + shoebill_control_t control; + pthread_t pid; + + + bzero(&control, sizeof(shoebill_control_t)); + + /* + * A variety of hacky things happen in debug mode. + * shoebill_start() will not create a new thread to run + * the CPU loop. We'll create a CPU thread here, bypass + * core_api, and directly manipulate the emulator guts. + * + * This is not a great example of how to write a GUI + * for shoebill... + */ + control.debug_mode = 1; + + control.aux_verbose = 1; + control.ram_size = 16 * 1024 * 1024; + control.aux_kernel_path = "/unix"; + control.rom_path = "/Users/pruten/checkouts/shoebill/priv/macii.rom"; + + control.scsi_devices[0].path = "/Users/pruten/checkouts/shoebill/priv/Apple_UNIX_3.iso"; + + if (!shoebill_initialize(&control)) { + printf("%s\n", control.error_msg); + return 0; + } + + _init_keyboard_map(); + + shoebill_install_video_card(&control, + 9, // slotnum + 1024, + 768, + 60.0); + + // Start the VIA timer thread + shoebill_start(); + + // Create a new thread to drive the CPU & debugger UI + pthread_create(&pid, NULL, ui_thread, NULL); + + int dummyargc = 1; + glutInit(&dummyargc, argv); + + // Create/configure the screen + _init_glut_video(); + + // Set a GLUT timer to update the screen + glutTimerFunc(15, timer_func, 0); + + glutMainLoop(); + + return 0; +} + + diff --git a/gui/Shoebill/shoeApplication.m b/gui/Shoebill/shoeApplication.m index 905743a..48df1d4 100644 --- a/gui/Shoebill/shoeApplication.m +++ b/gui/Shoebill/shoeApplication.m @@ -265,6 +265,7 @@ control.ram_size = (uint32_t)memsize * 1024 * 1024; control.aux_kernel_path = rootKernelPathCString; control.rom_path = romPathCString; + control.debug_mode = 0; *width = screenWidthValue; *height = screenHeightValue; diff --git a/web/0.0.1_prefs_disks.png b/web/0.0.1_prefs_disks.png deleted file mode 100644 index f818ebf..0000000 Binary files a/web/0.0.1_prefs_disks.png and /dev/null differ diff --git a/web/0.0.1_prefs_general.png b/web/0.0.1_prefs_general.png deleted file mode 100644 index 1f40af6..0000000 Binary files a/web/0.0.1_prefs_general.png and /dev/null differ diff --git a/web/0.0.2_prefs_general.png b/web/0.0.2_prefs_general.png deleted file mode 100644 index 4618678..0000000 Binary files a/web/0.0.2_prefs_general.png and /dev/null differ diff --git a/web/2014_02_26_aux1.1.1.png b/web/2014_02_26_aux1.1.1.png deleted file mode 100644 index b4dc51d..0000000 Binary files a/web/2014_02_26_aux1.1.1.png and /dev/null differ diff --git a/web/2014_02_26_marathon_mangled_clut.png b/web/2014_02_26_marathon_mangled_clut.png deleted file mode 100644 index 97d74f1..0000000 Binary files a/web/2014_02_26_marathon_mangled_clut.png and /dev/null differ diff --git a/web/2014_02_26_pathways.png b/web/2014_02_26_pathways.png deleted file mode 100644 index b1325d8..0000000 Binary files a/web/2014_02_26_pathways.png and /dev/null differ diff --git a/web/2014_02_26_possum.png b/web/2014_02_26_possum.png deleted file mode 100644 index c669b04..0000000 Binary files a/web/2014_02_26_possum.png and /dev/null differ diff --git a/web/2014_04_05_aux3.0.0_sorta_works.png b/web/2014_04_05_aux3.0.0_sorta_works.png deleted file mode 100644 index b15fa2f..0000000 Binary files a/web/2014_04_05_aux3.0.0_sorta_works.png and /dev/null differ