fixed arm register saving/restoring 3ds9 is broken rn
This commit is contained in:
parent
d14a3e5919
commit
9fcc1f0950
5 changed files with 105 additions and 30 deletions
|
@ -7,6 +7,11 @@ PICAfb term;
|
||||||
void main();
|
void main();
|
||||||
extern "C" void start() { main(); }
|
extern "C" void start() { main(); }
|
||||||
void drivers_init() {
|
void drivers_init() {
|
||||||
|
term << "initing main tty\n";
|
||||||
setMainTTY(&term);
|
setMainTTY(&term);
|
||||||
--term;
|
--term;
|
||||||
|
term << "Initing vectors\n";
|
||||||
|
initVectors();
|
||||||
|
term << "trying svc\n";
|
||||||
|
asm volatile("svc #0");
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,11 @@ _start:
|
||||||
orr r0, r0, #(1<<0)
|
orr r0, r0, #(1<<0)
|
||||||
mcr p15, 0, r0, c1, c0, 0
|
mcr p15, 0, r0, c1, c0, 0
|
||||||
*/
|
*/
|
||||||
|
//Certain bootloaders put the interrupt vectors in ITCM.
|
||||||
|
//We don't want to mess with ITCM, so we put it back
|
||||||
|
mrc p15, 0, r0, c1, c0, 0
|
||||||
|
orr r0, #(1<<13)
|
||||||
|
mcr p15, 0, r0, c1, c0, 0
|
||||||
//Start start
|
//Start start
|
||||||
blx start
|
blx start
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
#include "include/regs.h"
|
||||||
#include <base.hpp>
|
#include <base.hpp>
|
||||||
#include <regs.hpp>
|
|
||||||
void print_regdump(cpu_state *state) {
|
void print_regdump(cpu_state *state) {
|
||||||
(*out << "r0: ").puti(state->r0);
|
(*out << "r0: ").puti(state->r0);
|
||||||
(*out << " r1: ").puti(state->r1);
|
(*out << " r1: ").puti(state->r1);
|
||||||
|
@ -7,4 +7,42 @@ void print_regdump(cpu_state *state) {
|
||||||
(*out << " r3: ").puti(state->r3);
|
(*out << " r3: ").puti(state->r3);
|
||||||
(*out << " r4: ").puti(state->r4);
|
(*out << " r4: ").puti(state->r4);
|
||||||
(*out << " r5: ").puti(state->r5);
|
(*out << " r5: ").puti(state->r5);
|
||||||
|
(*out << " r6: ").puti(state->r6);
|
||||||
|
(*out << " r7: ").puti(state->r7);
|
||||||
|
(*out << " r8: ").puti(state->r8);
|
||||||
|
(*out << " r9: ").puti(state->r9);
|
||||||
|
(*out << " r10: ").puti(state->r10);
|
||||||
|
(*out << " r11: ").puti(state->r11);
|
||||||
|
(*out << " r12: ").puti(state->r12);
|
||||||
|
(*out << " pc: ").puti(state->pc);
|
||||||
|
*out << "\n";
|
||||||
|
}
|
||||||
|
extern "C" cpu_state *handleINT(int number, cpu_state *state) {
|
||||||
|
*out << "Interrupt";
|
||||||
|
out->puti(number);
|
||||||
|
*out << " occurred!\n";
|
||||||
|
if (number != 4) {
|
||||||
|
out->setColor(Color::RED);
|
||||||
|
print_regdump(state);
|
||||||
|
*out << "KERNEL PANIC: Unhandled CPU exception\n";
|
||||||
|
// for(;;);
|
||||||
|
}
|
||||||
|
switch (number) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
if (state->cpsr & 0x20)
|
||||||
|
state->returnAddr -= 2;
|
||||||
|
else
|
||||||
|
state->returnAddr -= 4;
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
extern "C" void panic2(char *msg, cpu_state *state) {
|
||||||
|
out->setColor(Color::RED);
|
||||||
|
*out << "KERNEL PANIC: " << msg << "\n";
|
||||||
|
print_regdump(state);
|
||||||
|
for (;;)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,49 +2,74 @@ int_handler.write(
|
||||||
"""\
|
"""\
|
||||||
.arm
|
.arm
|
||||||
.fpu vfpv2
|
.fpu vfpv2
|
||||||
|
.section .bss
|
||||||
|
.space 4096
|
||||||
|
exception_stack:
|
||||||
|
.section .text
|
||||||
.global branch_macro
|
.global branch_macro
|
||||||
branch_macro:
|
branch_macro:
|
||||||
ldr pc, [pc, #-4] //Load the next word into PC
|
ldr pc, [pc, #-4] //Load the next word into PC
|
||||||
|
.macro interrupt_handler intid
|
||||||
|
//Set to the correct stack
|
||||||
|
ldr sp, =exception_stack
|
||||||
|
push {r0-r12,lr} //Push registers
|
||||||
|
|
||||||
|
//Get previous sp and lr
|
||||||
|
mrs r1, cpsr //Current mode
|
||||||
|
mrs r0, spsr //Previous mode
|
||||||
|
orr r0, #0xC0 //Disable interrupts in the previous mode
|
||||||
|
bic r0, #0x20 //enable ARM mode in there
|
||||||
|
|
||||||
|
//If the mode is user, switch to system mode
|
||||||
|
and r2, r0, #0x1F
|
||||||
|
cmp r2, #0x10
|
||||||
|
bne 1f
|
||||||
|
orr r0, #0x1F
|
||||||
|
1:
|
||||||
|
//Change mode
|
||||||
|
msr cpsr, r0
|
||||||
|
mov r2, sp
|
||||||
|
mov r3, lr
|
||||||
|
//Switch back
|
||||||
|
msr cpsr, r1
|
||||||
|
mrs r0, spsr
|
||||||
|
|
||||||
|
//Push those registers
|
||||||
|
push {r0, r2, r3, lr}
|
||||||
|
|
||||||
|
//Set argument 1
|
||||||
|
ldr r0, =\intid
|
||||||
|
|
||||||
|
//Jump to generic handler
|
||||||
|
blx intr_common_handler
|
||||||
|
|
||||||
|
//pop the special registers
|
||||||
|
pop {r0, r3, r4, lr}
|
||||||
|
tst r0, #0x20 //Is code ARM or thumb?
|
||||||
|
beq 2f
|
||||||
|
orr lr, lr, #1 //Enable thumb mode on return#
|
||||||
|
2:
|
||||||
|
str lr, [sp, #0x34] //Set correct lr
|
||||||
|
ldmfd sp!, {r0-r12, pc}^ //Return back to original mode
|
||||||
|
.endm
|
||||||
.global data_abort
|
.global data_abort
|
||||||
data_abort:
|
data_abort:
|
||||||
sub lr, #4
|
interrupt_handler 0
|
||||||
push {r0-r12,lr}
|
|
||||||
ldr r0, =0
|
|
||||||
blx intr_common_handler
|
|
||||||
pop {r0-r12,pc}
|
|
||||||
.global fast_irq
|
.global fast_irq
|
||||||
fast_irq:
|
fast_irq:
|
||||||
sub lr, #4
|
interrupt_handler 1
|
||||||
push {r0-r12,lr}
|
|
||||||
ldr r0, =1
|
|
||||||
blx intr_common_handler
|
|
||||||
pop {r0-r12,pc}
|
|
||||||
.global normal_irq
|
.global normal_irq
|
||||||
normal_irq:
|
normal_irq:
|
||||||
sub lr, #4
|
interrupt_handler 2
|
||||||
push {r0-r12,lr}
|
|
||||||
ldr r0, =2
|
|
||||||
blx intr_common_handler
|
|
||||||
pop {r0-r12,pc}
|
|
||||||
.global prefetch_abort
|
.global prefetch_abort
|
||||||
prefetch_abort:
|
prefetch_abort:
|
||||||
sub lr, #4
|
interrupt_handler 3
|
||||||
push {r0-r12,lr}
|
|
||||||
ldr r0, =3
|
|
||||||
blx intr_common_handler
|
|
||||||
pop {r0-r12,pc}
|
|
||||||
.global svc_call
|
.global svc_call
|
||||||
svc_call:
|
svc_call:
|
||||||
push {r0-r12,lr}
|
interrupt_handler 4
|
||||||
ldr r0, =4
|
|
||||||
blx intr_common_handler
|
|
||||||
pop {r0-r12,pc}
|
|
||||||
.global undefined_op
|
.global undefined_op
|
||||||
undefined_op:
|
undefined_op:
|
||||||
push {r0-r12,lr}
|
interrupt_handler 5
|
||||||
ldr r0, =5
|
|
||||||
blx intr_common_handler
|
|
||||||
pop {r0-r12,pc}
|
|
||||||
|
|
||||||
.extern handleINT
|
.extern handleINT
|
||||||
intr_common_handler:
|
intr_common_handler:
|
||||||
|
@ -81,6 +106,8 @@ if ("ENABLE_HARD" in config) and config["ENABLE_HARD"]:
|
||||||
reg_struct.write(" uint32_t "+reg+";\n")
|
reg_struct.write(" uint32_t "+reg+";\n")
|
||||||
for reg in ("d"+str(i) for i in range(16)):
|
for reg in ("d"+str(i) for i in range(16)):
|
||||||
reg_struct.write(" double "+reg+";\n")
|
reg_struct.write(" double "+reg+";\n")
|
||||||
|
for reg in ["cpsr","sp","lr","returnAddr"]:
|
||||||
|
reg_struct.write(" uint32_t "+reg+";\n")
|
||||||
for i in range(13):
|
for i in range(13):
|
||||||
reg_struct.write(" uint32_t r"+str(i)+";\n")
|
reg_struct.write(" uint32_t r"+str(i)+";\n")
|
||||||
reg_struct.write(" uint32_t pc;\n};")
|
reg_struct.write(" uint32_t pc;\n};")
|
||||||
|
|
|
@ -9,7 +9,7 @@ void svc_call();
|
||||||
void undefined_op();
|
void undefined_op();
|
||||||
}
|
}
|
||||||
void initVectors() {
|
void initVectors() {
|
||||||
uintptr_t *vectors = (uintptr_t *)0x08000000;
|
uintptr_t *vectors = (uintptr_t *)0x0800000;
|
||||||
// branch_macro is a ldr pc, [pc,#-4], meaning it reads the following word as PC
|
// branch_macro is a ldr pc, [pc,#-4], meaning it reads the following word as PC
|
||||||
vectors[0] = branch_macro;
|
vectors[0] = branch_macro;
|
||||||
vectors[1] = (uintptr_t)&normal_irq;
|
vectors[1] = (uintptr_t)&normal_irq;
|
||||||
|
|
Loading…
Reference in a new issue