Vhex-kernel/src/kernel/util/disasm/main.c

153 lines
4.5 KiB
C

#include <kernel/util/disasm.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/drivers/keyboard.h>
#include <kernel/hardware/ubc.h>
#include <kernel/hardware/ubc.h>
#include <kernel/bits/context.h>
#include <kernel/util/extra.h>
#include <kernel/util/casio.h>
#include <kernel/driver.h>
#include <string.h>
void disasm_main(void)
{
extern void casio_syscall_test(void);
// Setup Channel 0.
SH7305_UBC.CRR0.PCB = 1; // Set PC break adter instruction break.
SH7305_UBC.CRR0.BIE = 1; // Request a Break.
SH7305_UBC.CBR0.MFE = 0; // Enable Match Flag.
SH7305_UBC.CBR0.MFI = 0b000000; // Set UBC.CCMFR.MF0 = 1, when break occur.
SH7305_UBC.CBR0.AIE = 0; // Disable ASID check.
SH7305_UBC.CBR0.SZ = 0b010; // Disable Match condition.
SH7305_UBC.CBR0.CD = 0; // Use Operand Bus for Operand Access.
SH7305_UBC.CBR0.ID = 0b01; // Selecte instruction Fetch cycle.
SH7305_UBC.CBR0.RW = 0b11; // Use Read or Write for match condition.
SH7305_UBC.CBR0.CE = 0; // Disable Channel 0.
// Set up target address.
SH7305_UBC.CAR0 = (uint32_t)&casio_Bfile_ReadFile; // Tested programe address !
SH7305_UBC.CAMR0 = 0x00000000; // Address Mask.
// Setup Control register.
SH7305_UBC.CBCR.UBDE = 1; // Use DBR instead of VBR.
//@note:
// You *SHOULD* use `icbi` SH4 instruction
// After channel enable, otherwise the calculator
// will freeze.
SH7305_UBC.CBR0.CE = 1; // Enable Channel 0 !
icbi((void*)0xa0000000);
// Start disassembly
// TODO: thread !!
drivers_uninstall(0);
char buffer[128];
int handle = casio_Bfile_OpenFile(u"\\\\fls0\\vhex.g1a", 1);
earlyterm_write("handle -> %#x\n", handle);
DBG_WAIT;
DBG_WAIT;
DBG_WAIT;
casio_Bfile_ReadFile(handle, buffer, 128, 0);
casio_Bfile_CloseFile(handle);
drivers_install(0);
}
static void internal_GetKey(ubc_session_t *session, void (**menu)(ubc_session_t*))
{
keyscan_t keylist[KEYBOARD_NB_KEYS];
int i;
// Wipe key informations
session->key.entry = 0;
session->key.shift = 0;
session->key.left = 0;
session->key.right = 0;
session->key.up = 0;
session->key.down = 0;
session->key.optn = 0;
session->key.minus = 0;
session->key.plus = 0;
// Wait user interactions
keyboard_wait_event(keylist);
// Check all pressed keys
i = -1;
while (keylist[++i].keycode != KEY_UNUSED && i < KEYBOARD_NB_KEYS)
{
// Check key validity
if (!(keylist[i].counter == 1
|| (i == 0 && keylist[i].counter > 10 && (keylist[i].counter & 1) == 0)))
continue;
// Check special keys
switch (keylist[i].keycode)
{
case KEY_EXE: session->key.entry = 1; break;
case KEY_SHIFT: session->key.shift = 1; break;
case KEY_ALPHA: session->key.alpha = 1; break;
case KEY_OPTN: session->key.optn = 1; break;
case KEY_LEFT: session->key.left = 1; break;
case KEY_RIGHT: session->key.right = 1; break;
case KEY_UP: session->key.up = 1; break;
case KEY_DOWN: session->key.down = 1; break;
case KEY_PLUS: session->key.plus = 1; break;
case KEY_MINUS: session->key.minus = 1; break;
case KEY_F1: *menu = &disasm_menu_disassembly; break;
case KEY_F2: *menu = &disasm_menu_show_context; break;
case KEY_MENU: casio_return_menu(0); break;
}
}
}
void ubc_handler(struct cpu_context *context, int channel)
{
extern struct earlyterm earlyterm;
void (*menu)(ubc_session_t *session);
ubc_session_t session;
// Initialize new session.
session.key.entry = 0;
session.key.shift = 0;
session.key.left = 0;
session.key.right = 0;
session.key.up = 0;
session.key.minus = 0;
session.key.plus = 0;
session.key.optn = 0;
session.channel = channel;
session.context = context;
session.menu.context.cursor = 0;
// Initialize disassembly menu
session.menu.disassembly.memory = (void *)(ptrdiff_t)context->spc;
session.menu.disassembly.memory = &session.menu.disassembly.memory[-earlyterm.display.ws_row / 2];
session.menu.disassembly.print_offset.horizontal = -4;
session.menu.disassembly.print_offset.vertical = 0;
session.menu.disassembly.next_break = context->spc;
session.menu.disassembly.next_instruction = 0x00000000;
// Main loop.
menu = &disasm_menu_disassembly;
while (session.key.entry == 0 && session.key.optn == 0)
{
menu(&session);
internal_GetKey(&session, &menu);
}
// Workaround for skip instruction
if (session.key.optn == 1) {
session.context->spc = session.menu.disassembly.next_break;
}
// Update UBC
SH7305_UBC.CAR0 = session.menu.disassembly.next_break; // Update break address.
SH7305_UBC.CAMR0 = 0x00000000; // Update break address.
SH7305_UBC.CBR0.CE = 1; // Enable channel.
icbi((void*)0xa0000000);
}