Add UBC driver + GUI pseudo-interface + disassembler menu (initial commit)

This commit is contained in:
Yatis 2021-02-18 17:22:15 +01:00
commit 01c9805e00
22 changed files with 6415 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build-*

208
Makefile Normal file
View File

@ -0,0 +1,208 @@
#! /usr/bin/make -f
# Default Makefile for fxSDK add-ins. This file was probably copied there by
# the [fxsdk] program.
#---
#
# Configuration
#
include project.cfg
# Compiler flags
CFLAGSFX = $(CFLAGS) $(CFLAGS_FX) $(INCLUDE_FX)
CFLAGSCG = $(CFLAGS) $(CFLAGS_CG) $(INCLUDE_CG)
# Linker flags
LDFLAGSFX := $(LDFLAGS) $(LDFLAGS_FX)
LDFLAGSCG := $(LDFLAGS) $(LDFLAGS_CG)
# Dependency list generation flags
depflags = -MMD -MT $@ -MF $(@:.o=.d) -MP
# ELF to binary flags
BINFLAGS := -R .bss -R .gint_bss
# G1A and G3A generation flags
NAME_G1A ?= $(NAME)
NAME_G3A ?= $(NAME)
G1AF := -i "$(ICON_FX)" -n "$(NAME_G1A)" --internal="$(INTERNAL)"
G3AF := -n basic:"$(NAME_G3A)" -i uns:"$(ICON_CG_UNS)" -i sel:"$(ICON_CG_SEL)"
ifeq "$(TOOLCHAIN_FX)" ""
TOOLCHAIN_FX := sh3eb-elf
endif
ifeq "$(TOOLCHAIN_CG)" ""
TOOLCHAIN_CG := sh4eb-elf
endif
# fxconv flags
FXCONVFX := --fx --toolchain=$(TOOLCHAIN_FX)
FXCONVCG := --cg --toolchain=$(TOOLCHAIN_CG)
# Determine the compiler install and include path
GCC_BASE_FX := $(shell $(TOOLCHAIN_FX)-gcc --print-search-dirs | grep install | sed 's/install: //')
GCC_BASE_CG := $(shell $(TOOLCHAIN_CG)-gcc --print-search-dirs | grep install | sed 's/install: //')
GCC_INCLUDE_FX := $(GCC_BASE_FX)/include
GCC_INCLUDE_CG := $(GCC_BASE_CG)/include
#
# File listings
#
NULL :=
TARGET := $(subst $(NULL) $(NULL),-,$(NAME))
ifeq "$(TARGET_FX)" ""
TARGET_FX := $(TARGET).g1a
endif
ifeq "$(TARGET_CG)" ""
TARGET_CG := $(TARGET).g3a
endif
ELF_FX := build-fx/$(shell basename "$(TARGET_FX)" .g1a).elf
BIN_FX := $(ELF_FX:.elf=.bin)
ELF_CG := build-cg/$(shell basename "$(TARGET_CG)" .g3a).elf
BIN_CG := $(ELF_CG:.elf=.bin)
# Source files
src := $(wildcard src/*.[csS] \
src/*/*.[csS] \
src/*/*/*.[csS] \
src/*/*/*/*.[csS])
assets-fx := $(wildcard assets-fx/*/*)
assets-cg := $(wildcard assets-cg/*/*)
# Object files
obj-fx := $(src:%=build-fx/%.o) \
$(assets-fx:assets-fx/%=build-fx/assets/%.o)
obj-cg := $(src:%=build-cg/%.o) \
$(assets-cg:assets-cg/%=build-cg/assets/%.o)
# Additional dependencies
deps-fx := $(ICON_FX)
deps-cg := $(ICON_CG_UNS) $(ICON_CG_SEL)
# All targets
all :=
ifneq "$(wildcard build-fx)" ""
all += all-fx
endif
ifneq "$(wildcard build-cg)" ""
all += all-cg
endif
#
# Build rules
#
all: $(all)
all-fx: $(TARGET_FX)
all-cg: $(TARGET_CG)
$(TARGET_FX): $(obj-fx) $(deps-fx)
@ mkdir -p $(dir $@)
$(TOOLCHAIN_FX)-gcc -o $(ELF_FX) $(obj-fx) $(CFLAGSFX) $(LDFLAGSFX)
$(TOOLCHAIN_FX)-objcopy -O binary $(BINFLAGS) $(ELF_FX) $(BIN_FX)
fxg1a $(BIN_FX) -o $@ $(G1AF)
$(TARGET_CG): $(obj-cg) $(deps-cg)
@ mkdir -p $(dir $@)
$(TOOLCHAIN_CG)-gcc -o $(ELF_CG) $(obj-cg) $(CFLAGSCG) $(LDFLAGSCG)
$(TOOLCHAIN_CG)-objcopy -O binary $(BINFLAGS) $(ELF_CG) $(BIN_CG)
mkg3a $(G3AF) $(BIN_CG) $@
# C sources
build-fx/%.c.o: %.c
@ mkdir -p $(dir $@)
$(TOOLCHAIN_FX)-gcc -c $< -o $@ $(CFLAGSFX) $(depflags)
build-cg/%.c.o: %.c
@ mkdir -p $(dir $@)
$(TOOLCHAIN_CG)-gcc -c $< -o $@ $(CFLAGSCG) $(depflags)
# Assembler sources
build-fx/%.s.o: %.s
@ mkdir -p $(dir $@)
$(TOOLCHAIN_FX)-gcc -c $< -o $@
build-cg/%.s.o: %.s
@ mkdir -p $(dir $@)
$(TOOLCHAIN_CG)-gcc -c $< -o $@
# Preprocessed assembler sources
build-fx/%.S.o: %.S
@ mkdir -p $(dir $@)
$(TOOLCHAIN_FX)-gcc -c $< -o $@ $(INCLUDE_FX)
build-cg/%.S.o: %.S
@ mkdir -p $(dir $@)
$(TOOLCHAIN_CG)-gcc -c $< -o $@ $(INCLUDE_CG)
# Images
build-fx/assets/img/%.o: assets-fx/img/%
@ mkdir -p $(dir $@)
fxconv --bopti-image $< -o $@ $(FXCONVFX) name:img_$(basename $*) $(IMG.$*)
build-cg/assets/img/%.o: assets-cg/img/%
@ mkdir -p $(dir $@)
fxconv --bopti-image $< -o $@ $(FXCONVCG) name:img_$(basename $*) $(IMG.$*)
# Fonts
build-fx/assets/fonts/%.o: assets-fx/fonts/%
@ mkdir -p $(dir $@)
fxconv -f $< -o $@ $(FXCONVFX) name:font_$(basename $*) $(FONT.$*)
build-cg/assets/fonts/%.o: assets-cg/fonts/%
@ mkdir -p $(dir $@)
fxconv -f $< -o $@ $(FXCONVCG) name:font_$(basename $*) $(FONT.$*)
# Binaries
build-fx/assets/bin/%.o: assets-fx/bin/%
@ mkdir -p $(dir $@)
fxconv -b $< -o $@ $(FXCONVFX) name:bin_$(basename $*) $(BIN.$*)
build-cg/assets/bin/%.o: assets-cg/bin/%
@ mkdir -p $(dir $@)
fxconv -b $< -o $@ $(FXCONVCG) name:bin_$(basename $*) $(BIN.$*)
# Custom conversions
build-fx/assets/%.o: assets-fx/%
@ mkdir -p $(dir $@)
fxconv --custom $< -o $@ $(FXCONVFX) type:$(subst /,,$(dir $*)) name:$(subst /,_,$(basename $*))
build-cg/assets/%.o: assets-cg/%
@ mkdir -p $(dir $@)
fxconv --custom $< -o $@ $(FXCONVCG) type:$(subst /,,$(dir $*)) name:$(subst /,_,$(basename $*))
#
# Cleaning and utilities
#
# Dependency information
-include $(shell find build* -name *.d 2> /dev/null)
build-fx/%.d: ;
build-cg/%.d: ;
.PRECIOUS: build-fx build-cg build-fx/%.d build-cg/%.d %/
clean-fx:
@ rm -rf build-fx/
clean-cg:
@ rm -rf build-cg/
distclean-fx: clean-fx
@ rm -f $(TARGET_FX)
distclean-cg: clean-cg
@ rm -f $(TARGET_CG)
clean: clean-fx clean-cg
distclean: distclean-fx distclean-cg
install-fx: $(TARGET_FX)
p7 send -f $<
install-cg: $(TARGET_CG)
@ while [[ ! -h /dev/Prizm1 ]]; do sleep 0.25; done
@ while ! mount /dev/Prizm1; do sleep 0.25; done
@ rm -f /mnt/prizm/$<
@ cp $< /mnt/prizm
@ umount /dev/Prizm1
@- eject /dev/Prizm1
.PHONY: all all-fx all-cg clean distclean install-fx install-cg

BIN
assets-cg/icon-cg-sel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
assets-cg/icon-cg-uns.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
assets-fx/icon-fx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
gintrace.g3a Normal file

Binary file not shown.

View File

@ -0,0 +1,16 @@
#ifndef __GINTRACE_GUI_FKEY_H__
# define __GINTRACE_GUI_FKEY_H__
#include <stddef.h>
#include <stdint.h>
/* fkey_action(): A black-on-white F-key */
extern void fkey_action(int position, char const *text);
/* fkey_button(): A rectangular F-key */
extern void fkey_button(int position, char const *text);
/* fkey_menu(): A rectangular F-key with the bottom right corner removed */
extern void fkey_menu(int position, char const *text);
#endif /*__GINTRACE_GUI_FKEY_H__*/

View File

@ -0,0 +1,66 @@
#ifndef __GINTRACE_MENU_H__
# define __GINTRACE_MENU_H__
#include <stddef.h>
#include <stdint.h>
#include "gintrace/ubc.h"
/* define menu information */
struct menu {
void (*ctor)(void);
void (*init)(struct ucontext *ctx);
void (*display)(struct ucontext *ctx);
int (*keyboard)(struct ucontext *ctx, int key);
void (*command)(struct ucontext *ctx, int argc, char **argv);
void (*dtor)(void);
};
/* menu group information */
struct menu_group {
int is_open;
int menu_page;
int menu_counter;
struct menu *selected;
struct menu_list {
const char *name;
struct menu *menu;
struct menu_list *next;
} *list;
volatile void *arg;
};
//---
// User API
//---
enum {
menu_retval_success = 0,
menu_retval_enomem = -1,
menu_retval_efault = -2,
menu_retval_already_registered = -3,
menu_retval_unregistered = -4,
};
/* menu_create(): Create a group of menus */
extern int menu_create(struct menu_group **gmenu);
/* menu_register(): Register a new menu to the internal menu table */
extern int menu_register(struct menu_group *gmenus,
struct menu *menu, const char *name);
/* menu_unregister(): Unregister menu */
extern int menu_unregister(struct menu_group *gmenus, const char *name);
/* menu_is_open(): Return the menu status */
extern int menu_is_open(struct menu_group *gmenu);
/* menu_init(): Initialize all menu */
extern int menu_init(struct menu_group *gmenus, volatile void *arg);
/* menu_draw(): Draw menu specific information and menu abstraction overlay */
extern int menu_draw(struct menu_group *gmenus);
/* menu_keyboard(): handle keyboard event */
extern int menu_keyboard(struct menu_group *gmenu);
#endif /*__GINTRACE_MENU_H__*/

View File

@ -0,0 +1,61 @@
#ifndef __GINTRACE_TRACER_H__
# define __GINTRACE_TRACER_H__
#include <stddef.h>
#include <stdint.h>
#include "gintrace/ubc.h"
#include "gintrace/gui/menu.h"
#include <gint/defs/types.h>
#include <gint/display.h>
/* define font information */
#ifdef FXCG50
#define FWIDTH 8
#define FHEIGHT 9
#endif
#ifdef FX9860G
#define FWIDTH 5
#define FHEIGHT 7
#endif
/* define display information */
#define DISASM_NB_COLUMN (DWIDTH / (FWIDTH + 1))
#define DISASM_NB_ROW (DHEIGHT / (FHEIGHT + 1))
/* tracer: internal information used to display disassembly view */
struct tracer {
/* circular buffer information.
* Note that the circular buffer is very special, it refert, on the
* first level, the "instruction address" then, the second level its
* instruction note and mnemonic.
*
* TODO: doc */
struct {
char ***raw;
struct {
size_t width;
size_t height;
} size;
off_t cursor;
uint16_t *anchor;
} buffer;
/* display offset */
struct {
int hoffset;
int voffset;
} disp;
/* memory information */
uint16_t *memory;
uintptr_t next_break;
uintptr_t next_instruction;
uintptr_t spc;
};
/* extern menu information */
extern struct menu menu_disasm;
#endif /*__GINTRACE_TRACER_H__*/

165
include/gintrace/ubc.h Normal file
View File

@ -0,0 +1,165 @@
#ifndef __GINTRACE_UBC_H__
# define __GINTRACE_UBC_H__
#include <stddef.h>
#include <stdint.h>
#include <gint/defs/types.h>
//---
// Hardware information - Same as the SH7724
//---
#define SH7305_UBC (*(volatile struct sh7305_ubc *)0xff200000)
struct sh7305_ubc {
//---
// Channel 0
//---
lword_union(CBR0,
uint32_t MFE : 1; /* Match Flag Enable */
uint32_t AIE : 1; /* ASID Enable */
uint32_t MFI : 6; /* Match Flag Specify */
uint32_t AIV : 8; /* ASID Specify */
uint32_t const : 1; /* All 0 */
uint32_t SZ : 3; /* Operend Size Select */
uint32_t const : 4; /* All 0 */
uint32_t CD : 2; /* Bus Select */
uint32_t ID : 2; /* Instr Fetch/Operand Access Select */
uint32_t const : 1; /* All 0 */
uint32_t RW : 2; /* Bus Command Select */
uint32_t CE : 1; /* Channel Enable */
);
lword_union(CRR0,
uint32_t const : 18; /* All 0 */
uint32_t const : 1; /* All 1 */
uint32_t const : 11; /* All 0 */
uint32_t PCB : 1; /* PC Breack Select */
uint32_t BIE : 1; /* Breack Enable */
);
uint32_t CAR0; /* Compare Address */
uint32_t CAMR0; /* Compare Address Mask */
pad(0x10);
//---
// Channel 1
//---
lword_union(CBR1,
uint32_t MFE : 1; /* Match Flag Enable */
uint32_t AIE : 1; /* ASID Enable */
uint32_t MFI : 6; /* Match Flag Specify */
uint32_t AIV : 8; /* ASID Specify */
uint32_t DBE : 1; /* Data Value Enable */
uint32_t SZ : 3; /* Operend Size Select */
uint32_t ETBE : 1; /* Execution Count Value Enable */
uint32_t const : 3; /* All 0 */
uint32_t CD : 2; /* Bus Select */
uint32_t ID : 2; /* Instr Fetch/Operand Access Select */
uint32_t const : 1; /* All 0 */
uint32_t RW : 2; /* Bus Command Select */
uint32_t CE : 1; /* Channel Enable */
);
lword_union(CRR1,
uint32_t const : 18; /* All 0 */
uint32_t const : 1; /* All 1 */
uint32_t const : 11; /* All 0 */
uint32_t PCB : 1; /* PC Breack Select */
uint32_t BIE : 1; /* Breack Enable */
);
uint32_t CAR1; /* Compare Address */
uint32_t CAMR1; /* Compare Address Mask */
//--
// Compare Data Part.
//---
uint32_t CDR1; /* Compare Data Value */
uint32_t CDMR1; /* Compare Data Value Mask */
//---
// Execution Count Register
//---
lword_union(CETR1,
uint32_t const : 20; /* All 0 */
uint32_t CET : 12; /* Execution Count */
);
pad(0x5c4);
//---
// Channel Match Flag Register
//---
lword_union(CCMFR,
uint32_t const : 30; /* All 0 */
uint32_t MF1 : 1; /* Channel 1 Condition Match Flag */
uint32_t MF0 : 1; /* Channel 0 Condition Match Flag */
);
pad(0x1c);
//---
// Control Register
//---
lword_union(CBCR,
uint32_t const : 31; /* All 0 */
uint32_t UBDE : 1; /* UBC Debugging Support Enable */
);
};
/* hardware context */
struct sh7305_ubc_context {
uint32_t cbr0;
uint32_t crr0;
uint32_t car0;
uint32_t camr0;
uint32_t cbr1;
uint32_t crr1;
uint32_t car1;
uint32_t camr1;
uint32_t cdr1;
uint32_t cdmr1;
uint32_t cetr1;
uint32_t ccmfr;
uint32_t cbr;
};
//---
// Software information
//---
/* ucontext: UBC context */
struct ucontext {
uint32_t reg[16];
uint32_t gbr;
uint32_t macl;
uint32_t mach;
uint32_t ssr;
uint32_t spc;
uint32_t pr;
};
//---
// User API
//---
/* ub_install(): Install UBC driver */
extern void ubc_install(void);
extern void ubc_uninstall(void);
/* ubc_set_handler(): Setup the handler */
extern int ubc_set_handler(void (*handler)(struct ucontext *ctx));
/* ubc_set_breakpoint(): Setup one breakpoint */
extern int ubc_set_breakpoint(int channel, void *address, void *mask);
//---
// "low-level" interface
//---
/* ubc_kernel_dbr_set(): Switch DBR register */
extern void *ubc_kernel_dbr_set(void *dbr);
/* ubc_kernel_inth: Content the relocalised UBC interrupt handler */
extern void (*ubc_kernel_inth)(void);
/* ubc_kernel_update(): Perform a cache reset */
extern void ubc_kernel_update(void);
#endif /*__GINTRACE_UBC_H__*/

88
project.cfg Normal file
View File

@ -0,0 +1,88 @@
#---
# fxSDK project configuration file for GINTRACE
#---
# Project name, should be at most 8 bytes long.
# (You can also specify NAME_G1A or NAME_G3A to override individually.)
NAME := gintrace
# Internal name, should be '@' followed by at most 7 uppercase letters.
# WARNING: If this convention is not followed, the add-in might not appear in
# the main menu of the calculator!
INTERNAL := @GTRACE
# Output file name. The default is to take <NAME>, replace spaces with dashes,
# and add .g1a (or .g3a). You can specify a different folder if you want.
TARGET_FX :=
TARGET_CG :=
# fx-9860G icon location
ICON_FX = assets-fx/icon-fx.png
# fx-CG 50 icon locations
ICON_CG_UNS = assets-cg/icon-cg-uns.png
ICON_CG_SEL = assets-cg/icon-cg-sel.png
#---
# Toolchain selection
#---
# Toolchain for fx9860g. Please see also CFLAGS_FX below.
TOOLCHAIN_FX := sh-elf
# Toolchain for fxcg50. Please see also CFLAGS_CG below.
TOOLCHAIN_CG := sh-elf
#---
# Compiler flags
#---
# Base compiler flags for the fxSDK, you usually want to keep these.
CFLAGS := -mb -ffreestanding -nostdlib -fstrict-volatile-bitfields
# Platform-specific compiler flags.
# <> If you are using sh3eb-elf, use -m3. (You can do this on both FX and CG.)
# <> If you are using sh4eb-elf, use -m4-nofpu. (Not ideal on FX but works.)
# <> If you are using sh4eb-nofpu-elf, then your compiler will likely use the
# FPU and cause problems on the calculator. Consider another configuration.
# <> If you are using an sh-elf with several targets, specify whichever you
# support. I recommend -m3 on FX and -m4-nofpu on CG.
# Please see also TOOLCHAIN_FX and TOOLCHAIN_CG above.
CFLAGS_FX := -D FX9860G -m3
CFLAGS_CG := -D FXCG50 -m4-nofpu
# Additional compiler flags, change to your own taste!
CFLAGS += -Wall -Wextra -Wno-missing-field-initializers -Os
# Include paths. Add one -I option for each folder from which you want to
# be able to include files with #include<>. The Makefile provides a variable
# GCC_INCLUDE_FX/GCC_INCLUDE_CG that represents the default include folder,
# which is useful for some libraries such as OpenLibm.
INCLUDE_FX = -I include -I .
INCLUDE_CG = -I include -I .
# Libraries. Add one -l option for each library you are using, and also
# suitable -L options if you have library files in custom folders. To use
# fxlib, add libfx.a to the project directory and use "-L . -lfx".
LIBS_FX :=
LIBS_CG :=
# Base linker flags for the fxSDK, you usually want to keep these.
LDFLAGS_FX := -T fx9860g.ld -lgint-fx $(LIBS_FX) -lgint-fx -lgcc
LDFLAGS_CG := -T fxcg50.ld -lgint-cg $(LIBS_CG) -lgint-cg -lgcc
# Additional linker flags, if you need any.
LDFLAGS :=
# Additional platform-specific linker flags.
LDFLAGS_FX += -Wl,-Map=build-fx/map
LDFLAGS_CG += -Wl,-Map=build-cg/map
#---
# File conversion parameters
#---
# Here you can add fxconv options for each converted file, individually.
# The syntax is "<type>.<file>". For example, to specify the parameters for a
# font named "hexa.png", you might write:
#
# FONT.hexa.png = charset:print grid.size:3x5 grid.padding:1

47
src/gint.c Normal file
View File

@ -0,0 +1,47 @@
#include "gintrace/ubc.h"
#include <gint/gint.h>
#include <gint/atomic.h>
#include <gint/defs/attributes.h>
#include <gint/drivers.h>
/* external symbols */
extern void *kernel_env_casio;
extern void *kernel_env_gint;
/* gint_switch(): Temporarily switch out of gint */
void gint_switch(void (*function)(void))
{
/* Switch from gint to the OS after a short wait */
ubc_uninstall();
drivers_wait();
drivers_switch(kernel_env_gint, kernel_env_casio);
ubc_install();
if(function != NULL)
function();
/* then switch back to gint once the os finishes working */
ubc_uninstall();
drivers_wait();
drivers_switch(kernel_env_casio, kernel_env_gint);
ubc_install();
}
/* Switch from gint to the OS after a short wait */
void gint_switch_to_casio(void)
{
ubc_uninstall();
drivers_wait();
drivers_switch(kernel_env_gint, kernel_env_casio);
ubc_install();
}
/* Switch from gint to the OS after a short wait */
void gint_switch_to_gint(void)
{
ubc_uninstall();
drivers_wait();
drivers_switch(kernel_env_casio, kernel_env_gint);
ubc_install();
}

52
src/gui/fkey.c Normal file
View File

@ -0,0 +1,52 @@
#include "gintrace/gui/fkey.h"
#include <gint/display.h>
/* fkey_action(): A black-on-white F-key */
void fkey_action(int position, char const *text)
{
int width;
dsize(text, NULL, &width, NULL);
int x = 4 + 65 * (position - 1);
int y = 207;
int w = 63;
dline(x + 1, y, x + w - 2, y, C_BLACK);
dline(x + 1, y + 14, x + w - 2, y + 14, C_BLACK);
drect(x, y + 1, x + 1, y + 13, C_BLACK);
drect(x + w - 2, y + 1, x + w - 1, y + 13, C_BLACK);
dtext(x + ((w - width) >> 1), y + 3, C_BLACK, text);
}
/* fkey_button(): A rectangular F-key */
void fkey_button(int position, char const *text)
{
int width;
dsize(text, NULL, &width, NULL);
int x = 4 + 65 * (position - 1);
int y = 207;
int w = 63;
dline(x + 1, y, x + w - 2, y, C_BLACK);
dline(x + 1, y + 14, x + w - 2, y + 14, C_BLACK);
drect(x, y + 1, x + w - 1, y + 13, C_BLACK);
dtext(x + ((w - width) >> 1), y + 3, C_WHITE, text);
}
/* fkey_menu(): A rectangular F-key with the bottom right corner removed */
void fkey_menu(int position, char const *text)
{
int x = 4 + 65 * (position - 1);
int y = 207;
int w = 63;
fkey_button(position, text);
dline(x + w - 1, y + 10, x + w - 5, y + 14, C_WHITE);
dline(x + w - 1, y + 11, x + w - 4, y + 14, C_WHITE);
dline(x + w - 1, y + 12, x + w - 3, y + 14, C_WHITE);
dline(x + w - 1, y + 13, x + w - 2, y + 14, C_WHITE);
}

176
src/gui/menu.c Normal file
View File

@ -0,0 +1,176 @@
//---
// gintrace:menu - Menu helper
//---
#include "gintrace/gui/menu.h"
#include "gintrace/gui/fkey.h"
#include <gint/std/string.h>
#include <gint/std/stdlib.h>
#include <gint/keyboard.h>
#include <gint/display.h>
/* menu_create(): Create a group of menus */
int menu_create(struct menu_group **gmenu)
{
*gmenu = calloc(sizeof(struct menu_group), 1);
if (*gmenu == NULL)
return (menu_retval_enomem);
return (menu_retval_success);
}
/* menu_register(): Register a new menu to the internal menu table */
int menu_register(struct menu_group *gmenu,
struct menu *menu, const char *name)
{
struct menu_list **node;
if (gmenu == NULL || name == NULL)
return (menu_retval_efault);
node = &gmenu->list;
while (*node != NULL) {
if (strcmp((*node)->name, name) == 0)
return (menu_retval_already_registered);
node = &(*node)->next;
}
*node = calloc(sizeof(struct menu_list), 1);
if (*node == NULL)
return (menu_retval_enomem);
if (menu != NULL && menu->ctor != NULL)
menu->ctor();
if (gmenu->selected == NULL)
gmenu->selected = menu;
(*node)->menu = menu;
(*node)->name = name;
gmenu->menu_counter += 1;
return (menu_retval_success);
}
/* menu_unregister(): Unregister menu */
int menu_unregister(struct menu_group *gmenu, const char *name)
{
struct menu_list **node;
void *tmp;
if (gmenu == NULL || name == NULL)
return (menu_retval_efault);
node = &gmenu->list;
while (*node != NULL) {
if (strcmp((*node)->name, name) != 0) {
node = &(*node)->next;
continue;
}
tmp = *node;
*node = (*node)->next;
free(tmp);
return (menu_retval_success);
}
gmenu->menu_counter -= 1;
return (menu_retval_unregistered);
}
/* menu_init(): Initialize all menu */
int menu_init(struct menu_group *gmenu, volatile void *arg)
{
struct menu_list *node;
if (gmenu == NULL)
return (menu_retval_efault);
node = gmenu->list;
while (node != NULL) {
if (node->menu != NULL && node->menu->init != NULL)
node->menu->init((void*)arg);
node = node->next;
}
gmenu->arg = arg;
gmenu->is_open = 0;
return (menu_retval_success);
}
/* menu_is_open(): Return the menu status */
int menu_is_open(struct menu_group *gmenu)
{
if (gmenu == NULL)
return (menu_retval_efault);
return (gmenu->is_open != 0);
}
/* menu_draw(): Draw menu specific information and menu abstraction overlay */
int menu_draw(struct menu_group *gmenu)
{
struct menu_list *node;
int offset;
int counter;
if (gmenu == NULL)
return (menu_retval_efault);
dclear(C_WHITE);
if (gmenu->selected != NULL && gmenu->selected->display != NULL)
gmenu->selected->display((void*)gmenu->arg);
counter = 0;
node = gmenu->list;
offset = gmenu->menu_page * 5;
while (node != NULL) {
if (gmenu->menu_counter <= 6) {
fkey_menu(1 + counter, node->name);
counter += 1;
node = node->next;
continue;
}
if (counter - offset >= 5)
break;
if (counter - offset >= 0)
fkey_menu(1 + (counter - offset), node->name);
node = node->next;
counter += 1;
}
if (gmenu->menu_counter >= 7)
fkey_action(6, ">");
dupdate();
return (menu_retval_success);
}
/* menu_keyboard(): handle keyboard event */
int menu_keyboard(struct menu_group *gmenu)
{
const int keylist[] = {KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6};
struct menu_list *node;
int counter;
int target;
int key;
if (gmenu == NULL)
return (menu_retval_efault);
key = getkey().key;
if (key == KEY_EXIT) {
gmenu->is_open = 1;
return (menu_retval_success);
}
for (int i = 0; i < 6; ++i) {
if (keylist[i] != key)
continue;
if (key == KEY_F6 && gmenu->menu_counter >= 7) {
gmenu->menu_page += 1;
if (gmenu->menu_page * 5 >= gmenu->menu_counter)
gmenu->menu_page = 0;
return (0);
}
counter = 0;
target = (gmenu->menu_page * 5) + i;
node = gmenu->list;
while (node != NULL) {
if (counter == target) {
gmenu->selected = node->menu;
return (menu_retval_success);
}
counter += 1;
node = node->next;
}
return (menu_retval_success);
}
if (gmenu->selected == NULL || gmenu->selected->keyboard == NULL)
return (menu_retval_success);
if (gmenu->selected->keyboard((void*)gmenu->arg, key) != 0)
gmenu->is_open = 1;
return (menu_retval_success);
}

45
src/main.c Normal file
View File

@ -0,0 +1,45 @@
#include "gintrace/gui/menu.h"
#include "gintrace/menu/disasm.h"
#include "gintrace/ubc.h"
#include <gint/gint.h>
#include <gint/keyboard.h>
#include <gint/display.h>
/* save the selected menu */
static struct menu_group *gmenu = NULL;
/* gintrac_handler(): UBC handler */
static void gintrace_handler(struct ucontext *context)
{
gint_switch_to_gint();
menu_init(gmenu, context);
while (menu_is_open(gmenu) == 0) {
menu_draw(gmenu);
menu_keyboard(gmenu);
}
gint_switch_to_casio();
}
int main(void)
{
/* initialize all internal menu and get the "first" menu to display */
menu_create(&gmenu);
menu_register(gmenu, &menu_disasm, "Disasm");
menu_register(gmenu, NULL, "Context");
menu_register(gmenu, NULL, "Hexdump");
menu_register(gmenu, NULL, "TLB");
menu_register(gmenu, NULL, "CallG");
menu_register(gmenu, NULL, "BBBBB");
/* intialize UBC information */
ubc_install();
ubc_set_handler(&gintrace_handler);
ubc_set_breakpoint(0, (void*)0x80358a6c, NULL);
/* try to trace the function */
gint_switch((void *)0x80358a6c);
//TODO : destructor part !!
return (0);
}

View File

@ -0,0 +1,92 @@
#ifndef _SRC_MENU_DISASSEMBLER_DICTIONARY_H__
# define _SRC_MENU_DISASSEMBLER_DICTIONARY_H__
#include <stddef.h>
#include <stdint.h>
//---
// Internal data information
//---
/* Define the number max of arguments for intrustions. */
#define OPCODE_ARGUMENTS_MAX 3
/* Arguments information
* 0b0000x -> argument special enable
* 0bxxxx0 -> special action ID
*
* Info organisations
* 0b*[s000][s000][s000]xxx -> xxx = arg status
* act2 act1 act0 -> s = 1) signed, 0) unsigned */
#define __ARG_SIGN_SET(arg, sign) ((sign & 1) << (3 + 3 + (arg << 2)))
#define __ARG_ACTION_SET(arg, action) ((action & 0b111) << (3 + (arg << 2)))
#define __ARG_STATUS_SET(arg) (1 << arg)
/* Opcode information help */
#define OPCODE_INFO_IS_SIGNED(info, arg) \
(info & __ARG_SIGN_SET(arg, 1))
#define OPCODE_INFO_IS_SET(info, arg) \
(info & __ARG_STATUS_SET(arg))
#define OPCODE_INFO_GET_ACTION(info, arg) \
((info >> (3 + (arg << 2))) & 0b0111)
#define OPCODE_INFO_SET(arg, action, sign) \
( __ARG_SIGN_SET(arg, sign) \
| __ARG_ACTION_SET(arg, action) \
| __ARG_STATUS_SET(arg))
/* Opcode registers information */
#define OPCODE_ARG_0 0b000
#define OPCODE_ARG_1 0b001
#define OPCODE_ARG_2 0b010
#define OPCODE_ARG_SIGNED 0b1
#define OPCODE_ARG_UNSIGNED 0b0
/* Opcode actions information */
#define OPCODE_ACTION_INST_LONG 0b0000
#define OPCODE_ACTION_INST_WORD 0b0001
#define OPCODE_ACTION_PC_LONG 0b0010
#define OPCODE_ACTION_PC_WORD 0b0011
#define OPCODE_ACTION_DISP_LONG 0b0100
#define OPCODE_ACTION_DISP_WORD 0b0101
/* opcode - internal instruction data part. */
struct opcode {
const char *name;
uint16_t mask;
uint16_t code;
struct {
uint16_t mask;
} arg[OPCODE_ARGUMENTS_MAX];
uint16_t info;
} __attribute__((packed, aligned(4)));
/* sysname - syscall name */
struct sysname {
uint32_t syscall;
const char *name;
};
/* regname - peripherals name */
struct regname {
uint32_t address;
const char *name;
};
//---
// Functions
//---
/* disasm_dictionary_check_syscall(): Check if the address is a syscall. */
extern const char *disasm_dictionary_check_syscalls(void *address);
/* disasm_dictionaru_check_peripheral(): Check preipheral address */
extern const char *disasm_dictionary_check_peripheral(void *address);
/* disasm_dictionnary_opcode_get_arg(); return arguments of a given opcode */
extern uint32_t disasm_dictionary_opcode_get_arg(const struct opcode *info,
uint16_t opcode, int argID, void *pc);
/* disasm_dictionnary_check_opcode(): Try to find opcode information */
extern const struct opcode *disasm_dictionary_check_opcode(uint16_t opcode);
#endif /*_SRC_MENU_DISASSEMBLER_DICTIONARY_H__*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,770 @@
#include "./src/menu/disassembler/dictionary.h"
#include <gint/std/stdio.h>
/* disasm_dictionaru_check_peripheral(): Check preipheral address */
const char *disasm_dictionary_check_peripheral(void *address)
{
extern const struct regname sh7305_peripherals[];
for (int i = 0 ; sh7305_peripherals[i].name != NULL ;++i) {
if (sh7305_peripherals[i].address == (uintptr_t)address)
return (sh7305_peripherals[i].name);
}
return (NULL);
}
/* Thank's Simon Lothar and Lephenixnoir */
const struct regname sh7305_peripherals[] = {
// Other registers
{.address = 0xff000020, .name = "TRA (Trap event)"},
{.address = 0xff000024, .name = "EXPEVT (Excetpion event)"},
{.address = 0xff2f0004, .name = "EXPMASK (Nonsupport exception event)"},
{.address = 0xff2f0000, .name = "CPUOPM (CPU Operation)"},
{.address = 0xff000030, .name = "PVR (Processor version)"},
{.address = 0xff000040, .name = "CVR (Cache version)"},
{.address = 0xff000044, .name = "PRR (Product version)"},
// PFC (Port function control)"},
{.address = 0xA4050100, .name = "PACR (Port A Control)"},
{.address = 0xA4050102, .name = "PBCR (Port B Control)"},
{.address = 0xA4050104, .name = "PCCR (Port C Control)"},
{.address = 0xA4050106, .name = "PDCR (Port D Control)"},
{.address = 0xA4050108, .name = "PECR (Port E Control)"},
{.address = 0xA405010A, .name = "PFCR (Port F Control)"},
{.address = 0xA405010C, .name = "PGCR (Port G Control)"},
{.address = 0xA405010E, .name = "PHCR (Port H Control)"},
{.address = 0xA4050110, .name = "PJCR (Port J Control)"},
{.address = 0xA4050112, .name = "PKCR (Port K Control)"},
{.address = 0xA4050114, .name = "PLCR (Port L Control)"},
{.address = 0xA4050116, .name = "PMCR (Port M Control)"},
{.address = 0xA4050118, .name = "PNCR (Port N Control)"},
{.address = 0xA405014C, .name = "PPCR (Port P Control)"},
{.address = 0xA405011A, .name = "PQCR (Port Q Control)"},
{.address = 0xA405011C, .name = "PRCR (Port R Control)"},
{.address = 0xA405011E, .name = "PSCR (Port S Control)"},
{.address = 0xA4050140, .name = "PTCR (Port T Control)"},
{.address = 0xA4050142, .name = "PUCR (Port U Control)"},
{.address = 0xA4050144, .name = "PVCR (Port V Control)"},
{.address = 0xA405014E, .name = "PSELA (Pin group A select)"},
{.address = 0xA4050150, .name = "PSELB (Pin group B select)"},
{.address = 0xA4050152, .name = "PSELC (Pin group C select)"},
{.address = 0xA4050154, .name = "PSELD (Pin group D select)"},
{.address = 0xA4050156, .name = "PSELE (Pin group E select)"},
{.address = 0xA405015E, .name = "PSELF (Pin group F select)"},
{.address = 0xA40501C8, .name = "PSELG (Pin group G select)"},
{.address = 0xA40501D6, .name = "PSELH (Pin group H select)"},
{.address = 0xA4050158, .name = "HIZCRA (Data pin Hi-Z control A)"},
{.address = 0xA405015A, .name = "HIZCRB (Data pin Hi-Z control B)"},
{.address = 0xA405015C, .name = "HIZCRC (Data pin Hi-Z control C)"},
{.address = 0xA4050180, .name = "MSELCRA (Module function select A)"},
{.address = 0xA4050182, .name = "MSELCRB (Module function select B)"},
{.address = 0xA4050186, .name = "DRVCRA (Buffer drive control A)"},
{.address = 0xA4050188, .name = "DRVCRB (Buffer drive control B)"},
{.address = 0xA405018A, .name = "DRVCRC (Buffer drive control C)"},
{.address = 0xA4050184, .name = "DRVCRD (Buffer drive control D)"},
{.address = 0xA40501C3, .name = "PULCRBSC (BSC pull-up/down control)"},
{.address = 0xA40501C5, .name = "PULCRTRST (TRST pull-up/down select)"},
{.address = 0xA4050190, .name = "PULCRA (Port A pull-up/down control)"},
{.address = 0xA4050191, .name = "PULCRB (Port B pull-up/down control)"},
{.address = 0xA4050192, .name = "PULCRC (Port C pull-up/down control)"},
{.address = 0xA4050193, .name = "PULCRD (Port D pull-up/down control)"},
{.address = 0xA4050194, .name = "PULCRE (Port E pull-up/down control)"},
{.address = 0xA4050195, .name = "PULCRF (Port F pull-up/down control)"},
{.address = 0xA4050196, .name = "PULCRG (Port G pull-up/down control)"},
{.address = 0xA4050197, .name = "PULCRH (Port H pull-up/down control)"},
{.address = 0xA4050198, .name = "PULCRJ (Port J pull-up/down control)"},
{.address = 0xA4050199, .name = "PULCRK (Port K pull-up/down control)"},
{.address = 0xA405019A, .name = "PULCRL (Port L pull-up/down control)"},
{.address = 0xA405019B, .name = "PULCRM (Port M pull-up/down control)"},
{.address = 0xA405019C, .name = "PULCRN (Port N pull-up/down control)"},
{.address = 0xA40501C6, .name = "PULCRP (Port P pull-up/down control)"},
{.address = 0xA405019D, .name = "PULCRQ (Port Q pull-up/down control)"},
{.address = 0xA405019E, .name = "PULCRR (Port R pull-up/down control)"},
{.address = 0xA405019F, .name = "PULCRS (Port S pull-up/down control)"},
{.address = 0xA40501C0, .name = "PULCRT (Port T pull-up/down control)"},
{.address = 0xA40501C1, .name = "PULCRU (Port U pull-up/down control)"},
{.address = 0xA40501C2, .name = "PULCRV (Port V pull-up/down control)"},
//IO (Port I/O)"},
{.address = 0xA4050128, .name = "PEDR (Port E data)"},
{.address = 0xA405012A, .name = "PFDR (Port F data)"},
{.address = 0xA405012C, .name = "PGDR (Port G data)"},
{.address = 0xA405012E, .name = "PHDR (Port H data)"},
{.address = 0xA4050130, .name = "PJDR (Port J data)"},
{.address = 0xA4050132, .name = "PKDR (Port K data)"},
{.address = 0xA4050134, .name = "PLDR (Port L data)"},
{.address = 0xA4050136, .name = "PMDR (Port M data)"},
{.address = 0xA4050138, .name = "PNDR (Port N data)"},
{.address = 0xA405016A, .name = "PPDR (Port P data)"},
{.address = 0xA405013A, .name = "PQDR (Port Q data)"},
{.address = 0xA405013C, .name = "PRDR (Port R data)"},
{.address = 0xA405013E, .name = "PSDR (Port S data)"},
{.address = 0xA4050160, .name = "PTDR (Port T data)"},
{.address = 0xA4050162, .name = "PUDR (Port U data)"},
{.address = 0xA4050164, .name = "PVDR (Port V data)"},
//INT (Interrupt)"},
{.address = 0xA4080000, .name = "IPRA (Interrupt priority A)"},
{.address = 0xA4080004, .name = "IPRB (Interrupt priority B)"},
{.address = 0xA4080008, .name = "IPRC (Interrupt priority C)"},
{.address = 0xA408000C, .name = "IPRD (Interrupt priority D)"},
{.address = 0xA4080010, .name = "IPRE (Interrupt priority E)"},
{.address = 0xA4080014, .name = "IPRF (Interrupt priority F)"},
{.address = 0xA4080018, .name = "IPRG (Interrupt priority G)"},
{.address = 0xA408001C, .name = "IPRH (Interrupt priority H)"},
{.address = 0xA4080020, .name = "IPRI (Interrupt priority I)"},
{.address = 0xA4080024, .name = "IPRJ (Interrupt priority J)"},
{.address = 0xA4080028, .name = "IPRK (Interrupt priority K)"},
{.address = 0xA408002C, .name = "IPRL (Interrupt priority L)"},
{.address = 0xA4140000, .name = "ICR0 (Interrupt control 0)"},
{.address = 0xA414001C, .name = "ICR1 (Interrupt control 1)"},
{.address = 0xA4140010, .name = "INTPRI00 (Interrupt priority for IRQ)"},
{.address = 0xA4140024, .name = "INTREQ00 (Interrupt request for IRQ)"},
{.address = 0xA4140044, .name = "INTMSK00 (Interrupt mask for IRQ)"},
{.address = 0xA4140064, .name = "INTMSKCLR00 (Interrupt mask clear for IRQ)"},
{.address = 0xA41400C0, .name = "NMIFCR (Interrupt control for NMI)"},
{.address = 0xA4700000, .name = "USERIMASK (User interrupt mask)"},
{.address = 0xFF000028, .name = "INTEVT (Interrupt event)"},
{.address = 0xA40501DC, .name = "PINTCRA (PINT control A)"},
{.address = 0xA40501DE, .name = "PINTCRB (PINT control B)"},
{.address = 0xA40501EA, .name = "PINTSRA (PINT status A)"},
{.address = 0xA40501EC, .name = "PINTSRB (PINT status B)"},
{.address = 0xA40501EE, .name = "PINTSRC (PINT status C)"},
{.address = 0xA40501FA, .name = "PINTSRD (PINT status D)"},
{.address = 0xA4080080, .name = "IMR0 (Interrupt mask 0)"},
{.address = 0xA40800C0, .name = "IMCR0 (Interrupt mask clear 0)"},
{.address = 0xA4080084, .name = "IMR1 (Interrupt mask 1)"},
{.address = 0xA40800C4, .name = "IMCR1 (Interrupt mask clear 1)"},
{.address = 0xA4080088, .name = "IMR2 (Interrupt mask 2)"},
{.address = 0xA40800C8, .name = "IMCR2 (Interrupt mask clear 2)"},
{.address = 0xA408008C, .name = "IMR3 (Interrupt mask 3)"},
{.address = 0xA40800CC, .name = "IMCR3 (Interrupt mask clear 3)"},
{.address = 0xA4080090, .name = "IMR4 (Interrupt mask 4)"},
{.address = 0xA40800D0, .name = "IMCR4 (Interrupt mask clear 4)"},
{.address = 0xA4080094, .name = "IMR5 (Interrupt mask 5)"},
{.address = 0xA40800D4, .name = "IMCR5 (Interrupt mask clear 5)"},
{.address = 0xA4080098, .name = "IMR6 (Interrupt mask 6)"},
{.address = 0xA40800D8, .name = "IMCR6 (Interrupt mask clear 6)"},
{.address = 0xA408009C, .name = "IMR7 (Interrupt mask 7)"},
{.address = 0xA40800DC, .name = "IMCR7 (Interrupt mask clear 7)"},
{.address = 0xA40800A0, .name = "IMR8 (Interrupt mask 8)"},
{.address = 0xA40800E0, .name = "IMCR8 (Interrupt mask clear 8)"},
{.address = 0xA40800A4, .name = "IMR9 (Interrupt mask 9)"},
{.address = 0xA40800E4, .name = "IMCR9 (Interrupt mask clear 9)"},
{.address = 0xA40800A8, .name = "IMR10 (Interrupt mask 10)"},
{.address = 0xA40800E8, .name = "IMCR10 (Interrupt mask clear 10)"},
{.address = 0xA40800AC, .name = "IMR11 (Interrupt mask 11)"},
{.address = 0xA40800EC, .name = "IMCR11 (Interrupt mask clear 11)"},
{.address = 0xA40800B0, .name = "IMR12 (Interrupt mask 12)"},
{.address = 0xA40800F0, .name = "IMCR12 (Interrupt mask clear 12)"},
//DMA (DMA Controller)"},
{.address = 0xFE008020, .name = "SAR0 (DMA0 Source address)"},
{.address = 0xFE008024, .name = "DAR0 (DMA0 Dest address)"},
{.address = 0xFE008028, .name = "TCR0 (DMA0 Count)"},
{.address = 0xFE00802C, .name = "CHCR0 (DMA0 Control)"},
{.address = 0xFE008030, .name = "SAR1 (DMA1 Source address)"},
{.address = 0xFE008034, .name = "DAR1 (DMA1 Dest address)"},
{.address = 0xFE008038, .name = "TCR1 (DMA1 Count)"},
{.address = 0xFE00803C, .name = "CHCR1 (DMA1 Control)"},
{.address = 0xFE008040, .name = "SAR2 (DMA2 Source address)"},
{.address = 0xFE008044, .name = "DAR2 (DMA2 Dest address)"},
{.address = 0xFE008048, .name = "TCR2 (DMA2 Count)"},
{.address = 0xFE00804C, .name = "CHCR2 (DMA2 Control)"},
{.address = 0xFE008050, .name = "SAR3 (DMA3 Source address)"},
{.address = 0xFE008054, .name = "DAR3 (DMA3 Dest address)"},
{.address = 0xFE008058, .name = "TCR3 (DMA3 Count)"},
{.address = 0xFE00805C, .name = "CHCR3 (DMA3 Control)"},
{.address = 0xFE008060, .name = "DMAOR (DMA Operation)"},
{.address = 0xFE008070, .name = "SAR4 (DMA4 Source address)"},
{.address = 0xFE008074, .name = "DAR4 (DMA4 Dest address)"},
{.address = 0xFE008078, .name = "TCR4 (DMA4 Count)"},
{.address = 0xFE00807C, .name = "CHCR4 (DMA4 Control)"},
{.address = 0xFE008080, .name = "SAR5 (DMA5 Source address)"},
{.address = 0xFE008084, .name = "DAR5 (DMA5 Dest address)"},
{.address = 0xFE008088, .name = "TCR5 (DMA5 Count)"},
{.address = 0xFE00808C, .name = "CHCR5 (DMA5 Control)"},
{.address = 0xFE008120, .name = "SARB0 (DMA0 Source address B)"},
{.address = 0xFE008124, .name = "DARB0 (DMA0 Dest address B)"},
{.address = 0xFE008128, .name = "TCRB0 (DMA0 Count B)"},
{.address = 0xFE008130, .name = "SARB1 (DMA1 Source address B)"},
{.address = 0xFE008134, .name = "DARB1 (DMA1 Dest address B)"},
{.address = 0xFE008138, .name = "TCRB1 (DMA1 Count B)"},
{.address = 0xFE008140, .name = "SARB2 (DMA2 Source address B)"},
{.address = 0xFE008144, .name = "DARB2 (DMA2 Dest address B)"},
{.address = 0xFE008148, .name = "TCRB2 (DMA2 Count B)"},
{.address = 0xFE008150, .name = "SARB3 (DMA3 Source address B)"},
{.address = 0xFE008154, .name = "DARB3 (DMA3 Dest address B)"},
{.address = 0xFE008158, .name = "TCRB3 (DMA3 Count B)"},
{.address = 0xFE009000, .name = "DMARS0 (DMA resource select 0)"},
{.address = 0xFE009004, .name = "DMARS1 (DMA resource select 1)"},
{.address = 0xFE009008, .name = "DMARS2 (DMA resource select 2)"},
// MMU (Memory Manager)"},
{.address = 0xFF000010, .name = "MMUCR (MMU Control)"},
{.address = 0xFF000000, .name = "PTEH (MMU Page table entry high)"},
{.address = 0xFF000004, .name = "PTEL (MMU Page table entry low)"},
{.address = 0xFF000034, .name = "PTEA (MMU Page table entry assistance)"},
{.address = 0xFF000008, .name = "TTB (MMU Translation table base)"},
{.address = 0xFF00000C, .name = "TEA (MMU TLB Exception address)"},
{.address = 0xFF000070, .name = "PASCR (Physical address control)"},
{.address = 0xFF000078, .name = "IRMCR (Instruction refetch inhibit control)"},
{.address = 0xF2000000, .name = "ITLBADDRA (ITLB Address Array)"},
{.address = 0xF3000000, .name = "ITLBDATAA1 (ITLB Data Array 1)"},
{.address = 0xF3800000, .name = "ITLBDATAA2 (ITLB Data Array 2)"},
{.address = 0xF6000000, .name = "UTLBADDRA (UTLB Address Array)"},
{.address = 0xF7000000, .name = "UTLBDATAA1 (UTLB Data Array 1)"},
{.address = 0xF7800000, .name = "UTLBDATAA2 (UTLB Data Array 2)"},
{.address = 0xF6100000, .name = "PMBADDRA (PMB Address Array)"},
{.address = 0xF7100000, .name = "PMBDATAA (PMB Data Array)"},
//Cache (Cache control)"},
{.address = 0xFF00001C, .name = "CCR (Cache control)"},
{.address = 0xF0000000, .name = "ICADDRA (Instruction Cache Address Array)"},
{.address = 0xF1000000, .name = "ICDATAA (Instruction Cache Data Array)"},
{.address = 0xF4000000, .name = "OCADDRA (Operand Cache Address Array)"},
{.address = 0xF5000000, .name = "OCDATAA (Operand Cache Data Array)"},
//BSC (Bus control)"},
{.address = 0xFEC10048, .name = "RTCSR (Refresh timer control)"},
{.address = 0xFEC1004C, .name = "RTCNT (Refresh counter)"},
{.address = 0xFEC10050, .name = "RTCOR (Refresh constant)"},
{.address = 0xFEC10000, .name = "CMNCR (Bus Common control)"},
{.address = 0xFEC10004, .name = "CS0BCR (Bus control for CS0)"},
{.address = 0xFEC10008, .name = "CS2BCR (Bus control for CS2)"},
{.address = 0xFEC1000C, .name = "CS3BCR (Bus control for CS3)"},
{.address = 0xFEC10010, .name = "CS4BCR (Bus control for CS4)"},
{.address = 0xFEC10014, .name = "CS5ABCR (Bus control for CS5A)"},
{.address = 0xFEC10018, .name = "CS5BBCR (Bus control for CS5B)"},
{.address = 0xFEC1001C, .name = "CS6ABCR (Bus control for CS6A)"},
{.address = 0xFEC10020, .name = "CS6BBCR (Bus control for CS6B)"},
{.address = 0xFEC10024, .name = "CS0WCR (Wait control for CS0)"},
{.address = 0xFEC10028, .name = "CS2WCR (Wait control for CS2)"},
{.address = 0xFEC1002C, .name = "CS3WCR (Wait control for CS3)"},
{.address = 0xFEC10030, .name = "CS4WCR (Wait control for CS4)"},
{.address = 0xFEC10034, .name = "CS5AWCR (Wait control for CS5A)"},
{.address = 0xFEC10038, .name = "CS5BWCR (Wait control for CS5B)"},
{.address = 0xFEC1003C, .name = "CS6AWCR (Wait control for CS6A)"},
{.address = 0xFEC10040, .name = "CS6BWCR (Wait control for CS6B)"},
{.address = 0xFEC10044, .name = "SDCR (SDRAM control)"},
{.address = 0xFEC14000, .name = "SDMR2 (SDRAM mode for CS2)"},
{.address = 0xFEC15000, .name = "SDMR3 (SDRAM mode for CS3)"},
// Clock (Clock generation)"},
{.address = 0xA4150000, .name = "FRQCR (Frequency control)"},
{.address = 0xA4150008, .name = "FSICLKCR (FSI Clock control)"},
{.address = 0xA415003C, .name = "SPUCLKCR (SPU Clock control)"},
{.address = 0xA4150010, .name = "DDCLKCR (DD Clock control)"},
{.address = 0xA4150014, .name = "USBCLKCR (USB Clock control)"},
{.address = 0xA4150024, .name = "PLLCR (PLL1 control)"},
{.address = 0xA4150028, .name = "PLL2CR (PLL2 control)"},
{.address = 0xA4150050, .name = "FLLFRQ (FLL Multiplication control)"},
{.address = 0xA4150060, .name = "LSTATUS (Frequency change status)"},
{.address = 0xA4150044, .name = "SSCGCR (Spread spectrum control)"},
// RTC (Real-time clock)"},
{.address = 0xA413FEC0, .name = "R64CNT (64-Hz counter)"},
{.address = 0xA413FEC2, .name = "RSECCNT (Seconds counter)"},
{.address = 0xA413FEC4, .name = "RMINCNT (Minutes counter)"},
{.address = 0xA413FEC6, .name = "RHRCNT (Hours counter)"},
{.address = 0xA413FEC8, .name = "RWKCNT (Weekday counter)"},
{.address = 0xA413FECA, .name = "RDAYCNT (Date counter)"},
{.address = 0xA413FECC, .name = "RMONCNT (Months counter)"},
{.address = 0xA413FECE, .name = "RYRCNT (Years counter)"},
{.address = 0xA413FED0, .name = "RSECAR (Seconds alarm)"},
{.address = 0xA413FED2, .name = "RMINAR (Minutes alarm)"},
{.address = 0xA413FED4, .name = "RHRAR (Hours alarm)"},
{.address = 0xA413FED6, .name = "RWKAR (Weekday alarm)"},
{.address = 0xA413FED8, .name = "RDAYAR (Date alarm)"},
{.address = 0xA413FEDA, .name = "RMONAR (Months alarm)"},
{.address = 0xA413FEE0, .name = "RYRAR (Years alarm)"},
{.address = 0xA413FEDC, .name = "RCR1 (RTC control 1)"},
{.address = 0xA413FEDE, .name = "RCR2 (RTC control 2)"},
{.address = 0xA413FEE4, .name = "RCR3 (RTC control 3)"},
// WDT (Watchdog timer)"},
{.address = 0xA4520000, .name = "RWTCNT (Watchdog timer counter)"},
{.address = 0xA4520004, .name = "RWTCSR (Watchdog control)"},
// Power (Power-down modes)"},
{.address = 0xA4150020, .name = "STBCR (Standby control)"},
{.address = 0xA4150030, .name = "MSTPCR0 (Module stop 0)"},
{.address = 0xA4150038, .name = "MSTPCR2 (Module stop 2)"},
{.address = 0xA4150040, .name = "BAR (Boot address)"},
// TMU0 (Timer unit 0)"},
{.address = 0xA4490004, .name = "TSTR (Timer start)"},
{.address = 0xA4490008, .name = "TCOR0 (Timer 0 constant)"},
{.address = 0xA449000C, .name = "TCNT0 (Timer 0 counter)"},
{.address = 0xA4490010, .name = "TCR0 (Timer 0 control)"},
// TMU1 (Timer unit 1)"},
{.address = 0xA4490014, .name = "TCOR1 (Timer 1 constant)"},
{.address = 0xA4490018, .name = "TCNT1 (Timer 1 counter)"},
{.address = 0xA449001C, .name = "TCR1 (Timer 1 control)"},
// TMU2 (Timer unit 2)"},
{.address = 0xA4490020, .name = "TCOR2 (Timer 2 constant)"},
{.address = 0xA4490024, .name = "TCNT2 (Timer 2 counter)"},
{.address = 0xA4490028, .name = "TCR2 (Timer 2 control)"},
// CMT (Compare match timer)"},
{.address = 0xA44A0000, .name = "CMSTR (Compare match timer start)"},
{.address = 0xA44A0060, .name = "CMCSR (Compare match timer control)"},
{.address = 0xA44A0064, .name = "CMCNT (Compare match timer counter)"},
{.address = 0xA44A0068, .name = "CMCOR (Compare match timer constant)"},
// Custom-module
{.address = 0xa44c0000, .name = "DDCLKR0 (External CLK1 setting)"},
{.address = 0xa44c0002, .name = "DDCLKR1 (External CLK2 setting)"},
{.address = 0xa44c0004, .name = "DDCLKR2 (External CLK3 setting)"},
{.address = 0xa44c0020, .name = "DDCK_CNTR (External clock control)"},
{.address = 0xa44c0006, .name = "DDCS_CNTR (External CS control)"},
{.address = 0xa44c0008, .name = "HIZ_CNTR (Interrupt pin level control)"},
{.address = 0xa4cb0010, .name = "FASCR (BCD Calculation control)"},
{.address = 0xa4cb0014, .name = "FASSRA (BCD Calculation source A)"},
{.address = 0xa4cb0018, .name = "FASSRB (BCD Calculation source B)"},
{.address = 0xa4cb001c, .name = "FASDR (BCD Calculation result)"},
{.address = 0xa44d0030, .name = "RTSTR0(RTC Clock timer 0 start)"},
{.address = 0xa44d003c, .name = "RTCR0 (RTC Clock timer 0 control)"},
{.address = 0xa44d0034, .name = "RTCOR0 (RTC Clock timer 0 constant)"},
{.address = 0xa44d0038, .name = "RTCNT0 (RTC Clock timer 0 counter)"},
{.address = 0xa44d0050, .name = "RTSTR1(RTC Clock timer 1 start)"},
{.address = 0xa44d005c, .name = "RTCR1 (RTC Clock timer 1 control)"},
{.address = 0xa44d0054, .name = "RTCOR1 (RTC Clock timer 1 constant)"},
{.address = 0xa44d0058, .name = "RTCNT1 (RTC Clock timer 1 counter)"},
{.address = 0xa44d0070, .name = "RTSTR2 (RTC Clock timer 2 start)"},
{.address = 0xa44d007c, .name = "RTCR2 (RTC Clock timer 2 control)"},
{.address = 0xa44d0074, .name = "RTCOR2 (RTC Clock timer 2 constant)"},
{.address = 0xa44d0078, .name = "RTCNT2 (RTC Clock timer 2 counter)"},
{.address = 0xa44d0090, .name = "RTSTR3 (RTC Clock timer 3 start)"},
{.address = 0xa44d009c, .name = "RTCR3 (RTC Clock timer 3 control)"},
{.address = 0xa44d0094, .name = "RTCOR3 (RTC Clock timer 3 constant)"},
{.address = 0xa44d0098, .name = "RTCNT3 (RTC Clock timer 3 counter)"},
{.address = 0xa44d00b0, .name = "RTSTR4 (RTC Clock timer 4 start)"},
{.address = 0xa44d00bc, .name = "RTCR4 (RTC Clock timer 4 control)"},
{.address = 0xa44d00b4, .name = "RTCOR4 (RTC Clock timer 4 constant)"},
{.address = 0xa44d00b8, .name = "RTCNT4 (RTC Clock timer 4 counter)"},
{.address = 0xa44d00d0, .name = "RTSTR5 (RTC Clock timer 5 start)"},
{.address = 0xa44d00dc, .name = "RTCR5 (RTC Clock timer 5 control)"},
{.address = 0xa44d00d4, .name = "RTCOR5 (RTC Clock timer 5 constant)"},
{.address = 0xa44d00d8, .name = "RTCNT5 (RTC Clock timer 5 counter)"},
// Custom module 2a
{.address = 0xa4cd0000, .name = "CHRMCTRL (Character extension operation control)"},
{.address = 0xa4cd0004, .name = "CHRCOLOR (Character color specification)"},
{.address = 0xa4cd0008, .name = "CHRRADDR (Character data read start address)"},
{.address = 0xa4cd000c, .name = "CHRSIZE (Character data read length)"},
{.address = 0xa4cd0010, .name = "MSKRADDR (Mask data read start address)"},
{.address = 0xa4cd0014, .name = "VRMWADDR (VRAM write start address)"},
{.address = 0xa4cd0018, .name = "VRMWSBIT (VRAM write start bit)"},
{.address = 0xa4cd001c, .name = "VRMAREA (VRAM area)"},
{.address = 0xa4cd0020, .name = "DESWADDR (Destination write start address)"},
{.address = 0xa4cd0024, .name = "DESAREA (Destination area)"},
{.address = 0xa4cd0028, .name = "DMAMCTRL (DMA data transfer operation control)"},
{.address = 0xa4cd002c, .name = "VRMRADDR (VRAM data read start address)"},
{.address = 0xa4cd0030, .name = "VRMRSIZE (VRAM data read length)"},
{.address = 0xa4cd0034, .name = "DDWPOINT1 (D/D-RAM write start pointer 1)"},
{.address = 0xa4cd0038, .name = "DDWPOINT2 (D/D-RAM write start pointer 2)"},
{.address = 0xa4cd003c, .name = "DDWPOINT3 (D/D-RAM write start pointer 3)"},
{.address = 0xa4cd0040, .name = "DDWPOINT4 (D/D-RAM write start pointer 4)"},
{.address = 0xa4cd0044, .name = "DDWSIZE1 (D/D-RAM write length 1)"},
{.address = 0xa4cd0048, .name = "DDWSIZE2 (D/D-RAM write length 2)"},
{.address = 0xa4cd004c, .name = "DDWSIZE3 (D/D-RAM write length 3)"},
{.address = 0xa4cd0050, .name = "DDWSIZE4 (D/D-RAM write length 4)"},
{.address = 0xa4cd0054, .name = "DDAREA1 (D/D-RAM area 1)"},
{.address = 0xa4cd0058, .name = "DDAREA2 (D/D-RAM area 2)"},
{.address = 0xa4cd005c, .name = "DDAREA3 (D/D-RAM area 3)"},
{.address = 0xa4cd0060, .name = "DDAREA4 (D/D-RAM area 4)"},
{.address = 0xa4cd0064, .name = "LAYMCTRL (Layer operation control)"},
// SCIF (Serial communication)"},
{.address = 0xA4410000, .name = "SCSMR (Serial Mode)"},
{.address = 0xA4410004, .name = "SCBRR (Serial Bit rate)"},
{.address = 0xA4410008, .name = "SCSCR (Serial Control)"},
{.address = 0xA441000C, .name = "SCFTDR (Serial Transmit data)"},
{.address = 0xA4410010, .name = "SCFSR (Serial Status)"},
{.address = 0xA4410014, .name = "SCFRDR (Serial Receive data)"},
{.address = 0xA4410018, .name = "SCFCR (Serial FIFO control)"},
{.address = 0xA441001C, .name = "SCFDR (Serial FIFO count)"},
{.address = 0xA4410024, .name = "SCLSR (Serial Line status)"},
// IIC (I2C communication)"},
{.address = 0xA4470000, .name = "ICDR (I2C bus data)"},
{.address = 0xA4470004, .name = "ICCR (I2C bus control)"},
{.address = 0xA4470008, .name = "ICSR (I2C bus status)"},
{.address = 0xA447000C, .name = "ICIC (I2C interrupt control)"},
{.address = 0xA4470010, .name = "ICCL (I2C clock control low)"},
{.address = 0xA4470014, .name = "ICCH (I2C clock control high)"},
// USB (USB 2 control)"},
{.address = 0xA4D80000, .name = "SYSCFG (System configuration control)"},
{.address = 0xA4D80002, .name = "BUSWAIT (CPU bus wait setting)"},
{.address = 0xA4D80004, .name = "SYSSTS (System configuration status)"},
{.address = 0xA4D80008, .name = "DVSTCTR (Device status control)"},
{.address = 0xA4D8000C, .name = "TESTMODE (Test mode)"},
{.address = 0xA4D80014, .name = "CFIFO (CFIFO port)"},
{.address = 0xA4D80018, .name = "D0FIFO (D0FIFO port)"},
{.address = 0xA4D8001C, .name = "D1FIFO (D1FIFO port)"},
{.address = 0xA4D80020, .name = "CFIFOSEL (CFIFO port select)"},
{.address = 0xA4D80022, .name = "CFIFOCTR (CFIFO port control)"},
{.address = 0xA4D80028, .name = "D0FIFOSEL (D0FIFO port select)"},
{.address = 0xA4D8002A, .name = "D0FIFOCTR (D0FIFO port control)"},
{.address = 0xA4D8002C, .name = "D1FIFOSEL (D1FIFO port select)"},
{.address = 0xA4D8002E, .name = "D1FIFOCTR (D1FIFO port control)"},
{.address = 0xA4D80030, .name = "INTENB0 (Interrupt enable 0)"},
{.address = 0xA4D80036, .name = "BRDYENB (BRDY interrupt enable)"},
{.address = 0xA4D80038, .name = "NRDYENB (NRDY interrupt enable)"},
{.address = 0xA4D8003A, .name = "BEMPENB (BEMP interrupt enable)"},
{.address = 0xA4D8003C, .name = "SOFCFG (SOF pin configuration)"},
{.address = 0xA4D80040, .name = "INTSTS0 (Interrupt status 0)"},
{.address = 0xA4D80046, .name = "BRDYSTS (BRDY interrupt status)"},
{.address = 0xA4D80048, .name = "NRDYSTS (NRDY interrupt status)"},
{.address = 0xA4D8004A, .name = "BEMPSTS (BEMP interrupt status)"},
{.address = 0xA4D8004C, .name = "FRMNUM (Frame number)"},
{.address = 0xA4D8004E, .name = "UFRMNUM (mFrame number)"},
{.address = 0xA4D80050, .name = "USBADDR (USB address)"},
{.address = 0xA4D80054, .name = "USBREQ (USB request type)"},
{.address = 0xA4D80056, .name = "USBVAL (USB request value)"},
{.address = 0xA4D80058, .name = "USBINDX (USB request index)"},
{.address = 0xA4D8005A, .name = "USBLENG (USB request length)"},
{.address = 0xA4D8005C, .name = "DCPCFG (DCP configuration)"},
{.address = 0xA4D8005E, .name = "DCPMAXP (DCP max packet size)"},
{.address = 0xA4D80060, .name = "DCPCTR (DCP control)"},
{.address = 0xA4D80064, .name = "PIPESEL (Pipe window select)"},
{.address = 0xA4D80068, .name = "PIPECFG (Pipe configuration)"},
{.address = 0xA4D8006A, .name = "PIPEBUF (Pipe buffer setting)"},
{.address = 0xA4D8006C, .name = "PIPEMAXP (Pipe max packet size)"},
{.address = 0xA4D8006E, .name = "PIPEPERI (Pipe cycle control)"},
{.address = 0xA4D80070, .name = "PIPE1CTR (Pipe 1 control)"},
{.address = 0xA4D80072, .name = "PIPE2CTR (Pipe 2 control)"},
{.address = 0xA4D80074, .name = "PIPE3CTR (Pipe 3 control)"},
{.address = 0xA4D80076, .name = "PIPE4CTR (Pipe 4 control)"},
{.address = 0xA4D80078, .name = "PIPE5CTR (Pipe 5 control)"},
{.address = 0xA4D8007A, .name = "PIPE6CTR (Pipe 6 control)"},
{.address = 0xA4D8007C, .name = "PIPE7CTR (Pipe 7 control)"},
{.address = 0xA4D8007E, .name = "PIPE8CTR (Pipe 8 control)"},
{.address = 0xA4D80080, .name = "PIPE9CTR (Pipe 9 control)"},
{.address = 0xA4D80090, .name = "PIPE1TRE (Pipe 1 transaction counter enable)"},
{.address = 0xA4D80092, .name = "PIPE1TRN (Pipe 1 transaction counter)"},
{.address = 0xA4D80094, .name = "PIPE2TRE (Pipe 2 transaction counter enable)"},
{.address = 0xA4D80096, .name = "PIPE2TRN (Pipe 2 transaction counter)"},
{.address = 0xA4D80098, .name = "PIPE3TRE (Pipe 3 transaction counter enable)"},
{.address = 0xA4D8009A, .name = "PIPE3TRN (Pipe 3 transaction counter)"},
{.address = 0xA4D8009C, .name = "PIPE4TRE (Pipe 4 transaction counter enable)"},
{.address = 0xA4D8009E, .name = "PIPE4TRN (Pipe 4 transaction counter)"},
{.address = 0xA4D800A0, .name = "PIPE5TRE (Pipe 5 transaction counter enable)"},
{.address = 0xA4D800A2, .name = "PIPE5TRN (Pipe 5 transaction counter)"},
{.address = 0xA40501D4, .name = "UPONCR (USB power control)"},
// FSI (FIFO serial interface)"},
{.address = 0xFE3C0000, .name = "A_DO_FMT (A output serial format)"},
{.address = 0xFE3C0004, .name = "A_DOFF_CTL (A output FIFO control)"},
{.address = 0xFE3C0008, .name = "A_DOFF_ST (A output FIFO status)"},
{.address = 0xFE3C000C, .name = "A_DI_FMT (A input serial format)"},
{.address = 0xFE3C0010, .name = "A_DIFF_CTL (A input FIFO control)"},
{.address = 0xFE3C0014, .name = "A_DIFF_ST (A input FIFO status)"},
{.address = 0xFE3C0018, .name = "A_CKG1 (A clock set 1)"},
{.address = 0xFE3C001C, .name = "A_CKG2 (A clock set 2)"},
{.address = 0xFE3C0020, .name = "A_DIDT (A read data)"},
{.address = 0xFE3C0024, .name = "A_DODT (A write data)"},
{.address = 0xFE3C0028, .name = "A_MUTE_ST (A mute state)"},
{.address = 0xFE3C0040, .name = "B_DO_FMT (B output serial format)"},
{.address = 0xFE3C0044, .name = "B_DOFF_CTL (B output FIFO control)"},
{.address = 0xFE3C0048, .name = "B_DOFF_ST (B output FIFO status)"},
{.address = 0xFE3C004C, .name = "B_DI_FMT (B input serial format)"},
{.address = 0xFE3C0050, .name = "B_DIFF_CTL (B input FIFO control)"},
{.address = 0xFE3C0054, .name = "B_DIFF_ST (B input FIFO status)"},
{.address = 0xFE3C0058, .name = "B_CKG1 (B clock set 1)"},
{.address = 0xFE3C005C, .name = "B_CKG2 (B clock set 2)"},
{.address = 0xFE3C0060, .name = "B_DIDT (B read data)"},
{.address = 0xFE3C0064, .name = "B_DODT (B write data)"},
{.address = 0xFE3C0068, .name = "B_MUTE_ST (B mute state)"},
{.address = 0xFE3C0200, .name = "INT_ST (Interrupt state)"},
{.address = 0xFE3C0204, .name = "IEMSK (Interrupt source mask)"},
{.address = 0xFE3C0208, .name = "IMSK (Interrupt signal mask)"},
{.address = 0xFE3C020C, .name = "MUTE (Mute set)"},
{.address = 0xFE3C0210, .name = "CLK_RST (Clock reset)"},
{.address = 0xFE3C0214, .name = "SOFT_RST (Software reset)"},
{.address = 0xFE3C0218, .name = "FIFO_SZ (FIFO size)"},
// KEY (Key interface unit)"},
{.address = 0xA44B0000, .name = "KIUDATA0 (Key input data 0)"},
{.address = 0xA44B0002, .name = "KIUDATA1 (Key input data 1)"},
{.address = 0xA44B0004, .name = "KIUDATA2 (Key input data 2)"},
{.address = 0xA44B0006, .name = "KIUDATA3 (Key input data 3)"},
{.address = 0xA44B0008, .name = "KIUDATA4 (Key input data 4)"},
{.address = 0xA44B000A, .name = "KIUDATA5 (Key input data 5)"},
{.address = 0xA44B000C, .name = "KIUCNTREG (Scan control)"},
{.address = 0xA44B000E, .name = "KIAUTOFIXREG (Automatic key bounce setting)"},
{.address = 0xA44B0010, .name = "KIUMODEREG (Scan mode setting)"},
{.address = 0xA44B0012, .name = "KIUSTATEREG (Scan state)"},
{.address = 0xA44B0014, .name = "KIUINTREG (Interrupt setting)"},
{.address = 0xA44B0016, .name = "KIUWSETREG (Scan wait time setting)"},
{.address = 0xA44B0018, .name = "KIUINTERVALREG (Scan interval time setting)"},
{.address = 0xA44B001A, .name = "KOUTPINSET (KOUT line function setting)"},
{.address = 0xA44B001C, .name = "KINPINSET (KIN line function setting)"},
// MSIOF0 (Sync serial interface 0)"},
{.address = 0xA4C40000, .name = "SITMDR1 (Transmit mode 1)"},
{.address = 0xA4C40004, .name = "SITMDR2 (Transmit mode 2)"},
{.address = 0xA4C40008, .name = "SITMDR3 (Transmit mode 3)"},
{.address = 0xA4C40020, .name = "SITSCR (Transmit clock select)"},
{.address = 0xA4C40010, .name = "SIRMDR1 (Receive mode 1)"},
{.address = 0xA4C40014, .name = "SIRMDR2 (Receive mode 2)"},
{.address = 0xA4C40018, .name = "SIRMDR3 (Receive mode 3)"},
{.address = 0xA4C40024, .name = "SIRSCR (Receive clock select)"},
{.address = 0xA4C40028, .name = "SICTR (Control)"},
{.address = 0xA4C40030, .name = "SIFCTR (FIFO control)"},
{.address = 0xA4C40040, .name = "SISTR (Status)"},
{.address = 0xA4C40044, .name = "SIIER (Interrupt enable)"},
{.address = 0xA4C40048, .name = "SITDR1 (Transmit control data 1)"},
{.address = 0xA4C4004C, .name = "SITDR2 (Transmit control data 2)"},
{.address = 0xA4C40050, .name = "SITFDR (Transmit FIFO data)"},
{.address = 0xA4C40058, .name = "SIRDR1 (Receive control data 1)"},
{.address = 0xA4C4005C, .name = "SIRDR2 (Receive control data 2)"},
{.address = 0xA4C40060, .name = "SIRFDR (Receive FIFO data)"},
// MSIOF1 (Sync serial interface 1)"},
{.address = 0xA4C50000, .name = "SITMDR1 (Transmit mode 1)"},
{.address = 0xA4C50004, .name = "SITMDR2 (Transmit mode 2)"},
{.address = 0xA4C50008, .name = "SITMDR3 (Transmit mode 3)"},
{.address = 0xA4C50020, .name = "SITSCR (Transmit clock select)"},
{.address = 0xA4C50010, .name = "SIRMDR1 (Receive mode 1)"},
{.address = 0xA4C50014, .name = "SIRMDR2 (Receive mode 2)"},
{.address = 0xA4C50018, .name = "SIRMDR3 (Receive mode 3)"},
{.address = 0xA4C50024, .name = "SIRSCR (Receive clock select)"},
{.address = 0xA4C50028, .name = "SICTR (Control)"},
{.address = 0xA4C50030, .name = "SIFCTR (FIFO control)"},
{.address = 0xA4C50040, .name = "SISTR (Status)"},
{.address = 0xA4C50044, .name = "SIIER (Interrupt enable)"},
{.address = 0xA4C50048, .name = "SITDR1 (Transmit control data 1)"},
{.address = 0xA4C5004C, .name = "SITDR2 (Transmit control data 2)"},
{.address = 0xA4C50050, .name = "SITFDR (Transmit FIFO data)"},
{.address = 0xA4C50058, .name = "SIRDR1 (Receive control data 1)"},
{.address = 0xA4C5005C, .name = "SIRDR2 (Receive control data 2)"},
{.address = 0xA4C50060, .name = "SIRFDR (Receive FIFO data)"},
// ADC (Analog/Digital converter)"},
{.address = 0xA4610080, .name = "ADDRA (A/D A data)"},
{.address = 0xA4610082, .name = "ADDRB (A/D B data)"},
{.address = 0xA4610084, .name = "ADDRC (A/D C data)"},
{.address = 0xA4610086, .name = "ADDRD (A/D D data)"},
{.address = 0xA4610088, .name = "ADCSR (A/D Control/status)"},
{.address = 0xA461008A, .name = "ADCCSR (A/D Custom control)"},
{.address = 0xA461008C, .name = "ADCUST (A/D Control)"},
{.address = 0xA461008E, .name = "ADPCTL (A/D Port control)"},
// SHway (Super Hyway Bus)"},
{.address = 0xFF800018, .name = "PRLCKCR (LCK control)"},
{.address = 0xFF800020, .name = "PRPRICR0 (PRI control 0)"},
{.address = 0xFF800028, .name = "PRPRICR1 (PRI control 1)"},
{.address = 0xFF800030, .name = "PRPRICR2 (PRI control 2)"},
{.address = 0xFF800038, .name = "PRPRICR3 (PRI control 3)"},
{.address = 0xFF800040, .name = "PRPRICR4 (PRI control 4)"},
{.address = 0xFF800048, .name = "PRPRICR5 (PRI control 5)"},
{.address = 0xA4530000, .name = "SHOCMCR (SHOC master control)"},
{.address = 0xA4530004, .name = "SHOCMSR (SHOC master status)"},
// SD Card Host Controller
{.address = 0xa4cf0000, .name= "SD_CMD (?)"},
{.address = 0xa4cf0004, .name= "SD_ARG0 (?)"},
{.address = 0xa4cf0006, .name= "SD_ARG1 (?)"},
{.address = 0xa4cf0008, .name= "SD_STOP (?)"},
{.address = 0xa4cf000a, .name= "SD_SECCNT (?)"},
{.address = 0xa4cf000c, .name= "SD_RSP0 (?)"},
{.address = 0xa4cf000e, .name= "SD_RSP1 (?)"},
{.address = 0xa4cf0010, .name= "SD_RSP2 (?)"},
{.address = 0xa4cf0012, .name= "SD_RSP3 (?)"},
{.address = 0xa4cf0014, .name= "SD_RSP4 (?)"},
{.address = 0xa4cf0016, .name= "SD_RSP5 (?)"},
{.address = 0xa4cf0018, .name= "SD_RSP6 (?)"},
{.address = 0xa4cf001a, .name= "SD_RSP7 (?)"},
{.address = 0xa4cf001c, .name= "SD_INFO1 (SD card information 1)"},
{.address = 0xa4cf001e, .name= "SD_INFO2 (?)"},
{.address = 0xa4cf0020, .name= "SD_INFO1_MASK (?)"},
{.address = 0xa4cf0022, .name= "SD_INFO2_MASK (?)"},
{.address = 0xa4cf0024, .name= "SD_CLK_CNTL (?)"},
{.address = 0xa4cf0026, .name= "SD_SIZE (?)"},
{.address = 0xa4cf0028, .name= "SD_OPTION (?)"},
{.address = 0xa4cf002c, .name= "SD_ERR_STS1 (?)"},
{.address = 0xa4cf002e, .name= "SD_ERR_STS2 (?)"},
{.address = 0xa4cf0030, .name= "SD_BUFO (?)"},
{.address = 0xa4cf0034, .name= "SDIO_MODE (?)"},
{.address = 0xa4cf0036, .name= "SDIO_INFO1 (?)"},
{.address = 0xa4cf0038, .name= "SDIO_INFO1_MASK (?)"},
{.address = 0xa4cf00d8, .name= "CC_EXT_MODE (?)"},
{.address = 0xa4cf00e0, .name= "SOFT_RST (?)"},
{.address = 0xa4cf00e2, .name= "VERSION (?)"},
{.address = 0xa4cf00f0, .name= "EXT_SWAP (?)"},
// SPU2 (Sound Processing Unit 2)
{.address = 0xfe2ffc00, .name = "PBANKC0 (PRAM bank control 0)"},
{.address = 0xfe2ffc04, .name = "PBANKC1 (PRAM bank control 1)"},
{.address = 0xfe2ffc10, .name = "XBANKC0 (XRAM bank control 0)"},
{.address = 0xfe2ffc14, .name = "XBANKC1 (XRAM bank control 1)"},
{.address = 0xfe2ffc24, .name = "SPUSRST (SPU software reset)"},
{.address = 0xfe2ffc28, .name = "SPUADR (SPU address)"},
{.address = 0xfe2ffc2c, .name = "ENDIAN (SHway endian)"},
{.address = 0xfe2ffc40, .name = "GCOM0 (Global common 0)"},
{.address = 0xfe2ffc44, .name = "GCOM1 (Global common 1)"},
{.address = 0xfe2ffc48, .name = "GCOM2 (Global common 2)"},
{.address = 0xfe2ffc4c, .name = "GCOM3 (Global common 3)"},
{.address = 0xfe2ffc50, .name = "GCOM4 (Global common 4)"},
{.address = 0xfe2ffc54, .name = "GCOM5 (Global common 5)"},
{.address = 0xfe2ffc58, .name = "GCOM6 (Global common 6)"},
{.address = 0xfe2ffc5c, .name = "GCOM7 (Global common 7)"},
{.address = 0xfe2ffc80, .name = "DMABUF0 (Inter-DSP communication buffer 0)"},
{.address = 0xfe2ffc84, .name = "DMABUF1 (Inter-DSP communication buffer 1)"},
{.address = 0xfe2ffc88, .name = "DMABUF2 (Inter-DSP communication buffer 2)"},
{.address = 0xfe2ffc8c, .name = "DMABUF3 (Inter-DSP communication buffer 3)"},
// SPU2DSP0 (Sound Processing Unit 2 DSP 0)
{.address = 0xfe2ffd00, .name = "DSPRST (DSP full reset)"},
{.address = 0xfe2ffd04, .name = "DSPCORERST (DSP core reset)"},
{.address = 0xfe2ffd08, .name = "DSPHOLD (DSP hold)"},
{.address = 0xfe2ffd0c, .name = "DSPRESTART (DSP restart)"},
{.address = 0xfe2ffd18, .name = "IEMASKC (CPU interrupt source mask)"},
{.address = 0xfe2ffd1c, .name = "IMASKC (CPU interrupt signal mask)"},
{.address = 0xfe2ffd20, .name = "IEVENTC (CPU interrupt source)"},
{.address = 0xfe2ffd24, .name = "IEMASKD (DSP interrupt source mask)"},
{.address = 0xfe2ffd28, .name = "IMASKD (DSP interrupt signal mask)"},
{.address = 0xfe2ffd2c, .name = "IESETD (DSP interrupt set)"},
{.address = 0xfe2ffd30, .name = "IECLRD (DSP interrupt clear)"},
{.address = 0xfe2ffd34, .name = "OR (DMAC operation)"},
{.address = 0xfe2ffd38, .name = "COM0 (CPU-DSP communication 0)"},
{.address = 0xfe2ffd3c, .name = "COM1 (CPU-DSP communication 1)"},
{.address = 0xfe2ffd40, .name = "COM2 (CPU-DSP communication 2)"},
{.address = 0xfe2ffd44, .name = "COM3 (CPU-DSP communication 3)"},
{.address = 0xfe2ffd48, .name = "COM4 (CPU-DSP communication 4)"},
{.address = 0xfe2ffd4c, .name = "COM5 (CPU-DSP communication 5)"},
{.address = 0xfe2ffd50, .name = "COM6 (CPU-DSP communication 6)"},
{.address = 0xfe2ffd54, .name = "COM7 (CPU-DSP communication 7)"},
{.address = 0xfe2ffd58, .name = "BTADRU (Bus-through address high)"},
{.address = 0xfe2ffd5c, .name = "BTADRL (Bus-through address low)"},
{.address = 0xfe2ffd60, .name = "WDATU (Bus-through write data high)"},
{.address = 0xfe2ffd64, .name = "WDATL (Bus-through write data low)"},
{.address = 0xfe2ffd68, .name = "RDATU (Bus-through read data high)"},
{.address = 0xfe2ffd6c, .name = "RDATL (Bus-through read data low)"},
{.address = 0xfe2ffd70, .name = "BTCTRL (Bus-through mode control)"},
{.address = 0xfe2ffd74, .name = "SPUSTS (SPU status)"},
{.address = 0xfe2ffe00, .name = "SBAR0 (Source base address 0)"},
{.address = 0xfe2ffe04, .name = "SAR0 (Source address 0)"},
{.address = 0xfe2ffe08, .name = "DBAR0 (Destination base address 0)"},
{.address = 0xfe2ffe0c, .name = "DAR0 (Destination address 0)"},
{.address = 0xfe2ffe10, .name = "TCR0 (Transfer count 0)"},
{.address = 0xfe2ffe14, .name = "SHPRI0 (SHway priority 0)"},
{.address = 0xfe2ffe18, .name = "CHCR0 (Channel control 0)"},
{.address = 0xfe2ffe20, .name = "SBAR1 (Source base address 1)"},
{.address = 0xfe2ffe24, .name = "SAR1 (Source address 1)"},
{.address = 0xfe2ffe28, .name = "DBAR1 (Destination base address 1)"},
{.address = 0xfe2ffe2c, .name = "DAR1 (Destination address 1)"},
{.address = 0xfe2ffe30, .name = "TCR1 (Transfer count 1)"},
{.address = 0xfe2ffe34, .name = "SHPRI1 (SHway priority 1)"},
{.address = 0xfe2ffe38, .name = "CHCR1 (Channel control 1)"},
{.address = 0xfe2ffe40, .name = "SBAR2 (Source base address 2)"},
{.address = 0xfe2ffe44, .name = "SAR2 (Source address 2)"},
{.address = 0xfe2ffe48, .name = "DBAR2 (Destination base address 2)"},
{.address = 0xfe2ffe4c, .name = "DAR2 (Destination address 2)"},
{.address = 0xfe2ffe50, .name = "TCR2 (Transfer count 2)"},
{.address = 0xfe2ffe54, .name = "SHPRI2 (SHway priority 2)"},
{.address = 0xfe2ffe58, .name = "CHCR2 (Channel control 2)"},
{.address = 0xfe2ffe80, .name = "LSA0 (Loop start address 0)"},
{.address = 0xfe2ffe84, .name = "LEA0 (Loop end address 0)"},
{.address = 0xfe2ffe90, .name = "LSA1 (Loop start address 1)"},
{.address = 0xfe2ffe94, .name = "LEA1 (Loop end address 1)"},
{.address = 0xfe2ffea0, .name = "LSA2 (Loop start address 2)"},
{.address = 0xfe2ffea4, .name = "LEA2 (Loop end address 2)"},
// SPU2DSP1 (Sound Processing Unit 2 DSP 1)
{.address = 0xfe3ffd00, .name = "DSPRST (DSP full reset)"},
{.address = 0xfe3ffd04, .name = "DSPCORERST (DSP core reset)"},
{.address = 0xfe3ffd08, .name = "DSPHOLD (DSP hold)"},
{.address = 0xfe3ffd0c, .name = "DSPRESTART (DSP restart)"},
{.address = 0xfe3ffd18, .name = "IEMASKC (CPU interrupt source mask)"},
{.address = 0xfe3ffd1c, .name = "IMASKC (CPU interrupt signal mask)"},
{.address = 0xfe3ffd20, .name = "IEVENTC (CPU interrupt source)"},
{.address = 0xfe3ffd24, .name = "IEMASKD (DSP interrupt source mask)"},
{.address = 0xfe3ffd28, .name = "IMASKD (DSP interrupt signal mask)"},
{.address = 0xfe3ffd2c, .name = "IESETD (DSP interrupt set)"},
{.address = 0xfe3ffd30, .name = "IECLRD (DSP interrupt clear)"},
{.address = 0xfe3ffd34, .name = "OR (DMAC operation)"},
{.address = 0xfe3ffd38, .name = "COM0 (CPU-DSP communication 0)"},
{.address = 0xfe3ffd3c, .name = "COM1 (CPU-DSP communication 1)"},
{.address = 0xfe3ffd40, .name = "COM2 (CPU-DSP communication 2)"},
{.address = 0xfe3ffd44, .name = "COM3 (CPU-DSP communication 3)"},
{.address = 0xfe3ffd48, .name = "COM4 (CPU-DSP communication 4)"},
{.address = 0xfe3ffd4c, .name = "COM5 (CPU-DSP communication 5)"},
{.address = 0xfe3ffd50, .name = "COM6 (CPU-DSP communication 6)"},
{.address = 0xfe3ffd54, .name = "COM7 (CPU-DSP communication 7)"},
{.address = 0xfe3ffd58, .name = "BTADRU (Bus-through address high)"},
{.address = 0xfe3ffd5c, .name = "BTADRL (Bus-through address low)"},
{.address = 0xfe3ffd60, .name = "WDATU (Bus-through write data high)"},
{.address = 0xfe3ffd64, .name = "WDATL (Bus-through write data low)"},
{.address = 0xfe3ffd68, .name = "RDATU (Bus-through read data high)"},
{.address = 0xfe3ffd6c, .name = "RDATL (Bus-through read data low)"},
{.address = 0xfe3ffd70, .name = "BTCTRL (Bus-through mode control)"},
{.address = 0xfe3ffd74, .name = "SPUSTS (SPU status)"},
{.address = 0xfe3ffe00, .name = "SBAR0 (Source base address 0)"},
{.address = 0xfe3ffe04, .name = "SAR0 (Source address 0)"},
{.address = 0xfe3ffe08, .name = "DBAR0 (Destination base address 0)"},
{.address = 0xfe3ffe0c, .name = "DAR0 (Destination address 0)"},
{.address = 0xfe3ffe10, .name = "TCR0 (Transfer count 0)"},
{.address = 0xfe3ffe14, .name = "SHPRI0 (SHway priority 0)"},
{.address = 0xfe3ffe18, .name = "CHCR0 (Channel control 0)"},
{.address = 0xfe3ffe20, .name = "SBAR1 (Source base address 1)"},
{.address = 0xfe3ffe24, .name = "SAR1 (Source address 1)"},
{.address = 0xfe3ffe28, .name = "DBAR1 (Destination base address 1)"},
{.address = 0xfe3ffe2c, .name = "DAR1 (Destination address 1)"},
{.address = 0xfe3ffe30, .name = "TCR1 (Transfer count 1)"},
{.address = 0xfe3ffe34, .name = "SHPRI1 (SHway priority 1)"},
{.address = 0xfe3ffe38, .name = "CHCR1 (Channel control 1)"},
{.address = 0xfe3ffe40, .name = "SBAR2 (Source base address 2)"},
{.address = 0xfe3ffe44, .name = "SAR2 (Source address 2)"},
{.address = 0xfe3ffe48, .name = "DBAR2 (Destination base address 2)"},
{.address = 0xfe3ffe4c, .name = "DAR2 (Destination address 2)"},
{.address = 0xfe3ffe50, .name = "TCR2 (Transfer count 2)"},
{.address = 0xfe3ffe54, .name = "SHPRI2 (SHway priority 2)"},
{.address = 0xfe3ffe58, .name = "CHCR2 (Channel control 2)"},
{.address = 0xfe3ffe80, .name = "LSA0 (Loop start address 0)"},
{.address = 0xfe3ffe84, .name = "LEA0 (Loop end address 0)"},
{.address = 0xfe3ffe90, .name = "LSA1 (Loop start address 1)"},
{.address = 0xfe3ffe94, .name = "LEA1 (Loop end address 1)"},
{.address = 0xfe3ffea0, .name = "LSA2 (Loop start address 2)"},
{.address = 0xfe3ffea4, .name = "LEA2 (Loop end address 2)"},
// FSI - FIFO Serail interface
{.address = 0xfe3c0000, .name = "A_DO_FMT (A output serial format)"},
{.address = 0xfe3c0004, .name = "A_DOFF_CTL (A output FIFO control)"},
{.address = 0xfe3c0008, .name = "A_DOFF_ST (A output FIFO status)"},
{.address = 0xfe3c000c, .name = "A_DI_FMT (A input serial format)"},
{.address = 0xfe3c0010, .name = "A_DIFF_CTL (A input FIFO control)"},
{.address = 0xfe3c0014, .name = "A_DIFF_ST (A input FIFO status)"},
{.address = 0xfe3c0018, .name = "A_CKG1 (A clock set 1)"},
{.address = 0xfe3c001c, .name = "A_CKG2 (A clock set 2)"},
{.address = 0xfe3c0020, .name = "A_DIDT (A read data)"},
{.address = 0xfe3c0024, .name = "A_DODT (A write data)"},
{.address = 0xfe3c0028, .name = "A_MUTE_ST (A mute state)"},
{.address = 0xfe3c0040, .name = "B_DO_FMT (B output serial format)"},
{.address = 0xfe3c0044, .name = "B_DOFF_CTL (B output FIFO control)"},
{.address = 0xfe3c0048, .name = "B_DOFF_ST (B output FIFO status)"},
{.address = 0xfe3c004c, .name = "B_DI_FMT (B input serial format)"},
{.address = 0xfe3c0050, .name = "B_DIFF_CTL (B input FIFO contro)"},
{.address = 0xfe3c0054, .name = "B_DIFF_ST (B input FIFO status)"},
{.address = 0xfe3c0058, .name = "B_CKG1 (B clock set 1)"},
{.address = 0xfe3c005c, .name = "B_CKG2 (B clock set 2)"},
{.address = 0xfe3c0060, .name = "B_DIDT (B read data)"},
{.address = 0xfe3c0064, .name = "B_DODT (B write data)"},
{.address = 0xfe3c0068, .name = "B_MUTE_ST (B mute state)"},
{.address = 0xfe3c0200, .name = "INT_ST (Interrupt state)"},
{.address = 0xfe3c0204, .name = "IEMSK (Interrupt source mask)"},
{.address = 0xfe3c0208, .name = "IMSK (Interrupt signal mask)"},
{.address = 0xfe3c020c, .name = "MUTE (Mute set)"},
{.address = 0xfe3c0210, .name = "CLK_RST (Clock reset)"},
{.address = 0xfe3c0214, .name = "SOFT_RST (Software reset)"},
{.address = 0xfe3c0218, .name = "FIFO_SZ (FIFO size)"},
// stop
{.address = 0x00000000, .name = NULL},
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,330 @@
#include "gintrace/menu/disasm.h"
#include "gintrace/ubc.h"
#include "./src/menu/disassembler/dictionary.h"
#include <gint/std/string.h>
#include <gint/std/stdlib.h>
#include <gint/std/stdio.h>
#include <gint/display.h>
#include <gint/keyboard.h>
/* define the menu information */
/* TODO: find way to have local information */
struct tracer tracer;
//---
// Internal disassembler processing
//---
/* dhreverse(): Reverse horizotal area (TODO: move me !!) */
static void dhreverse(int ypos, size_t size)
{
#ifdef FXCG50
/* FIXME: border !!! */
uint32_t *long_vram;
int y1;
int y2;
y1 = ypos;
y2 = ypos + size;
long_vram = (void *)gint_vram;
for(int i = 198 * y1; i < 198 * y2; i++)
long_vram[i] = ~long_vram[i];
#endif
}
/* disasm_update_index(): Little helper to update the circular index */
static int disasm_update_index(int index, int direction)
{
/* update the counter */
if (direction > 0)
index = index - 1;
if (direction < 0)
index = index + 1;
/* check border */
if (index < 0)
index = (int)tracer.buffer.size.height - 1;
if (index >= (int)tracer.buffer.size.height)
index = 0;
/* return the index */
return (index);
}
/* disasm_check_special_addr(): Check if the address is special
*
* @note:
* mode & 1 -> check hardware module register
* mode & 2 -> check syscall address */
static void disasm_check_special_addr(char *buffer, void *address, int mode)
{
extern struct tracer tracer;
const char *addrname;
addrname = NULL;
if ((mode & 1) != 0)
addrname = disasm_dictionary_check_peripheral(address);
if (addrname == NULL && (mode & 2) != 0)
addrname = disasm_dictionary_check_syscalls(address);
if (addrname == NULL)
return;
snprintf(buffer, tracer.buffer.size.width,
"@note: %p -> %s\n", address, addrname);
}
/* disasm_get_mnemonic_info(): Get mnemonic information
*
* @note:
* line[0] -> "address opcode opcode_name"
* line[1] -> opcode address note
* line[2] -> first note (arg0)
* line[3] -> first note (arg1)
* line[4] -> first note (arg2) */
static void disasm_get_mnemonic_info(int line, uint16_t *pc)
{
const struct opcode *opcode_info;
uint16_t opcode;
uintptr_t arg[3];
/* Wipe note */
tracer.buffer.raw[line][0][0] = '\0';
tracer.buffer.raw[line][1][0] = '\0';
tracer.buffer.raw[line][2][0] = '\0';
tracer.buffer.raw[line][3][0] = '\0';
tracer.buffer.raw[line][4][0] = '\0';
/* check special address (register, syscall, ...) */
disasm_check_special_addr(tracer.buffer.raw[line][1], pc, 2);
/* generate the "default" information (only the address and word) */
snprintf(&tracer.buffer.raw[line][0][0],
tracer.buffer.size.width, "%.8lx %.4x ",
(uintptr_t)pc, (unsigned int)pc[0]);
/* Try to get the current opcode */
opcode = pc[0];
opcode_info = disasm_dictionary_check_opcode(opcode);
if (opcode_info == NULL) {
snprintf(&tracer.buffer.raw[line][0][14],
tracer.buffer.size.width - 14,
".word\t%#.4x", (int)opcode);
return;
}
/* get mnemonic arguments, if available */
for (int i = 0 ; i < 3 ; ++i) {
arg[i] = disasm_dictionary_opcode_get_arg(opcode_info,
opcode, i, pc);
if (arg[i] == 0x00000000)
continue;
disasm_check_special_addr(
tracer.buffer.raw[line][2 + i],
(void*)arg[i], 3
);
}
/* generate the complet mnemonic information */
snprintf(&tracer.buffer.raw[line][0][14],
tracer.buffer.size.width - 14,
opcode_info->name, arg[0], arg[1], arg[2]);
}
/* disasm_buffer_update(): Update the internal display buffer information */
static void disasm_buffer_update(void)
{
int direction;
size_t gap;
int line;
int pc;
/* first, we need to calculate the gaps between the current buffer's
* based anchor and the new memory information, then determine the
* direction */
direction = (intptr_t)(tracer.buffer.anchor - tracer.memory);
gap = (direction < 0) ? 0 - direction : direction;
if (gap > tracer.buffer.size.height) {
gap = tracer.buffer.size.height;
direction = -tracer.buffer.size.height;
}
if (gap == 0)
return;
/* update the virtual PC, used with the internal memory information.
* Note that we reach */
pc = gap - 1;
if (direction < 0)
pc = tracer.buffer.size.height - gap;
/* get the start line index */
line = tracer.buffer.cursor;
if (direction > 0)
line = disasm_update_index(tracer.buffer.cursor, direction);
/* update the internal buffer */
tracer.buffer.anchor = tracer.memory;
while ((signed)--gap >= 0) {
disasm_get_mnemonic_info(line, &tracer.buffer.anchor[pc]);
if (direction > 0)
tracer.buffer.cursor = line;
line = disasm_update_index(line, direction);
pc = (direction < 0) ? pc + 1 : pc - 1;
}
if (direction < 0)
tracer.buffer.cursor = line;
}
//---
// Menu functions
//---
/* disasm_ctor(): disasm menu constructor */
static void disasm_ctor(void)
{
memset(&tracer, 0x00, sizeof(struct tracer));
tracer.buffer.size.width = DISASM_NB_COLUMN * 2;
tracer.buffer.size.height = DISASM_NB_ROW * 2;
tracer.buffer.raw = calloc(sizeof(void*), tracer.buffer.size.height);
for (size_t i = 0; i < tracer.buffer.size.height; ++i) {
tracer.buffer.raw[i] = calloc(sizeof(char*), 5);
tracer.buffer.raw[i][0] = calloc(tracer.buffer.size.width, 1);
tracer.buffer.raw[i][1] = calloc(tracer.buffer.size.width, 1);
tracer.buffer.raw[i][2] = calloc(tracer.buffer.size.width, 1);
tracer.buffer.raw[i][3] = calloc(tracer.buffer.size.width, 1);
tracer.buffer.raw[i][4] = calloc(tracer.buffer.size.width, 1);
}
tracer.buffer.cursor = 0;
tracer.disp.hoffset = 0;
tracer.disp.voffset = 0;
}
/* disasm_dtor(): disasm menu destructor */
static void disasm_dtor(void)
{
if (tracer.buffer.raw != NULL) {
for (size_t i = 0; i < tracer.buffer.size.height; ++i) {
if (tracer.buffer.raw[i] == NULL)
continue;
free(tracer.buffer.raw[i][0]);
free(tracer.buffer.raw[i][1]);
free(tracer.buffer.raw[i][2]);
free(tracer.buffer.raw[i][3]);
free(tracer.buffer.raw[i][4]);
free(tracer.buffer.raw[i]);
}
free(tracer.buffer.raw);
}
memset(&tracer, 0x00, sizeof(struct tracer));
}
/* disasm_init(): Called each breakpoint, update the internal buffer */
static void disasm_init(struct ucontext *context)
{
tracer.memory = (void*)(uintptr_t)((context->spc + 3) & ~3);
tracer.next_break = context->spc;
tracer.next_instruction = context->spc;
tracer.spc = context->spc;
disasm_buffer_update();
}
/* disasm_display(); Display trace information */
static void disasm_display(struct ucontext *context)
{
int line;
int pc;
pc = 0;
line = tracer.buffer.cursor;
for (int row = 0; row < DISASM_NB_ROW; ++row) {
/* display notes and opcode information */
for (int i = 0; i < 4; ++i) {
if (tracer.buffer.raw[line][i + 1][0] == '\0')
continue;
drect(0, row * (FHEIGHT + 1) - 1, DWIDTH,
(row * (FHEIGHT + 1) - 1) + (FHEIGHT + 2),
0x556655);
dtext(tracer.disp.hoffset * (FWIDTH + 1),
row * (FHEIGHT + 1), C_WHITE,
tracer.buffer.raw[line][i + 1]);
row = row + 1;
if (row >= DISASM_NB_ROW)
return;
}
dtext(tracer.disp.hoffset * (FWIDTH + 1),
row * (FHEIGHT + 1), C_BLACK,
tracer.buffer.raw[line][0]);
/* highlight SPC if possible */
if ((uintptr_t)&tracer.buffer.anchor[pc] == context->spc)
dhreverse(row * (FHEIGHT + 1) - 1, FHEIGHT + 2);
/* draw next break / instruction */
if (tracer.next_break != context->spc
&& (uintptr_t)&tracer.buffer.anchor[pc] == tracer.next_break) {
dhline(row * (FHEIGHT + 1) - 1, C_BLACK);
dhline((row + 1) * (FHEIGHT + 1) - 1, C_BLACK);
}
/* update line position (circular buffer) */
line = line + 1;
if (line >= (int)tracer.buffer.size.height)
line = 0;
pc = pc + 1;
}
}
/* disasm_keyboard(): Handle one key event */
static int disasm_keyboard(struct ucontext *context, int key)
{
/* horizontal update */
if (key == KEY_LEFT)
tracer.disp.hoffset += 1;
if (key == KEY_RIGHT)
tracer.disp.hoffset -= 1;
/* vertical update */
if (key == KEY_UP) {
tracer.memory = &tracer.memory[-1];
disasm_buffer_update();
}
if (key == KEY_DOWN) {
tracer.memory = &tracer.memory[1];
disasm_buffer_update();
}
/* move break point */
if (key == KEY_PLUS)
tracer.next_break += 2;
if (key == KEY_MINUS)
tracer.next_break -= 2;
/* skip instruction */
if (key == KEY_OPTN) {
context->spc = tracer.next_break;
ubc_set_breakpoint(0, (void*)tracer.next_break, NULL);
return (1);
}
/* go to net break point */
if (key == KEY_EXE) {
ubc_set_breakpoint(0, (void*)tracer.next_break, NULL);
return (1);
}
return(0);
}
//---
// Define the menu
//---
struct menu menu_disasm = {
.ctor = &disasm_ctor,
.init = &disasm_init,
.display = &disasm_display,
.keyboard = &disasm_keyboard,
.command = NULL,
.dtor = &disasm_dtor
};

132
src/ubc/kernel.S Normal file
View File

@ -0,0 +1,132 @@
.section .gint.mapped, "ax"
.align 2
.global _ubc_kernel_inth_reloc
/* ubc_kernel_inth_reloc(): Relocalised UBC handler */
_ubc_kernel_inth_reloc:
! Generate "programme" context (used by the UBC handler)
sts.l pr, @-r15
stc.l spc, @-r15
stc.l ssr, @-r15
sts.l mach, @-r15
sts.l macl, @-r15
stc.l gbr, @-r15
.word 0b0100111100110010 ! SH4 intruction "stc.l sgr, @-r15"
mov.l r14, @-r15
mov.l r13, @-r15
mov.l r12, @-r15
mov.l r11, @-r15
mov.l r10, @-r15
mov.l r9, @-r15
mov.l r8, @-r15
stc.l R7_BANK, @-r15
stc.l R6_BANK, @-r15
stc.l R5_BANK, @-r15
stc.l R4_BANK, @-r15
stc.l R3_BANK, @-r15
stc.l R2_BANK, @-r15
stc.l R1_BANK, @-r15
stc.l R0_BANK, @-r15
! Get which channel is trigger and clear interrupt flags.
mov.l ubc_ccmfr_reg, r0
mov.l @r0, r9
mov #0, r1
mov.l r1, @r0
mov.l icbi_addr, r2
.word 0b0000001011100011 ! SH4 instruction "icbi @r2"
! Allow / unblock interrupt and switch register bank !
stc sr, r8
mov r8, r1
mov.l sr_mask, r0
and r0, r1
ldc r1, sr
! Call high-level abstraction
mov r15, r4
mov r9, r5
mov.l ubc_handler, r0
mov.l @r0, r0
tst r0, r0
bt ubc_kernel_inth_prologue
jsr @r0
nop
ubc_kernel_inth_prologue:
! force SR register
ldc r8, sr
! Restore "program" context.
ldc.l @r15+, R0_BANK
ldc.l @r15+, R1_BANK
ldc.l @r15+, R2_BANK
ldc.l @r15+, R3_BANK
ldc.l @r15+, R4_BANK
ldc.l @r15+, R5_BANK
ldc.l @r15+, R6_BANK
ldc.l @r15+, R7_BANK
mov.l @r15+, r8
mov.l @r15+, r9
mov.l @r15+, r10
mov.l @r15+, r11
mov.l @r15+, r12
mov.l @r15+, r13
mov.l @r15+, r14
.word 0b0100111100110110 ! SH4 intruction "ldc.l @r15+, sgr"
ldc.l @r15+, gbr
lds.l @r15+, macl
lds.l @r15+, mach
ldc.l @r15+, ssr
ldc.l @r15+, spc
lds.l @r15+, pr
! Clean exit.
rte ! Interrupt Exit.
nop ! (db) Safety first.
.align 4
ubc_handler: .long _ubc_handler
ubc_ccmfr_reg: .long 0xff200600
icbi_addr: .long 0xa0000000
sr_mask: .long ~0x300000f0
/* gint mecanism to store relocalised information */
.section .gint.mappedrel, "awx"
.align 2
.global _ubc_kernel_inth
_ubc_kernel_inth:
.long _ubc_kernel_inth_reloc
.text
.global _ubc_kernel_dbr_set
.global _ubc_kernel_dbr_get
.global _ubc_kernel_update
/* ubc_kernel_dbr_set(): switch the DBR address */
_ubc_kernel_dbr_set:
.word 0b0000000011111010 ! SH4 intruction "stc dbr, r0"
.word 0b0100010011111010 ! SH4 intruction "ldc r4, dbr"
rts
nop
/* ubc_kernel_dbr_get(): get the DBR address */
_ubc_kernel_dbr_get:
.word 0b0000000011111010 ! SH4 intruction "stc dbr, r0"
rts
nop
/* _ubc_kernel_update(): When the UBC is modified, we should involve icbi int*/
_ubc_kernel_update:
mov #0xa0, r4
shll8 r4
shll16 r4
.word 0b0000010011100011 ! SH4 intstruction "icbi @r4"
rts
nop

96
src/ubc/ubc.c Normal file
View File

@ -0,0 +1,96 @@
#include "gintrace/ubc.h"
#include <gint/mpu/power.h>
/* internal saved driver state */
struct sh7305_ubc_context ubctx;
void (*ubc_handler)(struct ucontext *ctx) = NULL;
int ubc_driver_installed = 0;
/* ubc_install(): Install the UBC driver */
void ubc_install(void)
{
/* power on the UBC */
SH7305_POWER.MSTPCR0.UDB = 0;
/* switch the DBR */
ubc_kernel_dbr_set(*ubc_kernel_inth);
/* check if the driver has already been installed */
if (ubc_driver_installed != 0) {
SH7305_UBC.CBR0.lword = ubctx.cbr0;
SH7305_UBC.CRR0.lword = ubctx.crr0;
SH7305_UBC.CAR0 = ubctx.car0;
SH7305_UBC.CAMR0 = ubctx.camr0;
SH7305_UBC.CBR1.lword = ubctx.cbr1;
SH7305_UBC.CRR1.lword = ubctx.crr1;
SH7305_UBC.CAR1 = ubctx.car1;
SH7305_UBC.CAMR1 = ubctx.camr1;
SH7305_UBC.CDR1 = ubctx.cdr1;
SH7305_UBC.CDMR1 = ubctx.cdmr1;
SH7305_UBC.CETR1.lword = ubctx.cdr1;
return;
}
/* wipe sofware information */
ubc_handler = NULL;
/* Default initialization */
SH7305_UBC.CBR0.MFI = 0b000000;
SH7305_UBC.CBR0.CE = 0;
SH7305_UBC.CBR1.MFI = 0b000000;
SH7305_UBC.CBR1.CE = 0;
SH7305_UBC.CBCR.UBDE = 1;
/* indicate that the UBC driver is installed */
ubc_driver_installed = 1;
}
/* ubc_uninstall(): Uninstall the UBC driver */
void ubc_uninstall(void)
{
ubctx.cbr0 = SH7305_UBC.CBR0.lword;
ubctx.crr0 = SH7305_UBC.CRR0.lword;
ubctx.car0 = SH7305_UBC.CAR0;
ubctx.camr0 = SH7305_UBC.CAMR0;
ubctx.cbr1 = SH7305_UBC.CBR1.lword;
ubctx.crr1 = SH7305_UBC.CRR1.lword;
ubctx.car1 = SH7305_UBC.CAR1;
ubctx.camr1 = SH7305_UBC.CAMR1;
ubctx.cdr1 = SH7305_UBC.CDR1;
ubctx.cdmr1 = SH7305_UBC.CDMR1;
ubctx.cdr1 = SH7305_UBC.CETR1.lword;
}
/* ubc_set_breakpoint(): Setup one breakpoint */
int ubc_set_breakpoint(int channel, void *address, void *mask)
{
if (channel == 0) {
// Setup Channel 0.
SH7305_UBC.CRR0.PCB = 1; // Set PC break after 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.
SH7305_UBC.CAR0 = (uintptr_t)address; // update break address.
SH7305_UBC.CAMR0 = (uintptr_t)mask; // update break address.
SH7305_UBC.CBR0.CE = 1; // enable channel.
} else {
//TODO
return (-1);
}
ubc_kernel_update();
return (0);
}
/* ubc_set_handler(): Set the "user" handler */
int ubc_set_handler(void (*handler)(struct ucontext *ctxt))
{
ubc_handler = handler;
return (0);
}