/************************************************************************/ /* KEGS: Apple //gs Emulator */ /* Copyright 2002 by Kent Dickey */ /* */ /* This code is covered by the GNU GPL */ /* */ /* The KEGS web page is kegs.sourceforge.net */ /* You may contact the author at: kadickey@alumni.princeton.edu */ /************************************************************************/ const char rcsid_dis_c[] = "@(#)$KmKId: dis.c,v 1.103 2004-11-24 16:41:41-05 kentd Exp $"; #include #include "defc.h" #include #include "disas.h" #define LINE_SIZE 160 extern byte *g_memory_ptr; extern byte *g_slow_memory_ptr; extern int halt_sim; extern int enter_debug; extern int g_c068_statereg; extern word32 stop_run_at; extern int Verbose; extern int Halt_on; extern int g_testing_enabled; extern int g_fullscreen; extern int g_config_control_panel; int g_num_breakpoints = 0; word32 g_breakpts[MAX_BREAK_POINTS]; extern int g_irq_pending; extern Engine_reg engine; #define W_BUF_LEN 128 char w_buff[W_BUF_LEN]; int g_stepping = 0; word32 list_kpc; int hex_line_len; word32 a1,a2,a3; word32 g_a4, g_a4bank; int a1bank, a2bank, a3bank; char *line_ptr; int mode,old_mode; int got_num; int g_quit_sim_now = 0; int get_num() { int tmp1; a2 = 0; got_num = 0; while(1) { if(mode == 0 && got_num != 0) { /* printf("In getnum, mode =0, setting a1,a3 = a2\n"); printf("a2: %x\n", a2); */ a3 = a2; a3bank = a2bank; a1 = a2; a1bank = a2bank; } tmp1 = *line_ptr++ & 0x7f; if(tmp1 >= '0' && tmp1 <= '9') { a2 = (a2 << 4) + tmp1 - '0'; got_num = 1; continue; } if(tmp1 >= 'a' && tmp1 <= 'f') { a2 = (a2 << 4) + tmp1 - 'a' + 10; got_num = 1; continue; } if(tmp1 == '/') { a2bank = a2; a2 = 0; continue; } return tmp1; } } void debugger_help() { printf("KEGS Debugger help (courtesy Fredric Devernay\n"); printf("General command syntax: [bank]/[address][command]\n"); printf("e.g. 'e1/0010B' to set a breakpoint at the interrupt jump pt\n"); printf("Enter all addresses using lower-case\n"); printf("As with the IIgs monitor, you can omit the bank number after\n"); printf("having set it: 'e1/0010B' followed by '14B' will set\n"); printf("breakpoints at e1/0010 and e1/0014\n"); printf("\n"); printf("g Go\n"); printf("[bank]/[addr]g Go from [bank]/[address]\n"); printf("s Step one instruction\n"); printf("[bank]/[addr]s Step one instr at [bank]/[address]\n"); printf("[bank]/[addr]B Set breakpoint at [bank]/[address]\n"); printf("B Show all breakpoints\n"); printf("[bank]/[addr]D Delete breakpoint at [bank]/[address]\n"); printf("[bank]/[addr1].[addr2] View memory\n"); printf("[bank]/[addr]L Disassemble memory\n"); printf("P Dump the trace to 'pc_log_out'\n"); printf("Z Dump SCC state\n"); printf("I Dump IWM state\n"); printf("[drive].[track]I Dump IWM state\n"); printf("E Dump Ensoniq state\n"); printf("[osc]E Dump oscillator [osc] state\n"); printf("R Dump dtime array and events\n"); printf("T Show toolbox log\n"); printf("[bank]/[addr]T Dump tools using ptr [bank]/[addr]\n"); printf(" as 'tool_set_info'\n"); printf("[mode]V XOR verbose with 1=DISK, 2=IRQ,\n"); printf(" 4=CLK,8=SHADOW,10=IWM,20=DOC,\n"); printf(" 40=ABD,80=SCC, 100=TEST, 200=VIDEO\n"); printf("[mode]H XOR halt_on with 1=SCAN_INT,\n"); printf(" 2=IRQ, 4=SHADOW_REG, 8=C70D_WRITES\n"); printf("r Reset\n"); printf("[0/1]=m Changes m bit for l listings\n"); printf("[0/1]=x Changes x bit for l listings\n"); printf("[t]=z Stops at absolute time t (obsolete)\n"); printf("S show_bankptr_bank0 & smartport errs\n"); printf("P show_pmhz\n"); printf("A show_a2_line_stuff show_adb_log\n"); printf("Ctrl-e Dump registers\n"); printf("[bank]/[addr1].[addr2]us[file] Save mem area to [file]\n"); printf("[bank]/[addr1].[addr2]ul[file] Load mem area from [file]\n"); printf("v Show video information\n"); printf("q Exit Debugger (and KEGS)\n"); } void do_debug_intfc() { char linebuf[LINE_SIZE]; int slot_drive; int track; int osc; int done; int ret_val; g_config_control_panel = 1; hex_line_len = 0x10; a1 = 0; a2 = 0; a3 = 0; g_a4 = 0; a1bank = 0; a2bank = 0; a3bank = 0; g_a4bank = 0; list_kpc = engine.kpc; g_stepping = 0; mode = 0; old_mode = 0; done = 0; stop_run_at = -1; x_auto_repeat_on(0); g_fullscreen = 0; x_full_screen(0); if(g_quit_sim_now) { printf("Exiting immediately\n"); return; } printf("Type 'h' for help\n"); while(!done) { printf("> "); fflush(stdout); if(read_line(linebuf,LINE_SIZE-1) <= 0) { done = 1; continue; } line_ptr = linebuf; /* printf("input line: :%s:\n", linebuf); printf("mode: %d\n", mode); */ mode = 0; while(*line_ptr != 0) { ret_val = get_num(); /* printf("ret_val: %x, got_num= %d\n", ret_val, got_num); */ old_mode = mode; mode = 0; switch(ret_val) { case 'h': debugger_help(); break; case 'R': show_dtime_array(); show_all_events(); break; case 'I': slot_drive = -1; track = -1; if(got_num) { if(old_mode == '.') { slot_drive = a1; } track = a2; } iwm_show_track(slot_drive, track); iwm_show_stats(); break; case 'E': osc = -1; if(got_num) { osc = a2; } doc_show_ensoniq_state(osc); break; case 'T': if(got_num) { show_toolset_tables(a2bank, a2); } else { show_toolbox_log(); } break; case 'v': if(got_num) { dis_do_compare(); } else { video_show_debug_info(); } break; case 'V': printf("g_irq_pending: %05x\n", g_irq_pending); printf("Setting Verbose ^= %04x\n", a1); Verbose ^= a1; printf("Verbose is now: %04x\n", Verbose); break; case 'H': printf("Setting Halt_on ^= %04x\n", a1); Halt_on ^= a1; printf("Halt_on is now: %04x\n", Halt_on); break; case 'r': do_reset(); list_kpc = engine.kpc; break; case 'm': if(old_mode == '=') { if(!a1) { engine.psr &= ~0x20; } else { engine.psr |= 0x20; } if(engine.psr & 0x100) { engine.psr |= 0x30; } } else { dis_do_memmove(); } break; case 'p': dis_do_pattern_search(); break; case 'x': if(old_mode == '=') { if(!a1) { engine.psr &= ~0x10; } else { engine.psr |= 0x10; } if(engine.psr & 0x100) { engine.psr |= 0x30; } } break; case 'z': if(old_mode == '=') { stop_run_at = a1; printf("Calling add_event for t:%08x\n", a1); add_event_stop((double)a1); printf("set stop_run_at = %x\n", a1); } break; case 'l': case 'L': do_debug_list(); break; case 'Z': show_scc_log(); show_scc_state(); break; case 'S': show_bankptrs_bank0rdwr(); smartport_error(); break; case 'C': show_xcolor_array(); break; case 'P': show_pc_log(); break; case 'M': show_pmhz(); break; case 'A': show_a2_line_stuff(); show_adb_log(); break; case 's': g_stepping = 1; if(got_num) { engine.kpc = (a2bank<<16) + (a2&0xffff); } mode = 's'; list_kpc = engine.kpc; break; case 'B': if(got_num) { printf("got_num: %d, a2bank: %x, a2: %x\n", got_num, a2bank, a2); set_bp((a2bank << 16) + a2); } else { show_bp(); } break; case 'D': if(got_num) { printf("got_num: %d, a2bank: %x, a2: %x\n", got_num, a2bank, a2); delete_bp((a2bank << 16) + a2); } break; case 'g': case 'G': printf("Going..\n"); g_stepping = 0; if(got_num) { engine.kpc = (a2bank<<16) + (a2&0xffff); } if(ret_val == 'G' && g_testing_enabled) { do_gen_test(got_num, a2); } else { do_go(); } list_kpc = engine.kpc; break; case 'q': case 'Q': printf("Exiting debugger\n"); return; break; case 'u': printf("Unix commands\n"); do_debug_unix(); break; case ':': case '.': case '+': case '-': case '=': case ',': mode = ret_val; printf("Setting mode = %x\n", mode); break; case ' ': case '\t': if(!got_num) { mode = old_mode; break; } do_blank(); break; case '<': g_a4 = a2; g_a4bank = a2bank; break; case 0x05: /* ctrl-e */ show_regs(); break; case '\n': *line_ptr = 0; if(old_mode == 's') { do_blank(); break; } if(line_ptr == &linebuf[1]) { a2 = a1 | (hex_line_len - 1); show_hex_mem(a1bank,a1,a2bank,a2, -1); a1 = a2 + 1; } else { if(got_num == 1 || mode == 's') { do_blank(); } } break; case 'w': read_line(w_buff, W_BUF_LEN); break; default: printf("\nUnrecognized command: %s\n",linebuf); *line_ptr = 0; break; } } } printf("Console closed.\n"); } word32 dis_get_memory_ptr(word32 addr) { word32 tmp1, tmp2, tmp3; tmp1 = get_memory_c(addr, 0); tmp2 = get_memory_c(addr + 1, 0); tmp3 = get_memory_c(addr + 2, 0); return (tmp3 << 16) + (tmp2 << 8) + tmp1; } void show_one_toolset(FILE *toolfile, int toolnum, word32 addr) { word32 rout_addr; int num_routs; int i; num_routs = dis_get_memory_ptr(addr); fprintf(toolfile, "Tool 0x%02x, table: 0x%06x, num_routs:%03x\n", toolnum, addr, num_routs); for(i = 1; i < num_routs; i++) { rout_addr = dis_get_memory_ptr(addr + 4*i); fprintf(toolfile, "%06x = %02x%02x\n", rout_addr, i, toolnum); } } void show_toolset_tables(word32 a2bank, word32 addr) { FILE *toolfile; word32 tool_addr; int num_tools; int i; addr = (a2bank << 16) + (addr & 0xffff); toolfile = fopen("tool_set_info", "w"); if(toolfile == 0) { fprintf(stderr, "fopen of tool_set_info failed: %d\n", errno); exit(2); } num_tools = dis_get_memory_ptr(addr); fprintf(toolfile, "There are 0x%02x tools using ptr at %06x\n", num_tools, addr); for(i = 1; i < num_tools; i++) { tool_addr = dis_get_memory_ptr(addr + 4*i); show_one_toolset(toolfile, i, tool_addr); } fclose(toolfile); } #ifndef TEST65 void do_gen_test(int got_num, int base_seed) { /* dummy */ } #endif void set_bp(word32 addr) { int count; printf("About to set BP at %06x\n", addr); count = g_num_breakpoints; if(count >= MAX_BREAK_POINTS) { printf("Too many (0x%02x) breakpoints set!\n", count); return; } g_breakpts[count] = addr; g_num_breakpoints = count + 1; fixup_brks(); } void show_bp() { int i; printf("Showing breakpoints set\n"); for(i = 0; i < g_num_breakpoints; i++) { printf("bp:%02x: %06x\n", i, g_breakpts[i]); } } void delete_bp(word32 addr) { int count; int hit; int i; printf("About to delete BP at %06x\n", addr); count = g_num_breakpoints; hit = -1; for(i = 0; i < count; i++) { if(g_breakpts[i] == addr) { hit = i; break; } } if(hit < 0) { printf("Breakpoint not found!\n"); } else { printf("Deleting brkpoint #0x%02x\n", hit); for(i = hit+1; i < count; i++) { g_breakpts[i-1] = g_breakpts[i]; } g_num_breakpoints = count - 1; setup_pageinfo(); } show_bp(); } void do_blank() { int tmp, i; switch(old_mode) { case 's': tmp = a2; if(tmp == 0) tmp = 1; enter_debug = 0; for(i = 0; i < tmp; i++) { g_stepping = 1; do_step(); if(enter_debug || halt_sim != 0) { if(halt_sim != HALT_EVENT) { break; } } } list_kpc = engine.kpc; /* video_update_through_line(262); */ break; case ':': set_memory_c(((a3bank << 16) + a3), a2, 0); a3++; mode = old_mode; break; case '.': case 0: xam_mem(-1); break; case ',': xam_mem(16); break; case '+': printf("%x\n", a1 + a2); break; case '-': printf("%x\n", a1 - a2); break; default: printf("Unknown mode at space: %d\n", old_mode); break; } } void do_go() { /* also called by do_step */ g_config_control_panel = 0; clear_halt(); run_prog(); show_regs(); g_config_control_panel = 1; } void do_step() { int size; int size_mem_imm, size_x_imm; do_go(); size_mem_imm = 2; if(engine.psr & 0x20) { size_mem_imm = 1; } size_x_imm = 2; if(engine.psr & 0x10) { size_x_imm = 1; } size = do_dis(stdout, engine.kpc, size_mem_imm, size_x_imm, 0, 0); } void xam_mem(int count) { show_hex_mem(a1bank, a1, a2bank, a2, count); a1 = a2 + 1; } void show_hex_mem(int startbank, word32 start, int endbank, word32 end, int count) { char ascii[MAXNUM_HEX_PER_LINE]; word32 i; int val, offset; if(count < 0) { count = 16 - (start & 0xf); } offset = 0; ascii[0] = 0; printf("Showing hex mem: bank: %x, start: %x, end: %x\n", startbank, start, end); for(i = start; i <= end; i++) { if( (i==start) || (count == 16) ) { printf("%04x:",i); } printf(" %02x", get_memory_c((startbank <<16) + i, 0)); val = get_memory_c((startbank << 16) + i, 0) & 0x7f; if(val < 32 || val >= 0x7f) { val = '.'; } ascii[offset++] = val; ascii[offset] = 0; count--; if(count <= 0) { printf(" %s\n", ascii); offset = 0; ascii[0] = 0; count = 16; } } if(offset > 0) { printf(" %s\n", ascii); } } int read_line(char *buf, int len) { int space_left; int ret; #ifndef _WIN32 int flags, flags_save; /* Unix */ flags = fcntl(0, F_GETFL, 0); flags_save = flags; if(flags == -1) { return 0; } ret = fcntl(0, F_SETFL, flags | O_NONBLOCK); if(ret == -1) { return 0; } #endif space_left = len; buf[0] = 0; ret = 0; while(space_left > 0) { #ifdef _WIN32 ret = win_nonblock_read_stdin(0, buf, 1); #else /* Unix */ ret = read(0, buf, 1); #endif if(ret <= 0) { micro_sleep(15.0/60.0); if(errno == EAGAIN) { /* it would block, so no chars--do update */ video_update(); ret = 0; continue; } printf("read ret %d, errno: %d\n", ret, errno); if(errno == EAGAIN || errno == EINTR) { ret = 0; continue; } break; } space_left -= ret; if(buf[ret-1] == 0x0a) { break; } buf = &buf[ret]; } #ifndef _WIN32 (void)fcntl(0, F_SETFL, flags_save); #endif return (len-space_left); } void do_debug_list() { int i; int size; int size_mem_imm, size_x_imm; if(got_num) { list_kpc = (a2bank << 16) + (a2 & 0xffff); } printf("%d=m %d=x %d=LCBANK\n", (engine.psr >> 5)&1, (engine.psr >> 4) & 1, (g_c068_statereg & 0x4) >> 2); size_mem_imm = 2; if(engine.psr & 0x20) { size_mem_imm = 1; } size_x_imm = 2; if(engine.psr & 0x10) { size_x_imm = 1; } for(i=0;i<20;i++) { size = do_dis(stdout, list_kpc, size_mem_imm, size_x_imm, 0, 0); list_kpc += size; } } void dis_do_memmove() { word32 val; printf("Memory move from %02x/%04x.%04x to %02x/%04x\n", a1bank, a1, a2, g_a4bank, g_a4); while(a1 <= (a2 & 0xffff)) { val = get_memory_c((a1bank << 16) + a1, 0); set_memory_c((g_a4bank << 16) + g_a4, val, 0); a1++; g_a4++; } a1 = a1 & 0xffff; g_a4 = g_a4 & 0xffff; } void dis_do_pattern_search() { printf("Memory pattern search for %04x in %02x/%04x.%04x\n", g_a4, a1bank, a1, a2); } void dis_do_compare() { word32 val1, val2; printf("Memory Compare from %02x/%04x.%04x with %02x/%04x\n", a1bank, a1, a2, g_a4bank, g_a4); while(a1 <= (a2 & 0xffff)) { val1 = get_memory_c((a1bank << 16) + a1, 0); val2 = get_memory_c((g_a4bank << 16) + g_a4, 0); if(val1 != val2) { printf("%02x/%04x: %02x vs %02x\n", a1bank, a1, val1, val2); } a1++; g_a4++; } a1 = a1 & 0xffff; g_a4 = g_a4 & 0xffff; } void do_debug_unix() { char localbuf[LINE_SIZE]; word32 offset, len; int fd, ret; int load, save; int i; load = 0; save = 0; switch(*line_ptr++) { case 'l': case 'L': printf("Loading.."); load = 1; break; case 's': case 'S': printf("Saving..."); save = 1; break; default: printf("Unknown unix command: %c\n", *(line_ptr-1)); *line_ptr = 0; return; } while(*line_ptr == ' ' || *line_ptr == '\t') { line_ptr++; } i = 0; while(i < LINE_SIZE) { localbuf[i++] = *line_ptr++; if(*line_ptr==' ' || *line_ptr=='\t' || *line_ptr == '\n') { break; } } localbuf[i] = 0; printf("About to open: %s,len: %d\n", localbuf, (int)strlen(localbuf)); if(load) { fd = open(localbuf,O_RDONLY | O_BINARY); } else { fd = open(localbuf,O_WRONLY | O_CREAT | O_BINARY, 0x1b6); } if(fd < 0) { printf("Open %s failed: %d\n", localbuf, fd); printf("errno: %d\n", errno); return; } if(load) { offset = a1 & 0xffff; len = 0x20000 - offset; } else { if(old_mode == '.') { len = a2 - a1 + 1; } else { len = 0x100; } } if(load) { if(a1bank >= 0xe0 && a1bank < 0xe2) { ret = read(fd,&g_slow_memory_ptr[((a1bank & 1)<<16)+a1],len); } else { ret = read(fd,&g_memory_ptr[(a1bank << 16) + a1],len); } } else { if(a1bank >= 0xe0 && a1bank < 0xe2) { ret = write(fd,&g_slow_memory_ptr[((a1bank & 1)<<16)+a1],len); } else { ret = write(fd,&g_memory_ptr[(a1bank << 16) + a1],len); } } printf("Read/write: addr %06x for %04x bytes, ret: %x bytes\n", (a1bank << 16) + a1, len, ret); if(ret < 0) { printf("errno: %d\n", errno); } a1 = a1 + ret; } void do_debug_load() { printf("Sorry, can't load now\n"); } int do_dis(FILE *outfile, word32 kpc, int accsize, int xsize, int op_provided, word32 instr) { char buffer[150]; const char *out; int args, type; int opcode; word32 val; word32 oldkpc; word32 dtype; int signed_val; oldkpc = kpc; if(op_provided) { opcode = (instr >> 24) & 0xff; } else { opcode = (int)get_memory_c(kpc, 0) & 0xff; } kpc++; dtype = disas_types[opcode]; out = disas_opcodes[opcode]; type = dtype & 0xff; args = dtype >> 8; if(args > 3) { if(args == 4) { args = accsize; } else if(args == 5) { args = xsize; } } val = -1; switch(args) { case 0: val = 0; break; case 1: if(op_provided) { val = instr & 0xff; } else { val = get_memory_c(kpc, 0); } break; case 2: if(op_provided) { val = instr & 0xffff; } else { val = get_memory16_c(kpc, 0); } break; case 3: if(op_provided) { val = instr & 0xffffff; } else { val = get_memory24_c(kpc, 0); } break; default: fprintf(stderr, "args out of rang: %d, opcode: %08x\n", args, opcode); break; } kpc += args; if(!op_provided) { instr = (opcode << 24) | (val & 0xffffff); } switch(type) { case ABS: if(args != 2) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t$%04x",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case ABSX: if(args != 2) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t$%04x,X",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case ABSY: if(args != 2) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t$%04x,Y",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case ABSLONG: if(args != 3) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t$%06x",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case ABSIND: if(args != 2) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t($%04x)",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case ABSXIND: if(args != 2) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t($%04x,X)",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case IMPLY: if(args != 0) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s",out); show_line(outfile, oldkpc,instr,args+1,buffer); break; case ACCUM: if(args != 0) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s",out); show_line(outfile, oldkpc,instr,args+1,buffer); break; case IMMED: if(args == 1) { sprintf(buffer,"%s\t#$%02x",out,val); } else if(args == 2) { sprintf(buffer,"%s\t#$%04x",out,val); } else { printf("arg # mismatch for opcode %x\n", opcode); } show_line(outfile, oldkpc,instr,args+1,buffer); break; case JUST8: if(args != 1) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t$%02x",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case DLOC: if(args != 1) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t$%02x",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case DLOCX: if(args != 1) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t$%02x,X",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case DLOCY: if(args != 1) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t$%02x,Y",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case LONG: if(args != 3) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t$%06x",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case LONGX: if(args != 3) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t$%06x,X",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case DLOCIND: if(args != 1) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t($%02x)",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case DLOCINDY: if(args != 1) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t($%02x),Y",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case DLOCXIND: if(args != 1) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t($%02x,X)",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case DLOCBRAK: if(args != 1) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t[$%02x]",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case DLOCBRAKY: if(args != 1) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t[$%02x],y",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; case DISP8: if(args != 1) { printf("arg # mismatch for opcode %x\n", opcode); } signed_val = (signed char)val; sprintf(buffer,"%s\t$%04x",out, (word32)(kpc+(signed_val)) & 0xffff); show_line(outfile, oldkpc,instr,args+1,buffer); break; case DISP8S: if(args != 1) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t$%02x,S",out,(word32)(byte)(val)); show_line(outfile, oldkpc,instr,args+1,buffer); break; case DISP8SINDY: if(args != 1) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t($%02x,S),Y",out,(word32)(byte)(val)); show_line(outfile, oldkpc,instr,args+1,buffer); break; case DISP16: if(args != 2) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t$%04x", out, (word32)(kpc+(signed)(word16)(val)) & 0xffff); show_line(outfile, oldkpc,instr,args+1,buffer); break; case MVPMVN: if(args != 2) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t$%02x,$%02x",out,val&0xff,val>>8); show_line(outfile, oldkpc,instr,args+1,buffer); break; case SEPVAL: case REPVAL: if(args != 1) { printf("arg # mismatch for opcode %x\n", opcode); } sprintf(buffer,"%s\t#$%02x",out,val); show_line(outfile, oldkpc,instr,args+1,buffer); break; default: printf("argument type: %d unexpected\n", type); break; } return(args+1); } void show_line(FILE *outfile, word32 kaddr, word32 operand, int size, char *string) { int i; int opcode; fprintf(outfile, "%02x/%04x: ", kaddr >> 16, kaddr & 0xffff); opcode = (operand >> 24) & 0xff; fprintf(outfile,"%02x ", opcode); for(i=1;i> 8; } for(;i<5;i++) { fprintf(outfile, " "); } fprintf(outfile,"%s\n", string); } void halt_printf(const char *fmt, ...) { va_list args; va_start(args, fmt); vprintf(fmt, args); va_end(args); set_halt(1); } void halt2_printf(const char *fmt, ...) { va_list args; va_start(args, fmt); vprintf(fmt, args); va_end(args); set_halt(2); }