mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-12-25 20:41:55 +01:00
exception
This commit is contained in:
parent
cbe31306f7
commit
dafa515e4f
12
.vscode/tasks.json
vendored
12
.vscode/tasks.json
vendored
@ -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"
|
||||
},
|
||||
|
@ -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 \
|
||||
|
@ -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 = .;
|
||||
|
||||
|
136
sw/n64/src/exception.S
Normal file
136
sw/n64/src/exception.S
Normal file
@ -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
|
234
sw/n64/src/exception.c
Normal file
234
sw/n64/src/exception.c
Normal file
@ -0,0 +1,234 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#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);
|
||||
}
|
57
sw/n64/src/exception.h
Normal file
57
sw/n64/src/exception.h
Normal file
@ -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
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -10,11 +10,13 @@
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <assert.h>
|
||||
#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);
|
||||
|
@ -39,7 +39,9 @@ entry_handler:
|
||||
la $gp, _gp
|
||||
la $sp, _sp
|
||||
|
||||
run:
|
||||
la $t0, exception_install
|
||||
jalr $t0
|
||||
|
||||
la $t0, init
|
||||
jalr $t0
|
||||
|
||||
|
@ -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) { \
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user