Added interrupts on the A9 side of the 3DS

code for A9 doesn't work at all for the A11 - or I missed the interrupt table
location (Which I think should be in AXIWRAM)
This commit is contained in:
Morten Delenk 2016-06-29 19:04:49 +02:00
parent a049fc5f8a
commit db923970b5
12 changed files with 559 additions and 52 deletions

Binary file not shown.

View file

@ -4,7 +4,7 @@ ARM11SRCS = $(shell find arm11 -name '*.cpp' -o -name '*.[cS]')
ARM9OBJS = $(addsuffix .o,$(basename $(ARM9SRCS)))
ARM11OBJS = $(addsuffix .o,$(basename $(ARM11SRCS)))
ARM9FLAGS = -mcpu=arm946e-s -march=armv5te -mlittle-endian
ARM11FLAGS = -mcpu=mpcore -mlittle-endian
ARM11FLAGS = -mcpu=mpcore -mlittle-endian -mtune=mpcore -mfpu=vfp
CPP = $(PREFIX)g++
CC = $(PREFIX)gcc

View file

@ -0,0 +1,72 @@
.section .text
.global _a11vectors_begin
.global _a11vectors_end
.extern _start
_a11vectors_begin:
//b start
b data_abort
b fiq
b irq
b prefetch_abort
b _svc
b udi
start:
b =_start
.extern handleINT11
data_abort:
sub lr, #8
stmdb sp!, {r0-r12,lr}
mov r0, sp
mov r1, #0
ldr r2, [pc, #4]
blx r2
ldmia sp!, {r0-r12, pc}^
.word handleINT11
fiq:
sub lr, #4
stmdb sp!, {r0-r12,lr}
mov r0, sp
mov r1, #1
ldr r2, [pc, #4]
blx r2
ldmia sp!, {r0-r12, pc}^
.word handleINT11
irq:
sub lr, #4
stmdb sp!, {r0-r12,lr}
mov r0, sp
mov r1, #2
ldr r2, [pc, #4]
blx r2
ldmia sp!, {r0-r12, pc}^
.word handleINT11
prefetch_abort:
sub lr, #4
stmdb sp!, {r0-r12,lr}
mov r0, sp
mov r1, #3
ldr r2, [pc, #4]
blx r2
ldmia sp!, {r0-r12, pc}^
.word handleINT11
_svc:
stmdb sp!, {r0-r12,lr}
mov r0, sp
mov r1, #4
ldr r2, [pc, #4]
blx r2
ldmia sp!, {r0-r12, pc}^
.word handleINT11
udi:
stmdb sp!, {r0-r12,lr}
mov r0, sp
mov r1, #5
ldr r2, [pc, #4]
blx r2
ldmia sp!, {r0-r12, pc}^
.word handleINT11
_a11vectors_end:
.global initInterrupts
initInterrupts:
MCR p15, 0, r0, c7, c7, 0
bx lr

View file

@ -2,34 +2,28 @@
//A11 SYS_CORE
//If it's zero, SYS_CORE is ready for a new task
#include <stdint.h>
#include <stdfnt.h>
void(**fpointer)(void)=(void(**)(void))0x1FFFFFF8;
void __attribute__((naked)) arm11Stub(void)
{
//Disable interrupts
__asm(".word 0xF10C01C0");
//Wait for the entry to be set
while(*fpointer == &arm11Stub);
//Jump to it
(*fpointer)();
}
void mainRoutine() {
#include <textDISP.hpp>
extern "C" void initInterrupts();
void(**fpointer)(void*)=(void(**)(void*))0x1FFFFFF8;
void **farg = (void**)0x1FFFFFFC;
//Flags:
//0: Output from ARM11
//1: puts() lock
uint32_t *flags = (uint32_t*)0x1FFFFFF4;
namespace MTGosHAL {
void mainRoutine(void*) {
*farg=nullptr;
*fpointer=nullptr;
while(true) {
if(!(*fpointer))
continue;
(*fpointer)();
(*fpointer)(*farg);
*farg=nullptr;
*fpointer=nullptr;
*flags&=~1;
}
}
unsigned int seed=0;
unsigned int random() {
return seed=0x41C64E6D * seed + 0x00006073;
}
#define CALCXY_top(x,y) ((x)*240+240-(y))
void initScreen() {
void initScreen(void*) {
//top screen lfb size: 0x5dc00
//bottom screen lfb size: 0x4b000
//lfb locations: 0x18000000 (left 1)
@ -38,6 +32,9 @@ void initScreen() {
//lfb locations: 0x18120000 (right 2)
//lfb locations: 0x18180000 (bottom 1)
//lfb locations: 0x181D0000 (bottom 2)
unsigned int *lfbs = (unsigned int*)0x18000000;
for(int i=0;i<475136;i++)
lfbs[i]=0;
unsigned int *fb_init=(unsigned int*)0x10400400;
fb_init[0x70/4]&=~0x7;
fb_init[0x170/4]&=~0x7;
@ -49,18 +46,42 @@ void initScreen() {
fb_init[0x168/4]=0x18180000;
fb_init[0x16C/4]=0x181D0000;
fb_init[0x190/4]=960;
int *lfb=(int*)0x18060000;
for(int bx=0;bx<32;bx++) {
for(int by=0;by<8;by++) {
for(int x=0;x<8;x++) {
for(int y=0;y<8;y++) {
if(font[bx+by*32][y]&(1<<x))
lfb[CALCXY_top(bx*8+x,by*8+y)]=0xFFFFFF00;
else
lfb[CALCXY_top(bx*8+x,by*8+y)]=0x0;
}
}
}
}
fb_init[0x78/4]=1;
}
void testSVC(void*) {
initInterrupts();
asm volatile("svc #1");
}
}
struct cpu_info {
unsigned int pc;
unsigned int r12;
unsigned int r11;
unsigned int r10;
unsigned int r9;
unsigned int r8;
unsigned int r7;
unsigned int r6;
unsigned int r5;
unsigned int r4;
unsigned int r3;
unsigned int r2;
unsigned int r1;
unsigned int retAddr;
};
extern "C" void handleINT11(uint32_t stack, uint32_t id) {
MTGosHAL::Screen out;
*flags|=1;
out << MTGosHAL::Base::HEXADECIMAL << MTGosHAL::FG_color::RED << "Interrupt! " << (int)stack << "-" << (int)id << "\n";
struct cpu_info *cpu=(struct cpu_info*)stack;
out << "handler addr " << (int) cpu->pc << "\n";
out << "R1 " << (int) cpu->r1 << ", R2 " << (int)cpu->r2 << "\n";
out << "R3 " << (int) cpu->r3 << ", R4 " << (int)cpu->r4 << "\n";
out << "R5 " << (int) cpu->r5 << ", R6 " << (int)cpu->r6 << "\n";
out << "R7 " << (int) cpu->r7 << ", R8 " << (int)cpu->r8 << "\n";
out << "R9 " << (int) cpu->r9 << ", SL " << (int)cpu->r10 << "\n";
out << "FP " << (int) cpu->r11 << ", IP " << (int)cpu->r12 << "\n";
out << "SP " << (int) stack << ", PC " << (int)cpu->retAddr << "\n";
*flags&=~1;
if((id!=1)&&(id!=2)&&(id!=4))
for(;;);
}

View file

@ -0,0 +1,99 @@
#include <base.hpp>
#include <textDISP.hpp>
#include <stdfnt.h>
int x=0, y=0;
extern uint32_t *flags;
namespace MTGosHAL {
FG_color fg=FG_color::WHITE;
BG_color bg=BG_color::BLACK;
uint32_t* toplfb = (uint32_t*)0x18000000;
uint32_t* bottomlfb = (uint32_t*)0x18180000;
int base=10;
void Screen::putChar(char c) {
while(*flags&2); //to prevent garbage to be displayed when ARM9&ARM11 are trying to access it at the same time
*flags|=2;
switch(c) {
case '\n':
x=0; y++;
break;
case '\r':
x=0;
break;
case '\b':
x--;
if(x<0) x=0;
putChar(' ');
x--;
if(x<0) x=0;
break;
case '\0':
break;
default:
for(int lx=0;lx<8;lx++) {
for(int ly=0;ly<8;ly++) {
if(font[(int)((uint8_t)c)][ly]&(1<<lx)) {
if(y>=TOP_SCREEN_HEIGHT)
bottomlfb[CALCXY(x*8+lx,(y-TOP_SCREEN_HEIGHT)*8+ly)]=__builtin_bswap32(static_cast<uint32_t>(fg));
else
toplfb[CALCXY(x*8+lx,(y)*8+ly)]=__builtin_bswap32(static_cast<uint32_t>(fg));
} else {
if(y>=TOP_SCREEN_HEIGHT)
bottomlfb[CALCXY(x*8+lx,(y-TOP_SCREEN_HEIGHT)*8+ly)]=__builtin_bswap32(static_cast<uint32_t>(bg));
else
toplfb[CALCXY(x*8+lx,(y)*8+ly)]=__builtin_bswap32(static_cast<uint32_t>(bg));
}
}
}
x++;
if(x==(y>=TOP_SCREEN_HEIGHT?BOTTOM_SCREEN_WIDTH:TOP_SCREEN_WIDTH)) {
x=0;
y++;
}
break;
}
if(y>=TOP_SCREEN_HEIGHT+BOTTOM_SCREEN_HEIGHT)
scroll_impl();
*flags&=~2; //Unlock
}
void Screen::clrscr_impl() {
for(int p=0;p<400*240;p++)
toplfb[p]=__builtin_bswap32(static_cast<uint32_t>(bg));
for(int p=0;p<320*240;p++)
bottomlfb[p]=__builtin_bswap32(static_cast<uint32_t>(bg));
}
void Screen::scroll_impl() {
for(int ly=0;ly<240-8;ly++) {
for(int lx=0;lx<400;lx++) {
toplfb[CALCXY(lx,ly)]=toplfb[CALCXY(lx,ly+8)];
}
}
for(int ly=0;ly<8;ly++) {
for(int lx=0;lx<40;lx++) {
toplfb[CALCXY(lx,ly+240-8)]=__builtin_bswap32(static_cast<uint32_t>(bg));
}
for(int lx=40;lx<360;lx++) {
toplfb[CALCXY(lx,ly+240-8)]=bottomlfb[CALCXY(lx-40,ly)];
}
for(int lx=360;lx<400;lx++) {
toplfb[CALCXY(lx,ly+240-8)]=__builtin_bswap32(static_cast<uint32_t>(bg));
}
}
for(int ly=0;ly<240-8;ly++) {
for(int lx=0;lx<320;lx++) {
bottomlfb[CALCXY(lx,ly)]=bottomlfb[CALCXY(lx,ly+8)];
}
}
for(int ly=240-8;ly<240;ly++) {
for(int lx=0;lx<320;lx++) {
bottomlfb[CALCXY(lx,ly)]=__builtin_bswap32(static_cast<uint32_t>(bg));
}
}
y--;
}
auto Screen::a11puts(const char *s) -> void {
int i=0;
while(s[i])
putChar(s[i]);
}
}

View file

@ -0,0 +1,68 @@
.section .text
.global _a9vectors_begin
.global _a9vectors_end
.extern _start
_a9vectors_begin:
//b start
b data_abort
b fiq
b irq
b prefetch_abort
b _svc
b udi
start:
b =_start
.extern handleINT9
data_abort:
sub lr, #8
stmdb sp!, {r0-r12,lr}
mov r0, sp
mov r1, #0
ldr r2, [pc, #4]
blx r2
ldmia sp!, {r0-r12, pc}^
.word handleINT9
fiq:
sub lr, #4
stmdb sp!, {r0-r12,lr}
mov r0, sp
mov r1, #1
ldr r2, [pc, #4]
blx r2
ldmia sp!, {r0-r12, pc}^
.word handleINT9
irq:
sub lr, #4
stmdb sp!, {r0-r12,lr}
mov r0, sp
mov r1, #2
ldr r2, [pc, #4]
blx r2
ldmia sp!, {r0-r12, pc}^
.word handleINT9
prefetch_abort:
sub lr, #4
stmdb sp!, {r0-r12,lr}
mov r0, sp
mov r1, #3
ldr r2, [pc, #4]
blx r2
ldmia sp!, {r0-r12, pc}^
.word handleINT9
_svc:
stmdb sp!, {r0-r12,lr}
mov r0, sp
mov r1, #4
ldr r2, [pc, #4]
blx r2
ldmia sp!, {r0-r12, pc}^
.word handleINT9
udi:
stmdb sp!, {r0-r12,lr}
mov r0, sp
mov r1, #5
ldr r2, [pc, #4]
blx r2
ldmia sp!, {r0-r12, pc}^
.word handleINT9
_a9vectors_end:

View file

@ -44,8 +44,8 @@ _start:
mrc p15, 0, r0, c1, c0, 0 // read control register
orr r0, r0, #(1<<18) // - itcm enable
orr r0, r0, #(1<<16) // - dtcm enable
orr r0, r0, #(1<<12) // - instruction cache enable
orr r0, r0, #(1<<2) // - data cache enable
//orr r0, r0, #(1<<12) // - instruction cache enable
//orr r0, r0, #(1<<2) // - data cache enable
orr r0, r0, #(1<<0) // - mpu enable
mcr p15, 0, r0, c1, c0, 0 // write control register

View file

@ -1,14 +1,74 @@
void __attribute__((naked)) arm11Stub(void);
void mainRoutine();
void initScreen();
void(**a11fpointer)(void)=(void(**)(void))0x1FFFFFF8;
extern "C" void init() {
*a11fpointer=&arm11Stub;
for(int i=0;i<100;i++);
*a11fpointer=&mainRoutine;
while(*a11fpointer);
*a11fpointer=&initScreen;
while(*a11fpointer);
#include <textDISP.hpp>
while(true);
void(**a11fpointer)(void*)=(void(**)(void*))0x1FFFFFF8;
void **a11farg = (void**)0x1FFFFFFC;
extern uint32_t *flags;
extern unsigned int _a9vectors_begin;
extern unsigned int _a9vectors_end;
extern unsigned int _a11vectors_begin;
extern unsigned int _a11vectors_end;
namespace MTGosHAL {
void mainRoutine(void*);
void initScreen(void*);
void testSVC(void*);
void main() {
*a11farg = 0;
*a11fpointer=&mainRoutine;
while(*a11fpointer);
*a11fpointer=&initScreen;
while(*a11fpointer);
unsigned int * output=(unsigned int*)0x08000000;
Screen out;
out << "Waiting for interrupt...\n";
out << "Copying " << &_a9vectors_end-&_a9vectors_begin << " words...\n";
for(int i=0;i<(&_a9vectors_end-&_a9vectors_begin);i++) {
output[i]=(&_a9vectors_begin)[i];
}
asm volatile("svc #0\n");
out << "Did it work?\nSetting up A11 interrupts\n";
output=(unsigned int*)0x1FF80000;
out << "Copying " << &_a11vectors_end-&_a11vectors_begin << " words...\n";
for(int i=0;i<(&_a11vectors_end-&_a11vectors_begin);i++) {
output[i]=(&_a11vectors_begin)[i];
}
out << "Done!\n";
*a11fpointer=&testSVC;
while(*a11fpointer);
out << "Did it work?\n";
for(;;);
}
}
extern "C" void init() {
MTGosHAL::main();
}
struct cpu_info {
unsigned int pc;
unsigned int r12;
unsigned int r11;
unsigned int r10;
unsigned int r9;
unsigned int r8;
unsigned int r7;
unsigned int r6;
unsigned int r5;
unsigned int r4;
unsigned int r3;
unsigned int r2;
unsigned int r1;
unsigned int retAddr;
};
extern "C" void handleINT9(uint32_t stack, uint32_t id) {
MTGosHAL::Screen out;
out << MTGosHAL::Base::HEXADECIMAL << MTGosHAL::FG_color::RED << "Interrupt! " << (int)stack << "-" << (int)id << "\n";
struct cpu_info *cpu=(struct cpu_info*)stack;
out << "handler addr " << (int) cpu->pc << "\n";
out << "R1 " << (int) cpu->r1 << ", R2 " << (int)cpu->r2 << "\n";
out << "R3 " << (int) cpu->r3 << ", R4 " << (int)cpu->r4 << "\n";
out << "R5 " << (int) cpu->r5 << ", R6 " << (int)cpu->r6 << "\n";
out << "R7 " << (int) cpu->r7 << ", R8 " << (int)cpu->r8 << "\n";
out << "R9 " << (int) cpu->r9 << ", SL " << (int)cpu->r10 << "\n";
out << "FP " << (int) cpu->r11 << ", IP " << (int)cpu->r12 << "\n";
out << "SP " << (int) stack << ", PC " << (int)cpu->retAddr << "\n";
if((id!=1)&&(id!=2)&&(id!=4))
for(;;);
}

View file

@ -0,0 +1,97 @@
#include <base.hpp>
#include <textDISP.hpp>
//Flags:
//0: Output from ARM11
//1: puts() lock
extern uint32_t *flags;
namespace MTGosHAL {
auto Screen::puts(const char *s) -> void {
void(**a11fpointer)(void*)=(void(**)(void*))0x1FFFFFF8;
void **a11farg = (void**)0x1FFFFFFC;
int i=0;
while(s[i]) {
if(*flags&1)
putChar(s[i++]);
else {
while(*a11fpointer);
*a11farg=(void*)((unsigned int)s[i++]);
*a11fpointer=(void(*)(void*))&putChar;
}
}
}
auto Screen::clrscr() -> void {
void(**a11fpointer)(void*)=(void(**)(void*))0x1FFFFFF8;
while(*a11fpointer);
*a11fpointer=(void(*)(void*))(clrscr_impl);
}
auto Screen::scroll() -> void {
void(**a11fpointer)(void*)=(void(**)(void*))0x1FFFFFF8;
while(*a11fpointer);
*a11fpointer=(void(*)(void*))(scroll_impl);
}
template <>
auto Screen::operator<<<FG_color>(FG_color fg) -> Screen &{
fg=fg;
return *this;
}
template <>
auto Screen::operator<<<BG_color>(BG_color bg) -> Screen &{
bg=bg;
return *this;
}
auto Screen::setColor(FG_color fg) -> Screen &{
fg=fg;
return *this;
}
auto Screen::setColor(BG_color bg) -> Screen &{
bg=bg;
return *this;
}
auto Screen::setColor(FG_color fg, BG_color bg) -> Screen &{
return (*this).setColor(fg).setColor(bg);
}
template <>
auto Screen::operator<<<Base>(Base output) -> Screen & {
base=static_cast<int>(output);
return *this;
}
template <>
auto Screen::operator<<<int>(int op) -> Screen & {
uintptr_t output=op;
const char* chars="0123456789ABCDEF";
char buf[33];
buf[32]='\0';
char* ptr=buf+31;
do {
*(ptr--)=chars[output%base];
output/=base;
} while(output && (ptr!=buf));
puts(ptr+1);
return *this;
}
template <>
auto Screen::operator<<<long int>(long int op) -> Screen & {
uint64_t output=op;
const char* chars="0123456789ABCDEF";
char buf[65];
buf[64]='\0';
char* ptr=buf+63;
do {
*(ptr--)=chars[output%base];
output/=base;
} while(output && (ptr!=buf));
puts(ptr+1);
return *this;
}
template <>
auto Screen::operator<<<char>(char output) -> Screen & {
putChar(output);
return *this;
}
template <>
auto Screen::operator<<<char*>(char* output) -> Screen & {
puts(output);
return *this;
}
}

View file

@ -0,0 +1,90 @@
#ifndef _TEXTDISP_H
#define _TEXTDISP_H
#include <stdint.h>
#include <base.hpp>
#include <output.hpp>
#define TOP_SCREEN_WIDTH 50
#define TOP_SCREEN_HEIGHT 30
#define BOTTOM_SCREEN_WIDTH 40
#define BOTTOM_SCREEN_HEIGHT 30
namespace MTGosHAL {
enum class BG_color : uint32_t {
BLACK=0x000000,
BLUE=0x0000AA,
GREEN=0x00AA00,
CYAN=0x00AAAA,
RED=0xAA0000,
MAGENTA=0xAA00AA,
BROWN=0xAA5500,
LIGHT_GREY=0xAAAAAA,
GREY=0x555555,
LIGHT_BLUE=0x5555FF,
LIGHT_GREEN=0x55FF55,
LIGHT_CYAN=0x55FFFF,
LIGHT_RED=0xFF5555,
LIGHT_MAGENTA=0xFF55FF,
YELLOW=0xFFFF55,
WHITE=0xFFFFFF
};
enum class FG_color : uint32_t {
BLACK=0x000000,
BLUE=0x0000AA,
GREEN=0x00AA00,
CYAN=0x00AAAA,
RED=0xAA0000,
MAGENTA=0xAA00AA,
BROWN=0xAA5500,
LIGHT_GREY=0xAAAAAA,
GREY=0x555555,
LIGHT_BLUE=0x5555FF,
LIGHT_GREEN=0x55FF55,
LIGHT_CYAN=0x55FFFF,
LIGHT_RED=0xFF5555,
LIGHT_MAGENTA=0xFF55FF,
YELLOW=0xFFFF55,
WHITE=0xFFFFFF
};
extern FG_color fg;
extern BG_color bg;
extern uint32_t* toplfb;
extern uint32_t* bottomlfb;
extern int base;
class Screen {
private:
static auto putChar(char c) -> void; //ARM11
static auto clrscr_impl() -> void; //ARM11
static auto scroll_impl() -> void;
public:
auto puts(const char *s) -> void;
auto a11puts(const char *s) -> void;
Screen(){
}
template <typename T>
auto operator<< (T output) -> Screen & {
puts(output);
return *this;
}
auto clrscr() -> void;
auto scroll() -> void;
auto setColor(FG_color fg) -> Screen &;
auto setColor(BG_color bg) -> Screen &;
auto setColor(FG_color fg, BG_color bg) -> Screen &;
};
template <>
auto Screen::operator<<<FG_color>(FG_color fg) -> Screen &;
template <>
auto Screen::operator<<<BG_color>(BG_color bg) -> Screen &;
template <>
auto Screen::operator<<<Base>(Base output) -> Screen &;
template <>
auto Screen::operator<<<int>(int output) -> Screen &;
template <>
auto Screen::operator<<<long int>(long int output) -> Screen &;
template <>
auto Screen::operator<<<char>(char output) -> Screen &;
template <>
auto Screen::operator<<<char*>(char* output) -> Screen &;
}
#endif
#define CALCXY(x,y) ((x)*240+239-(y))

View file

@ -8,7 +8,7 @@ typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
typedef unsigned int uintptr_t;
typedef unsigned int size_t;
#else
typedef signed char int8_t;
typedef signed short int16_t;
@ -19,5 +19,5 @@ typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;
typedef unsigned long int uintptr_t;
#endif
typedef unsigned long int size_t;
#endif

Binary file not shown.