153 lines
4.5 KiB
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);
|
|
}
|