fixed arm register saving/restoring 3ds9 is broken rn

This commit is contained in:
Morten Delenk 2017-05-01 13:39:55 +00:00
parent d14a3e5919
commit 9fcc1f0950
5 changed files with 105 additions and 30 deletions

View file

@ -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");
} }

View file

@ -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

View file

@ -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 (;;)
;
} }

View file

@ -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};")

View file

@ -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;