From dafa515e4ff8bab45e312eed7f5ef10a75b54e34 Mon Sep 17 00:00:00 2001 From: Polprzewodnikowy Date: Fri, 7 Jan 2022 15:01:43 +0100 Subject: [PATCH] exception --- .vscode/tasks.json | 12 +++ sw/n64/Makefile | 4 +- sw/n64/N64.ld | 12 ++- sw/n64/src/exception.S | 136 ++++++++++++++++++++++++ sw/n64/src/exception.c | 234 +++++++++++++++++++++++++++++++++++++++++ sw/n64/src/exception.h | 57 ++++++++++ sw/n64/src/main.c | 3 +- sw/n64/src/sc64.c | 31 ++++-- sw/n64/src/sc64.h | 14 +-- sw/n64/src/startup.S | 4 +- sw/n64/src/storage.c | 2 + sw/n64/src/sys.c | 30 ++---- sw/n64/src/sys.h | 60 +++++------ 13 files changed, 523 insertions(+), 76 deletions(-) create mode 100644 sw/n64/src/exception.S create mode 100644 sw/n64/src/exception.c create mode 100644 sw/n64/src/exception.h diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 13088f3..463d8c3 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -5,6 +5,10 @@ "label": "build", "type": "shell", "command": "./docker_build.sh update -s -c -d", + "presentation": { + "showReuseMessage": false, + "clear": true + }, "windows":{ "command": "wsl -- ./docker_build.sh update -s -c -d" }, @@ -17,6 +21,10 @@ "label": "build_full", "type": "shell", "command": "./docker_build.sh release -c -d", + "presentation": { + "showReuseMessage": false, + "clear": true + }, "windows": { "command": "wsl -- ./docker_build.sh update -c -d" }, @@ -26,6 +34,10 @@ "label": "build_n64_bootloader", "type": "shell", "command": "./docker_build.sh n64 -d", + "presentation": { + "showReuseMessage": false, + "clear": true + }, "windows": { "command": "wsl -- ./docker_build.sh n64 -d" }, diff --git a/sw/n64/Makefile b/sw/n64/Makefile index d70114c..55310de 100644 --- a/sw/n64/Makefile +++ b/sw/n64/Makefile @@ -6,7 +6,7 @@ OBJDUMP = $(TOOLCHAIN)objdump SIZE = $(TOOLCHAIN)size FLAGS = -march=vr4300 -mtune=vr4300 -falign-functions=32 $(USER_FLAGS) -CFLAGS = -Os -Wall -ffunction-sections -fdata-sections -ffreestanding -MMD -MP +CFLAGS = -O2 -Wall -ffunction-sections -fdata-sections -ffreestanding -MMD -MP ASFLAGS = -Wa,-I$(N64_INST)/mips64-elf/lib LDFLAGS = -lc -nostartfiles -Wl,--gc-sections @@ -15,8 +15,10 @@ BUILD_DIR = build SRC_FILES = \ startup.S \ + exception.S \ boot.c \ crc32.c \ + exception.c \ init.c \ main.c \ sc64.c \ diff --git a/sw/n64/N64.ld b/sw/n64/N64.ld index f69881b..09f7f0f 100644 --- a/sw/n64/N64.ld +++ b/sw/n64/N64.ld @@ -1,10 +1,11 @@ MEMORY { - rdram (rwx) : org = 0x80000400, len = 4M - 0x400 + rdram (rwx) : org = 0x80300000, len = 1M flash (r) : org = 0xB0000000, len = 90k } ENTRY(entry_handler) +__exception_stack_size = 8k; __stack_size = 64k; SECTIONS { @@ -22,7 +23,7 @@ SECTIONS { _gp = . + 0x8000; *(.sdata .sdata.* .gnu.linkonce.s.*) *(.lit8 .lit4) - . = ALIGN(4); + . = ALIGN(8); } > rdram AT > flash .bss : { @@ -30,13 +31,16 @@ SECTIONS { *(.scommon .scommon.*) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) - . = ALIGN(4); + . = ALIGN(8); } > rdram _sheap = .; - . = ORIGIN(rdram) + LENGTH(rdram) - __stack_size; + . = ORIGIN(rdram) + LENGTH(rdram) - __exception_stack_size - __stack_size; _eheap = .; + . += __exception_stack_size; + _esp = .; + . += __stack_size; _sp = .; diff --git a/sw/n64/src/exception.S b/sw/n64/src/exception.S new file mode 100644 index 0000000..f68f61f --- /dev/null +++ b/sw/n64/src/exception.S @@ -0,0 +1,136 @@ +#include "exception.h" + + +.section .text.exception_handler +exception_handler: + .set noat + la $k0, (_esp - SAVE_REGISTERS_SIZE) + sd $at, AT_OFFSET($k0) + sd $v0, V0_OFFSET($k0) + sd $v1, V1_OFFSET($k0) + sd $a0, A0_OFFSET($k0) + sd $a1, A1_OFFSET($k0) + sd $a2, A2_OFFSET($k0) + sd $a3, A3_OFFSET($k0) + sd $t0, T0_OFFSET($k0) + sd $t1, T1_OFFSET($k0) + sd $t2, T2_OFFSET($k0) + sd $t3, T3_OFFSET($k0) + sd $t4, T4_OFFSET($k0) + sd $t5, T5_OFFSET($k0) + sd $t6, T6_OFFSET($k0) + sd $t7, T7_OFFSET($k0) + sd $s0, S0_OFFSET($k0) + sd $s1, S1_OFFSET($k0) + sd $s2, S2_OFFSET($k0) + sd $s3, S3_OFFSET($k0) + sd $s4, S4_OFFSET($k0) + sd $s5, S5_OFFSET($k0) + sd $s6, S6_OFFSET($k0) + sd $s7, S7_OFFSET($k0) + sd $t8, T8_OFFSET($k0) + sd $t9, T9_OFFSET($k0) + sd $gp, GP_OFFSET($k0) + sd $sp, SP_OFFSET($k0) + sd $fp, FP_OFFSET($k0) + sd $ra, RA_OFFSET($k0) + .set at + + move $sp, $k0 + +exception_is_fatal: + mfc0 $a0, C0_CAUSE + sw $a0, C0_CAUSE_OFFSET($k0) + move $a1, $a0 + andi $a1, EXCEPTION_CODE_MASK + srl $a1, $a1, EXCEPTION_CODE_BIT + beq $a1, $zero, exception_interrupt + +exception_fatal: + sd $k0, K0_OFFSET($k0) + sd $k1, K1_OFFSET($k0) + mfc0 $t0, C0_STATUS + sw $t0, C0_STATUS_OFFSET($k0) + dmfc0 $t0, C0_EPC + sd $t0, C0_EPC_OFFSET($k0) + addiu $t0, 4 + dmtc0 $t0, C0_EPC + move $a0, $k0 + la $t1, exception_fatal_handler + jalr $t1 + j exception_restore + +exception_interrupt: + andi $a0, INTERRUPT_PENDING_MASK + srl $a0, $a0, INTERRUPT_PENDING_BIT + la $t1, exception_interrupt_handler + jalr $t1 + +exception_restore: + .set noat + ld $at, AT_OFFSET($k0) + ld $v0, V0_OFFSET($k0) + ld $v1, V1_OFFSET($k0) + ld $a0, A0_OFFSET($k0) + ld $a1, A1_OFFSET($k0) + ld $a2, A2_OFFSET($k0) + ld $a3, A3_OFFSET($k0) + ld $t0, T0_OFFSET($k0) + ld $t1, T1_OFFSET($k0) + ld $t2, T2_OFFSET($k0) + ld $t3, T3_OFFSET($k0) + ld $t4, T4_OFFSET($k0) + ld $t5, T5_OFFSET($k0) + ld $t6, T6_OFFSET($k0) + ld $t7, T7_OFFSET($k0) + ld $s0, S0_OFFSET($k0) + ld $s1, S1_OFFSET($k0) + ld $s2, S2_OFFSET($k0) + ld $s3, S3_OFFSET($k0) + ld $s4, S4_OFFSET($k0) + ld $s5, S5_OFFSET($k0) + ld $s6, S6_OFFSET($k0) + ld $s7, S7_OFFSET($k0) + ld $t8, T8_OFFSET($k0) + ld $t9, T9_OFFSET($k0) + ld $gp, GP_OFFSET($k0) + ld $sp, SP_OFFSET($k0) + ld $fp, FP_OFFSET($k0) + ld $ra, RA_OFFSET($k0) + .set at + + eret + + +.section .text.exception_vector +exception_vector: + .set noreorder + la $k0, exception_handler + jalr $k1, $k0 + nop + .equ exception_vector_size, (. - exception_vector) + .set reorder + + +.section .text.exception_install +exception_install: + .global exception_install + la $t0, exception_vector + li $t1, VECTOR_LOCATION + li $t2, (VECTOR_SIZE * VECTOR_NUM) + add $t2, $t2, $t1 +1: + move $t3, $t0 + move $t4, $t1 + li $t5, exception_vector_size + add $t5, $t5, $t4 +2: + lw $t6, 0($t3) + sw $t6, 0($t4) + cache HIT_INVALIDATE_I, 0($t4) + addiu $t3, 4 + addiu $t4, 4 + bne $t4, $t5, 2b + addiu $t1, VECTOR_SIZE + bne $t1, $t2, 1b + jr $ra diff --git a/sw/n64/src/exception.c b/sw/n64/src/exception.c new file mode 100644 index 0000000..9d278d8 --- /dev/null +++ b/sw/n64/src/exception.c @@ -0,0 +1,234 @@ +#include +#include +#include "boot.h" +#include "exception.h" +#include "sc64.h" +#include "sys.h" + + +extern io32_t __ipl3_font __attribute__((section(".data"))); + + +#define SCREEN_WIDTH (640) +#define SCREEN_HEIGHT (240) + +#define BACKGROUND_COLOR (0xFFFFFFFFUL) +#define FOREGROUND_COLOR (0x000000FFUL) + +#define CHARACTER_WIDTH (13) +#define CHARACTER_HEIGHT (14) +#define CHARACTER_SIZE (23) + +#define LINE_HEIGHT (22) + + +static const vi_regs_t vi_config[] = {{ + .CR = VI_CR_TYPE_32, + .MADDR = 0x00200000UL, + .H_WIDTH = SCREEN_WIDTH, + .V_INTR = 512, + .CURR_LINE = 0, + .TIMING = 0x0404233A, + .V_SYNC = 625, + .H_SYNC = 0x00150C69, + .H_SYNC_LEAP = 0x0C6F0C6E, + .H_LIMITS = 0x00800300, + .V_LIMITS = 0x005F0239, + .COLOR_BURST = 0x00090268, + .H_SCALE = ((0x100 * SCREEN_WIDTH) / 160), + .V_SCALE = ((0x100 * SCREEN_HEIGHT) / 60), +}, { + .CR = VI_CR_TYPE_32, + .MADDR = 0x00200000UL, + .H_WIDTH = SCREEN_WIDTH, + .V_INTR = 512, + .CURR_LINE = 0, + .TIMING = 0x03E52239, + .V_SYNC = 525, + .H_SYNC = 0x00000C15, + .H_SYNC_LEAP = 0x0C150C15, + .H_LIMITS = 0x006C02EC, + .V_LIMITS = 0x002501FF, + .COLOR_BURST = 0x000E0204, + .H_SCALE = ((0x100 * SCREEN_WIDTH) / 160), + .V_SCALE = ((0x100 * SCREEN_HEIGHT) / 60), +}}; + +static const uint8_t exception_font_mapping[96] = { + 48, 36, 37, 38, 48, 48, 48, 39, 48, 48, 40, 41, 42, 43, 44, 45, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 46, 48, 48, 47, 48, 48, + 49, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 48, 48, 48, 48, 48, + 48, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 48, 48, 48, 48, 48, +}; + +static io32_t *exception_framebuffer; +static uint32_t exception_font_buffer[288]; + + +static void exception_init_screen (void) { + const vi_regs_t *cfg = &vi_config[OS_INFO->tv_type]; + + io32_t *src = &__ipl3_font; + uint32_t *dst = exception_font_buffer; + + bool sdram_switched = sc64_get_config(CFG_ID_SDRAM_SWITCH); + + if (sdram_switched) { + sc64_set_config(CFG_ID_SDRAM_SWITCH, false); + } + + for (int i = 0; i < sizeof(exception_font_buffer); i += 4) { + *dst++ = pi_io_read(src++); + } + + if (sdram_switched) { + sc64_set_config(CFG_ID_SDRAM_SWITCH, true); + } + + exception_framebuffer = (io32_t *) (cfg->MADDR); + + for (int i = 0; i < (SCREEN_WIDTH * SCREEN_HEIGHT); i++) { + io_write(exception_framebuffer + i, BACKGROUND_COLOR); + } + + io_write(&VI->MADDR, cfg->MADDR); + io_write(&VI->H_WIDTH, cfg->H_WIDTH); + io_write(&VI->V_INTR, cfg->V_INTR); + io_write(&VI->CURR_LINE, cfg->CURR_LINE); + io_write(&VI->TIMING, cfg->TIMING); + io_write(&VI->V_SYNC, cfg->V_SYNC); + io_write(&VI->H_SYNC, cfg->H_SYNC); + io_write(&VI->H_SYNC_LEAP, cfg->H_SYNC_LEAP); + io_write(&VI->H_LIMITS, cfg->H_LIMITS); + io_write(&VI->V_LIMITS, cfg->V_LIMITS); + io_write(&VI->COLOR_BURST, cfg->COLOR_BURST); + io_write(&VI->H_SCALE, cfg->H_SCALE); + io_write(&VI->V_SCALE, cfg->V_SCALE); + io_write(&VI->CR, cfg->CR); +} + + +static void exception_draw_character (int x, int y, char c) { + if ((c <= 32) || (c >= 127)) { + return; + } + + uint8_t index = exception_font_mapping[c - 32]; + uint8_t *character = ((uint8_t *) (exception_font_buffer)) + (index * CHARACTER_SIZE); + + for (int i = 0; i < (CHARACTER_WIDTH * CHARACTER_HEIGHT); i++) { + int c_x = x + (i % CHARACTER_WIDTH); + int c_y = y + (i / CHARACTER_WIDTH); + + if ((c_x >= SCREEN_WIDTH) || (c_y >= SCREEN_HEIGHT)) { + break; + } + + if (character[i / 8] & (1 << (7 - (i % 8)))) { + int screen_offset = c_x + (c_y * SCREEN_WIDTH); + io_write(&exception_framebuffer[screen_offset], FOREGROUND_COLOR); + } + } +} + +static void exception_print_string (int x, int y, const char *s) { + while (*s != '\0') { + exception_draw_character(x, y, *s++); + x += CHARACTER_WIDTH; + } +} + +static void exception_print (int *x, int *y, const char* fmt, ...) { + char line[64]; + va_list args; + + va_start(args, fmt); + + vsniprintf(line, sizeof(line), fmt, args); + exception_print_string(*x, *y, line); + *y += LINE_HEIGHT; + + va_end(args); +} + +static const char *exception_get_description (uint8_t exception_code) { + switch (exception_code) { + case 1: return "TLB Modification exception"; + case 2: return "TLB Miss exception (load or instruction fetch)"; + case 3: return "TLB Miss exception (store)"; + case 4: return "Address Error exception (load or instruction fetch)"; + case 5: return "Address Error exception (store)"; + case 6: return "Bus Error exception (instruction fetch)"; + case 7: return "Bus Error exception (data reference: load or store)"; + case 8: return "Syscall exception"; + case 9: return "Breakpoint exception"; + case 10: return "Reserved Instruction exception"; + case 11: return "Coprocessor Unusable exception"; + case 12: return "Arithmetic Overflow exception"; + case 13: return "Trap exception"; + case 15: return "Floating-Point exception"; + case 23: return "Watch exception"; + } + + return "Unknown exception"; +} + + +typedef struct { + uint64_t gpr[32]; + uint32_t sr; + uint32_t cr; + uint64_t epc; +} exception_t; + + +void exception_fatal_handler (exception_t *e) { + uint8_t exception_code = (uint8_t) ((e->cr & EXCEPTION_CODE_MASK) >> EXCEPTION_CODE_BIT); + const char *exception_description = exception_get_description(exception_code); + + exception_init_screen(); + + uint32_t gpr32[32]; + + for (int i = 0; i < 32; i++) { + gpr32[i] = (uint32_t) (e->gpr[i]); + } + + int x = 12; + int y = 8; + + exception_print(&x, &y, "%s", exception_description); + exception_print(&x, &y, "pc %08lX sr %08lX cr %08lX", (uint32_t) (e->epc), e->sr, e->cr); + exception_print(&x, &y, "zr %08lX at %08lX v0 %08lX v1 %08lX", gpr32[0], gpr32[1], gpr32[2], gpr32[3]); + exception_print(&x, &y, "a0 %08lX a1 %08lX a2 %08lX a3 %08lX", gpr32[4], gpr32[5], gpr32[6], gpr32[7]); + exception_print(&x, &y, "t0 %08lX t1 %08lX t2 %08lX t3 %08lX", gpr32[8], gpr32[9], gpr32[10], gpr32[11]); + exception_print(&x, &y, "t4 %08lX t5 %08lX t6 %08lX t7 %08lX", gpr32[12], gpr32[13], gpr32[14], gpr32[15]); + exception_print(&x, &y, "s0 %08lX s1 %08lX s2 %08lX s3 %08lX", gpr32[16], gpr32[17], gpr32[18], gpr32[19]); + exception_print(&x, &y, "s4 %08lX s5 %08lX s6 %08lX s7 %08lX", gpr32[20], gpr32[21], gpr32[22], gpr32[23]); + exception_print(&x, &y, "t8 %08lX t9 %08lX k0 %08lX k1 %08lX", gpr32[24], gpr32[25], gpr32[26], gpr32[27]); + exception_print(&x, &y, "gp %08lX sp %08lX fp %08lX ra %08lX", gpr32[28], gpr32[29], gpr32[30], gpr32[31]); + + LOG_E("%s\r\n", exception_description); + LOG_E("pc: 0x%08lX, sr: 0x%08lX, cr: 0x%08lX\r\n", (uint32_t) (e->epc), e->sr, e->cr); + LOG_E("zr: 0x%08lX, at: 0x%08lX, v0: 0x%08lX, v1: 0x%08lX\r\n", gpr32[0], gpr32[1], gpr32[2], gpr32[3]); + LOG_E("a0: 0x%08lX, a1: 0x%08lX, a2: 0x%08lX, a3: 0x%08lX\r\n", gpr32[4], gpr32[5], gpr32[6], gpr32[7]); + LOG_E("t0: 0x%08lX, t1: 0x%08lX, t2: 0x%08lX, t3: 0x%08lX\r\n", gpr32[8], gpr32[9], gpr32[10], gpr32[11]); + LOG_E("t4: 0x%08lX, t5: 0x%08lX, t6: 0x%08lX, t7: 0x%08lX\r\n", gpr32[12], gpr32[13], gpr32[14], gpr32[15]); + LOG_E("s0: 0x%08lX, s1: 0x%08lX, s2: 0x%08lX, s3: 0x%08lX\r\n", gpr32[16], gpr32[17], gpr32[18], gpr32[19]); + LOG_E("s4: 0x%08lX, s5: 0x%08lX, s6: 0x%08lX, s7: 0x%08lX\r\n", gpr32[20], gpr32[21], gpr32[22], gpr32[23]); + LOG_E("t8: 0x%08lX, t9: 0x%08lX, k0: 0x%08lX, k1: 0x%08lX\r\n", gpr32[24], gpr32[25], gpr32[26], gpr32[27]); + LOG_E("gp: 0x%08lX, sp: 0x%08lX, fp: 0x%08lX, ra: 0x%08lX\r\n", gpr32[28], gpr32[29], gpr32[30], gpr32[31]); + LOG_FLUSH(); + + while (1); +} + + +void exception_interrupt_handler (uint32_t interrupt) { + LOG_I("Unimplemented interrupt, mask: 0x%08lX\r\n", interrupt); + LOG_FLUSH(); + + while (1); +} diff --git a/sw/n64/src/exception.h b/sw/n64/src/exception.h new file mode 100644 index 0000000..ce522d1 --- /dev/null +++ b/sw/n64/src/exception.h @@ -0,0 +1,57 @@ +#ifndef EXCEPTION_H__ +#define EXCEPTION_H__ + + +#define VECTOR_LOCATION (0xA0000000) +#define VECTOR_SIZE (0x80) +#define VECTOR_NUM (4) + +#define HIT_INVALIDATE_I ((4 << 2) | 0) + +#define C0_STATUS $12 +#define C0_CAUSE $13 +#define C0_EPC $14 + +#define EXCEPTION_CODE_BIT (2) +#define EXCEPTION_CODE_MASK (0x007C) +#define INTERRUPT_PENDING_BIT (8) +#define INTERRUPT_PENDING_MASK (0xFF00) + +#define AT_OFFSET (8) +#define V0_OFFSET (16) +#define V1_OFFSET (24) +#define A0_OFFSET (32) +#define A1_OFFSET (40) +#define A2_OFFSET (48) +#define A3_OFFSET (56) +#define T0_OFFSET (64) +#define T1_OFFSET (72) +#define T2_OFFSET (80) +#define T3_OFFSET (88) +#define T4_OFFSET (96) +#define T5_OFFSET (104) +#define T6_OFFSET (112) +#define T7_OFFSET (120) +#define S0_OFFSET (128) +#define S1_OFFSET (136) +#define S2_OFFSET (144) +#define S3_OFFSET (152) +#define S4_OFFSET (160) +#define S5_OFFSET (168) +#define S6_OFFSET (176) +#define S7_OFFSET (184) +#define T8_OFFSET (192) +#define T9_OFFSET (200) +#define K0_OFFSET (208) +#define K1_OFFSET (216) +#define GP_OFFSET (224) +#define SP_OFFSET (232) +#define FP_OFFSET (240) +#define RA_OFFSET (248) +#define C0_STATUS_OFFSET (256) +#define C0_CAUSE_OFFSET (260) +#define C0_EPC_OFFSET (264) +#define SAVE_REGISTERS_SIZE (272) + + +#endif diff --git a/sw/n64/src/main.c b/sw/n64/src/main.c index 509df70..2328a24 100644 --- a/sw/n64/src/main.c +++ b/sw/n64/src/main.c @@ -70,7 +70,8 @@ void main (void) { sc64_init_is_viewer(); } - LOG_I("Booting IPL3\033[0m\r\n\r\n"); + LOG_I("Booting IPL3\r\n\r\n"); + LOG_FLUSH(); boot(&boot_info); } diff --git a/sw/n64/src/sc64.c b/sw/n64/src/sc64.c index 5598781..d57dcad 100644 --- a/sw/n64/src/sc64.c +++ b/sw/n64/src/sc64.c @@ -51,9 +51,10 @@ void sc64_set_config (cfg_id_t id, uint32_t value) { } void sc64_get_info (sc64_info_t *info) { + uint32_t tmp; io32_t *src = (io32_t *) UNCACHED(&header_text_info); - uint32_t *dst = (uint32_t *) info->bootloader_version; - + char *dst = info->bootloader_version; + bool sdram_switched = sc64_get_config(CFG_ID_SDRAM_SWITCH); if (sdram_switched) { @@ -61,7 +62,11 @@ void sc64_get_info (sc64_info_t *info) { } for (int i = 0; i < sizeof(info->bootloader_version); i += sizeof(uint32_t)) { - *dst++ = pi_io_read(src++); + tmp = pi_io_read(src++); + *dst++ = (tmp >> 24); + *dst++ = (tmp >> 16); + *dst++ = (tmp >> 8); + *dst++ = (tmp & 0xFF); } if (sdram_switched) { @@ -117,7 +122,8 @@ void sc64_debug_write (uint8_t type, const void *data, uint32_t len) { io32_t *sdram = (io32_t *) (SC64_DEBUG_WRITE_ADDRESS); - uint32_t *src = (uint32_t *) (data); + uint8_t *src = (uint8_t *) (data); + uint32_t tmp; io32_t *dst = sdram; uint32_t copy_length = ALIGN(len, 4); @@ -137,8 +143,12 @@ void sc64_debug_write (uint8_t type, const void *data, uint32_t len) { pi_io_write(dst++, *((uint32_t *) (dma))); pi_io_write(dst++, (type << 24) | len); - while (src < ((uint32_t *) (data + copy_length))) { - pi_io_write(dst++, *src++); + while (src < ((uint8_t *) (data + copy_length))) { + tmp = ((*src++) << 24); + tmp |= ((*src++) << 16); + tmp |= ((*src++) << 8); + tmp |= ((*src++) << 0); + pi_io_write(dst++, tmp); if (dst >= (io32_t *) ((void *) (sdram) + SC64_DEBUG_MAX_SIZE)) { sc64_usb_tx_data(sdram, (dst - sdram) * sizeof(uint32_t)); sc64_wait_usb_tx_ready(); @@ -165,7 +175,8 @@ void sc64_debug_fsd_read (const void *data, uint32_t sector, uint32_t count) { io32_t *sdram = (io32_t *) (SC64_DEBUG_READ_ADDRESS); io32_t *src = sdram; - uint32_t *dst = (uint32_t *) (data); + uint32_t tmp; + uint8_t *dst = (uint8_t *) (data); uint32_t read_length = count * 512; @@ -184,7 +195,11 @@ void sc64_debug_fsd_read (const void *data, uint32_t sector, uint32_t count) { } for (int i = 0; i < copy_length; i += 4) { - *dst++ = pi_io_read(src++); + tmp = pi_io_read(src++); + *dst++ = (tmp >> 24); + *dst++ = (tmp >> 16); + *dst++ = (tmp >> 8); + *dst++ = (tmp & 0xFF); } if (!sdram_switched) { diff --git a/sw/n64/src/sc64.h b/sw/n64/src/sc64.h index de42ea3..14dbc4c 100644 --- a/sw/n64/src/sc64.h +++ b/sw/n64/src/sc64.h @@ -10,11 +10,13 @@ #ifdef DEBUG #include -#define LOG_I(args...) {iprintf("\033[32m" args);} -#define LOG_E(args...) {iprintf("\033[31m" args);} +#define LOG_I(args...) {iprintf("\033[32m"); iprintf(args); iprintf("\033[0m");} +#define LOG_E(args...) {iprintf("\033[31m"); iprintf(args); iprintf("\033[0m");} +#define LOG_FLUSH() {fflush(stdout);} #else #define LOG_I(args...) #define LOG_E(args...) +#define LOG_FLUSH() #define assert(expr) #endif @@ -99,13 +101,13 @@ typedef enum { typedef struct { bool dd_enabled; - bool is_viewer_enabled; // investigate why it breaks when put before bootloader_version save_type_t save_type; uint16_t cic_seed; tv_type_t tv_type; io32_t *save_location; io32_t *ddipl_location; boot_mode_t boot_mode; + bool is_viewer_enabled; char bootloader_version[32]; } sc64_info_t; @@ -117,9 +119,9 @@ bool sc64_perform_cmd (uint8_t cmd, uint32_t *args, uint32_t *result); uint32_t sc64_get_config (cfg_id_t id); void sc64_set_config (cfg_id_t id, uint32_t value); void sc64_get_info (sc64_info_t *info); -void sc64_wait_usb_rx_ready (uint32_t *type, uint32_t *length); -void sc64_wait_usb_rx_busy (void); -void sc64_usb_rx_data (io32_t *address, uint32_t length); +void sc64_wait_usb_rx_ready (uint32_t *type, uint32_t *length); +void sc64_wait_usb_rx_busy (void); +void sc64_usb_rx_data (io32_t *address, uint32_t length); void sc64_wait_usb_tx_ready (void); void sc64_usb_tx_data (io32_t *address, uint32_t length); void sc64_debug_write (uint8_t type, const void *data, uint32_t len); diff --git a/sw/n64/src/startup.S b/sw/n64/src/startup.S index c875e9f..90e8dd2 100644 --- a/sw/n64/src/startup.S +++ b/sw/n64/src/startup.S @@ -39,7 +39,9 @@ entry_handler: la $gp, _gp la $sp, _sp -run: + la $t0, exception_install + jalr $t0 + la $t0, init jalr $t0 diff --git a/sw/n64/src/storage.c b/sw/n64/src/storage.c index ff22ace..d4d15f2 100644 --- a/sw/n64/src/storage.c +++ b/sw/n64/src/storage.c @@ -3,6 +3,7 @@ #include "fatfs/ff.h" +#ifdef DEBUG static const char *fatfs_error_codes[] = { "(0) Succeeded", "(1) A hard error occurred in the low level disk I/O layer", @@ -25,6 +26,7 @@ static const char *fatfs_error_codes[] = { "(18) Number of open files > FF_FS_LOCK", "(19) Given parameter is invalid", }; +#endif #define FF_CHECK(x) { \ diff --git a/sw/n64/src/sys.c b/sw/n64/src/sys.c index 6d9f860..e2231af 100644 --- a/sw/n64/src/sys.c +++ b/sw/n64/src/sys.c @@ -6,42 +6,24 @@ void c0_set_status (uint32_t status) { ".set noat \n" ".set noreorder \n" "mtc0 %[status], $12 \n" - "nop \n" - : - : [status] "r" (status) + "nop \n" :: + [status] "r" (status) ); } -uint32_t c0_get_count (void) { - uint32_t count; - asm volatile ( - ".set noat \n" - ".set noreorder \n" - "mfc0 %[count], $9 \n" - "nop \n" - : [count] "=r" (count) - ); - return count; -} - -void wait_ms (uint32_t ms) { - uint32_t start = c0_get_count(); - while (c0_get_count() - start < (ms * ((CPU_FREQUENCY / 2) / 1000))); -} - uint32_t io_read (io32_t *address) { io32_t *uncached = UNCACHED(address); - asm volatile ("" : : : "memory"); + asm volatile ("" ::: "memory"); uint32_t value = *uncached; - asm volatile ("" : : : "memory"); + asm volatile ("" ::: "memory"); return value; } void io_write (io32_t *address, uint32_t value) { io32_t *uncached = UNCACHED(address); - asm volatile ("" : : : "memory"); + asm volatile ("" ::: "memory"); *uncached = value; - asm volatile ("" : : : "memory"); + asm volatile ("" ::: "memory"); } uint32_t pi_busy (void) { diff --git a/sw/n64/src/sys.h b/sw/n64/src/sys.h index d31dfc1..765bf8e 100644 --- a/sw/n64/src/sys.h +++ b/sw/n64/src/sys.h @@ -14,39 +14,37 @@ typedef volatile uint32_t io32_t; #define UNCACHED(address) ((typeof(address)) (((io32_t) (address)) | (0xA0000000UL))) -#define CPU_FREQUENCY (93750000UL) - -#define C0_SR_CU3 (1 << 31) -#define C0_SR_CU2 (1 << 30) -#define C0_SR_CU1 (1 << 29) -#define C0_SR_CU0 (1 << 28) -#define C0_SR_RP (1 << 27) -#define C0_SR_FR (1 << 26) -#define C0_SR_RE (1 << 25) -#define C0_SR_DS_ITS (1 << 24) -#define C0_SR_DS_BEV (1 << 22) -#define C0_SR_DS_TS (1 << 21) -#define C0_SR_DS_SR (1 << 20) -#define C0_SR_DS_CH (1 << 18) -#define C0_SR_DS_CE (1 << 17) -#define C0_SR_DS_DE (1 << 16) -#define C0_SR_IM7 (1 << 15) -#define C0_SR_IM6 (1 << 14) -#define C0_SR_IM5 (1 << 13) -#define C0_SR_IM4 (1 << 12) -#define C0_SR_IM3 (1 << 11) -#define C0_SR_IM2 (1 << 10) -#define C0_SR_IM1 (1 << 9) -#define C0_SR_IM0 (1 << 8) -#define C0_SR_KX (1 << 7) -#define C0_SR_SX (1 << 6) -#define C0_SR_UX (1 << 5) -#define C0_SR_KSU1 (1 << 4) -#define C0_SR_KSU0 (1 << 3) -#define C0_SR_EXR (1 << 2) -#define C0_SR_EXL (1 << 1) #define C0_SR_IE (1 << 0) +#define C0_SR_EXL (1 << 1) +#define C0_SR_EXR (1 << 2) +#define C0_SR_KSU0 (1 << 3) +#define C0_SR_KSU1 (1 << 4) +#define C0_SR_UX (1 << 5) +#define C0_SR_SX (1 << 6) +#define C0_SR_KX (1 << 7) +#define C0_SR_IM0 (1 << 8) +#define C0_SR_IM1 (1 << 9) +#define C0_SR_IM2 (1 << 10) +#define C0_SR_IM3 (1 << 11) +#define C0_SR_IM4 (1 << 12) +#define C0_SR_IM5 (1 << 13) +#define C0_SR_IM6 (1 << 14) +#define C0_SR_IM7 (1 << 15) +#define C0_SR_DS_DE (1 << 16) +#define C0_SR_DS_CE (1 << 17) +#define C0_SR_DS_CH (1 << 18) +#define C0_SR_DS_SR (1 << 20) +#define C0_SR_DS_TS (1 << 21) +#define C0_SR_DS_BEV (1 << 22) +#define C0_SR_DS_ITS (1 << 24) +#define C0_SR_RE (1 << 25) +#define C0_SR_FR (1 << 26) +#define C0_SR_RP (1 << 27) +#define C0_SR_CU0 (1 << 28) +#define C0_SR_CU1 (1 << 29) +#define C0_SR_CU2 (1 << 30) +#define C0_SR_CU3 (1 << 31) typedef struct {