#include #include #include #include #include #include static void check_special_addr(ubc_session_t *session, uint32_t address, int mode) { extern struct earlyterm earlyterm; const char *addrname; char line[128]; // Check address validity addrname = NULL; if ((mode & 1) != 0) addrname = disasm_check_peripheral(address); if (addrname == NULL && (mode & 2) != 0) addrname = disasm_check_syscalls(address); if (addrname == NULL) return; // Update vertical counter if needed if (session->menu.disassembly.print_offset.vertical != 0) session->menu.disassembly.print_offset.vertical += 1; // Generate and print line sprintf(line, "@note: 0x%.8x -> %s\n", address, addrname); dprint(&earlyterm.display, session->menu.disassembly.print_offset.horizontal, session->menu.disassembly.print_offset.vertical, line); // Update vertical counter session->menu.disassembly.print_offset.vertical += 1; } static uint32_t get_arg(ubc_session_t *session, uint16_t code, const struct opcode_s *opcode, int id) { extern struct earlyterm earlyterm; uint32_t argument; int shift; // Get arg shift. shift = -1; while (++shift < 16 && !(opcode->arg[id].mask & (0x01 << shift))); // Get arguments argument = (code & opcode->arg[id].mask) >> shift; // Call specific argument function if (opcode->arg[id].special != NULL) argument = (*opcode->arg[id].special)(session->context, argument); // Check special address and return check_special_addr(session, argument, 3); return (argument); } static void display_mnemonic(ubc_session_t *session) { extern struct earlyterm earlyterm; char line[128]; uint16_t *area; uint32_t sspc; uint32_t spc; int i; int j; // Get starting area. area = session->menu.disassembly.memory; // Main Loop. i = -1; spc = (uint32_t)area; sspc = session->context->spc; session->context->spc = (uint32_t)area; session->menu.disassembly.print_offset.vertical= 0; while ((int)session->menu.disassembly.print_offset.vertical < earlyterm.display.ws_row) { // Generate first part. i = i + 1; memset(line, 0x00, 128); check_special_addr(session, (uint32_t)&area[i], 2); sprintf(line, "%.8x %.4x ", (uint32_t)&area[i], area[i]); // Try to find opcode. j = -1; while (opcode_list[++j].name != NULL) { // Check opcode. if ((area[i] & opcode_list[j].mask) != opcode_list[j].code) continue; // Generate common line. sprintf(&line[14], opcode_list[j].name, get_arg(session, area[i], &opcode_list[j], 0), get_arg(session, area[i], &opcode_list[j], 1), get_arg(session, area[i], &opcode_list[j], 2) ); break; } // If no opcode are found, generate "empty" line. if (opcode_list[j].name == NULL) sprintf(&line[14], ".word 0x%.4x", area[i]); // Update internal context // TODO: update all registers (complet emulation ?) session->context->spc = session->context->spc + 2; // Display line dprint(&earlyterm.display, session->menu.disassembly.print_offset.horizontal, session->menu.disassembly.print_offset.vertical, line); // Highlight break line if needed. if ((uint32_t)&area[i] == sspc) { dreverse(&earlyterm.display, 0, session->menu.disassembly.print_offset.vertical * (earlyterm.display.font->font.height + 1), 128, earlyterm.display.font->font.height + 1); } if (session->menu.disassembly.next_break != sspc && (uint32_t)&area[i] == session->menu.disassembly.next_break) { drect(&earlyterm.display, 0, session->menu.disassembly.print_offset.vertical * (earlyterm.display.font->font.height + 1) - 1, 128, earlyterm.display.font->font.height + 1 ); } // Update vertical counter session->menu.disassembly.print_offset.vertical += 1; } // Restore saved SPC session->context->spc = sspc; } static void cursor_update(ubc_session_t *session) { // Horizontal update. if (session->key.left == 1) session->menu.disassembly.print_offset.horizontal += 1; if (session->key.right == 1) session->menu.disassembly.print_offset.horizontal -= 1; // Vertical update. if (session->key.up == 1) session->menu.disassembly.memory = &session->menu.disassembly.memory[-1]; if (session->key.down == 1) session->menu.disassembly.memory = &session->menu.disassembly.memory[1]; // Move break point if (session->key.plus == 1) session->menu.disassembly.next_break += 2; if (session->key.minus == 1) session->menu.disassembly.next_break -= 2; } void disasm_menu_disassembly(ubc_session_t *session) { extern struct earlyterm earlyterm; // Update cursor position. cursor_update(session); // display ASM. dclear(&earlyterm.display); display_mnemonic(session); screen_update(earlyterm.display.vram); }