rpi baremetal stuff

This commit is contained in:
Triss 2022-01-29 19:09:46 +01:00
parent 0a7914e3f7
commit cb54b4d409
6 changed files with 324 additions and 251 deletions

View File

@ -39,6 +39,7 @@
// newlib assumed // newlib assumed
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#endif // platform #endif // platform
@ -50,7 +51,7 @@
// Cypress FX3 | ARM926EJ-S | 0x41069265 | 0x07926069 | 0x64100004 // Cypress FX3 | ARM926EJ-S | 0x41069265 | 0x07926069 | 0x64100004
// TI Nspire | ARM926EJ-S?| 0x41069265?| ??? | 0x64100004? // TODO // TI Nspire | ARM926EJ-S?| 0x41069265?| ??? | 0x64100004? // TODO
// Wii Starlet | ARM926EJ-S?| ??? | ??? | ??? // TODO // Wii Starlet | ARM926EJ-S?| ??? | ??? | ??? // TODO
// RPi v1.2 B+ |ARM1176JZF-S| 0x410FB767 | 0x07B7617F | 0x74100064 // RPi v1.2 B+ |ARM1176JZF-S| 0x410FB767 | 0x07B7617F | 0x74100064 // FIXME: insn enumeration broken due to caching or something
// Ninty .3DS | ARM11MPCore| 0x410FB025?| ??? | 0x74100064? // TODO // Ninty .3DS | ARM11MPCore| 0x410FB025?| ??? | 0x74100064? // TODO
// ??? TODO | Cortex-A8 | ??? | ??? | ??? // ??? TODO | Cortex-A8 | ??? | ??? | ???
// Xilinx Zynq7| Cortex-A9MP| 0x413FC090 | 0x4BA00477 | 0xF4100168 // Xilinx Zynq7| Cortex-A9MP| 0x413FC090 | 0x4BA00477 | 0xF4100168
@ -203,14 +204,15 @@ static void DC_FlushAll(void) {
"add r1, r1, #0x40000000\n" "add r1, r1, #0x40000000\n"
"cmp r1, #0\n" "cmp r1, #0\n"
"bne outer_loop\n" "bne outer_loop\n"
#elif __ARM_ARCH == 6 && defined(__ARM_ARCH_6KZ__)
"mov r0, #0\n" "mov r0, #0\n"
"mcr p15, 0, r0, c7, c10, 0\n" // clean & flush entire data cache #elif __ARM_ARCH == 6 && defined(__ARM_ARCH_6KZ__)
// FIXME: ARM11 code no worky
"mov r0, #0\n"
"mcr p15, 0, r0, c7, c14, 0\n" // Clean and Invalidate Entire Data Cache
#else #else
#error "wut" #error "wut"
#endif #endif
"mov r0, #0\n"
"mcr p15, 0, r0, c7, c10, 4 @ drain write buffer\n" // ARM9, ARM11 ok "mcr p15, 0, r0, c7, c10, 4 @ drain write buffer\n" // ARM9, ARM11 ok
"bx lr\n" "bx lr\n"
: :
@ -221,9 +223,22 @@ static void DC_FlushAll(void) {
__attribute__((__unused__)) __attribute__((__unused__))
static inline void DC_InvalidateAll(void) { static inline void DC_InvalidateAll(void) {
asm volatile("mcr p15, 0, %0, c7, c6, 0" : : "r"(0)); // ARM9, ARM11 ok asm volatile("mcr p15, 0, %0, c7, c6, 0" : : "r"(0)); // ARM9, ARM11 ok
#if __ARM_ARCH == 6
// FIXME: ARM11 code no worky
asm volatile("mcr p15, 0, %0, c7, c7, 0" : : "r"(0)); // ARM9, ARM11 ok
asm volatile("mcr p15, 0, %0, c8, c7, 0" : : "r"(0)); // invalidate tlb
asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r"(0)); // dsb
#endif
} }
static inline void IC_InvalidateAll(void) { static inline void IC_InvalidateAll(void) {
asm volatile("mcr p15, 0, %0, c7, c5, 0" : : "r"(0)); // ARM9, ARM11 ok asm volatile("mcr p15, 0, %0, c7, c5, 0" : : "r"(0)); // ARM9, ARM11 ok
#if __ARM_ARCH == 6
// FIXME: ARM11 code no worky
asm volatile("mcr p15, 0, %0, c7, c7, 0" : : "r"(0)); // ARM9, ARM11 ok
asm volatile("mcr p15, 0, %0, c8, c7, 0" : : "r"(0)); // invalidate tlb
asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r"(0)); // dsb
asm volatile("mcr p15, 0, %0, c7, c5, 4" : : "r"(0)); // flush prefetch buffer
#endif
} }
#elif __ARM_ARCH == 7 && defined(__ARM_ARCH_7A__) #elif __ARM_ARCH == 7 && defined(__ARM_ARCH_7A__)
#include "cache_cortexa.c" /* go sue me */ #include "cache_cortexa.c" /* go sue me */
@ -340,13 +355,15 @@ static void handler_idiv(void) {
// r0 = 3 // r0 = 3
// r1 = 4 // r1 = 4
// r2 = 2 // r2 = 2
// editing the above has no effect // editing the above has no effect (not on ARM9, nor on ARM11)
// NOTE: these depend on the stack content, i.e. it's not a moving register // NOTE: these depend on the stack content, i.e. it's not a moving register
// window. pushes happen in the following order: r0,r1,r2,r3 // window. pushes happen in the following order: r0,r1,r2,r3
// TODO: when the 'register stack cache' is full, what happens? does // TODO: when the 'register stack cache' is full, what happens? does
// it loop or does it act in a FIFO way, moving r0<-r1<-r2<-r3? // it loop or does it act in a FIFO way, moving r0<-r1<-r2<-r3?
// how can the fillrate be known??? (libjz says r5 & 3 but i // how can the fillrate be known??? (libjz says r5 & 3 but i
// dont see anything like that, maybe its an ARM11 thing?) // dont see anything like that, maybe its an ARM11 thing?)
// TODO: Hackspire also says something about the low bits of r5, not
// seeing this on ARM9 nor ARM11...
// "r4: Copy of local variable 0. Only valid when local variable 0 is a // "r4: Copy of local variable 0. Only valid when local variable 0 is a
// single word (i.e. int, float, or Object; not long or double)" // single word (i.e. int, float, or Object; not long or double)"
// -Hackspire // -Hackspire
@ -526,8 +543,9 @@ static uint8_t bytecode_test1[] = {
0x06, // iconst_3 0x06, // iconst_3
0x07, // iconst_4 0x07, // iconst_4
0x05, // iconst_2 0x05, // iconst_2
0xFE, // ??? (r5 readout) // FIXME: if we put 0xFE here instead, the end result is 11 on RPi. why?
0x6C, // idiv 0x6C, // idiv
0xFE, // ??? (r5 readout)
0x04, // iconst_1 0x04, // iconst_1
0x60, // iadd 0x60, // iadd
0x60, // iadd 0x60, // iadd
@ -562,7 +580,7 @@ void jazelle_main(void) {
uint32_t aid = arm_get_id(); uint32_t aid = arm_get_id();
uint32_t jid = jazelle_get_id(); uint32_t jid = jazelle_get_id();
iprintf("hello world! ARM coreID=0x%lx jazelle ID=0x%lx\r\n", aid, jid); iprintf("hello world! ARM coreID=0x%lx jazelle ID=0x%lx\r\n", aid, jid);
while (jid == 0) ; if (jid == 0) return;
int r = jazelle_exec(bytecode_test1); int r = jazelle_exec(bytecode_test1);
iprintf("retcode=%d; r5 was 0x%08lx\r\n", r, backup_r5); iprintf("retcode=%d; r5 was 0x%08lx\r\n", r, backup_r5);

View File

@ -5,8 +5,8 @@ OPENOCD_PORT_TELNET ?= 4444
PREFIX ?= arm-none-eabi- PREFIX ?= arm-none-eabi-
CC = $(PREFIX)gcc CC = $(PREFIX)gcc
CFLAGS = -mcpu=arm1176jzf-s -Wall CFLAGS = -mcpu=arm1176jzf-s -Wall -O2
LDFLAGS = -T rpi.ld -nostartfiles -nostdlib LDFLAGS = -T rpi.ld -nostartfiles -Wl,-Map=rpi.map -Wl,--cref
GDB ?= $(PREFIX)gdb GDB ?= $(PREFIX)gdb
PYTHON3 ?= python3 PYTHON3 ?= python3
NC ?= nc NC ?= nc
@ -16,13 +16,13 @@ LNXCC = $(LNXPREFIX)gcc
default: all default: all
all: rpi.elf all: rpi.elf rpi.img
rpi.o: rpi.c rpi.o: rpi.c
$(CC) $(CFLAGS) -c -o "$@" "$<" $(CC) $(CFLAGS) -c -o "$@" "$<"
rpi.elf: rpi.o vectors.o: vectors.s
$(CC) $(CFLAGS) $(LDFLAGS) -o "$@" $^ $(CC) -mcpu=arm1176jzf-s -c -o "$@" "$<"
#jazelle.S: ../jazelle.c #jazelle.S: ../jazelle.c
# $(CC) $(CFLAGS) -S -o "$@" "$<" # $(CC) $(CFLAGS) -S -o "$@" "$<"
@ -30,6 +30,15 @@ rpi.elf: rpi.o
jazelle.o: ../jazelle.c jazelle.o: ../jazelle.c
$(CC) $(CFLAGS) -c -o "$@" "$<" $(CC) $(CFLAGS) -c -o "$@" "$<"
nl-glue.o: nl-glue.c
$(CC) $(CFLAGS) -c -o "$@" "$<"
rpi.elf: rpi.o vectors.o nl-glue.o jazelle.o
$(CC) $(CFLAGS) $(LDFLAGS) -o "$@" $^
rpi.img: rpi.elf
$(PREFIX)objcopy -O binary "$<" "$@"
jazlinux: linux.c ../jazelle.c jazlinux: linux.c ../jazelle.c
$(LNXCC) $(CLFAGS) -o "$@" $^ $(LNXCC) $(CLFAGS) -o "$@" $^

98
rpi/nl-glue.c Normal file
View File

@ -0,0 +1,98 @@
/* glue code for Newlib */
#include <sys/types.h>
#include <sys/stat.h>
void uart_putc(char c);
void uart_puts(const char* s);
void uart_putdata(const uint8_t* p, size_t size);
/* Newlib's assert() calls this function if the assertion fails */
void __assert_func (const char *file, int line, const char *func, const char *failedexpr)
{
if (file != NULL) {
char linestrbuf[16], *linestr = &linestrbuf[sizeof(linestrbuf)];
uart_puts(file);
uart_putc(':');
/* Avoid using newlib functions like itoa so as not to trigger
a recursive assert... */
*--linestr = '\0';
while (line >= 10 && linestr != &linestrbuf[1]) {
*--linestr = '0' + (line % 10);
line /= 10;
}
*--linestr = '0' + line;
uart_puts(linestr);
uart_puts(": ");
}
if (func != NULL) {
uart_puts(func);
uart_puts(": ");
}
uart_puts("Assertion ");
if (failedexpr != NULL) {
uart_putc('`');
uart_puts(failedexpr);
uart_puts("' ");
}
uart_puts("failed.\n");
//Fx3UartTxFlush();
for(;;) ;
}
int _write(int fd, char* data, int size) {
if (fd >= 0 && fd < 3) {
if (size > 0)
uart_putdata((const uint8_t*)data, (size_t)size);
//Fx3UartTxFlush();
return size;
}
return -1;
}
int _close(int fd) { (void)fd; return 0; }
int _stat(char *file, struct stat *st) {
(void)file;
st->st_mode = S_IFCHR;
return 0;
}
int _read(int fd, char *ptr, int len) { (void)fd; (void)ptr; (void)len; return 0; }
int _lseek(int fd, int ptr, int dir) { (void)fd; (void)ptr; (void)dir; return 0; }
int _isatty(int fd) { (void)fd; return 1; }
int _fstat(int fd, struct stat *st) {
(void)fd;
st->st_mode = S_IFCHR;
return 0;
}
#define HEAPSIZE (256*1024*1024)
extern uint8_t _heap[];
caddr_t _sbrk_r(int incr) {
static uint8_t* heap_end = 0;
uint8_t* prev_heap_end;
/* initialize */
if (heap_end == 0)
heap_end = _heap;
prev_heap_end = heap_end;
if (heap_end + incr - _heap > HEAPSIZE) {
/* heap overflow - announce on stderr */
_write (2, "Heap overflow!\r\n", 16);
for (;;) asm volatile("nop");
}
heap_end += incr;
return (caddr_t)prev_heap_end;
}

288
rpi/rpi.c
View File

@ -5,245 +5,71 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
// known ID table: //-------------------------------------------------------------------------
// Chip name | ARM core | ARM CPUID | JTAG IDCODE | Jazelle ID //-------------------------------------------------------------------------
// ------------+------------+------------+-------------+----------- Jazelle DBX:
// ??? | ARM7EJ-S | ??? | ??? | ???
// Cypress FX3 | ARM926EJ-S | 0x41069265 | 0x07926069 | 0x64100004
// TI Nspire | ARM926EJ-S?| 0x41069265?| ??? | 0x64100004?
// RPi v1.?? | ARM11??? | ??? | ??? | ???
// Ninty ?3DS | ARM11MPCore| 0x410FB025?| ??? | 0x74100064?
// Xilinx Zynq7| Cortex-A9MP| 0x413FC090 | 0x4BA00477 | 0xF4100168
// ------------+------------+------------+-------------+----------- Jazelle RCT:
// Xilinx Zynq7| Cortex-A9MP| 0x413FC090 | 0x4BA00477 | 0xF4100168
// TODO: others (BeagleBoard Cortex-A8? Other A9s?)
// TODO: immediate next steps: extern void jazelle_main(void);
// * check if we can override jazelle insn execution with custom handlers
// * check what the control registers actually do
// * enumerate what all insns do
__attribute__((__naked__)) #define GPFSEL1 (*(volatile uint32_t*)0x20200004)
static uint32_t arm_get_id(void) { #define GPSET0 (*(volatile uint32_t*)0x2020001C)
asm volatile( #define GPCLR0 (*(volatile uint32_t*)0x20200028)
"mrc p15, 0, r0, c0, c0, 0\n" #define GPPUD (*(volatile uint32_t*)0x20200094)
"bkpt #4\n" #define GPPUDCLK0 (*(volatile uint32_t*)0x20200098)
"bx lr\n"
); #define AUX_ENABLES (*(volatile uint32_t*)0x20215004)
#define AUX_MU_IO_REG (*(volatile uint32_t*)0x20215040)
#define AUX_MU_IER_REG (*(volatile uint32_t*)0x20215044)
#define AUX_MU_IIR_REG (*(volatile uint32_t*)0x20215048)
#define AUX_MU_LCR_REG (*(volatile uint32_t*)0x2021504C)
#define AUX_MU_MCR_REG (*(volatile uint32_t*)0x20215050)
#define AUX_MU_LSR_REG (*(volatile uint32_t*)0x20215054)
#define AUX_MU_MSR_REG (*(volatile uint32_t*)0x20215058)
#define AUX_MU_SCRATCH (*(volatile uint32_t*)0x2021505C)
#define AUX_MU_CNTL_REG (*(volatile uint32_t*)0x20215060)
#define AUX_MU_STAT_REG (*(volatile uint32_t*)0x20215064)
#define AUX_MU_BAUD_REG (*(volatile uint32_t*)0x20215068)
void uart_putc(char c) {
while (!(AUX_MU_LSR_REG & 0x20)) asm volatile("nop");
AUX_MU_IO_REG = c;
}
void uart_puts(const char* s) {
for (; s && *s; ++s) {
uart_putc(*s);
}
}
void uart_putdata(const uint8_t* p, size_t size) {
for (size_t i = 0; i < size; ++i) {
uart_putc((char)p[i]);
}
} }
__attribute__((__naked__)) int main() {
static uint32_t jazelle_get_id(void) { AUX_ENABLES=1;
asm volatile( AUX_MU_IER_REG=0;
"mrc p14, 7, r0, c0, c0, 0\n" AUX_MU_CNTL_REG=0;
"bkpt #5\n" AUX_MU_LCR_REG=3;
"bx lr\n" AUX_MU_MCR_REG=0;
); AUX_MU_IER_REG=0;
} AUX_MU_IIR_REG=0xC6;
AUX_MU_BAUD_REG=270;
__attribute__((__aligned__(1024))) uint32_t ra = GPFSEL1;
static struct { ra&=~(7<<12); //gpio14
void* handlers[512]; ra|=2<<12; //alt5
uint8_t stack[256]; GPFSEL1=ra;
uint8_t locals[256];
} jazelle_block;
/* GPPUD=0;
* c0: Jazelle Identity register (read-only) for (int ra=0;ra<150;ra++) asm volatile("nop");
Bits 0-11: Subarchitecture-defined bits (reads as 4, meaning unknown) GPPUDCLK0=(1<<14);
Bits 12-19: Subarchitecture (reads as 0, Jazelle V1 according to documentation) for (int ra=0;ra<150;ra++) asm volatile("nop");
Bits 20-27: Implementor (reads as 0x41, ARM Limited according to documentation) GPPUDCLK0=0;
Bits 28-31: Architecture (reads as 6, ARMv5TEJ according to documentation)
c1: Operating System Control register
Bit 0: Configuration Disabled (CD) (documented)
Bit 1: Configuration Valid (CV) (documented)
c2: Main Configuration register
Bit 0: Jazelle Enable (JE) (documented)
Bits 26-28: Unknown
Bit 29: If set, array object contains its elements directly, otherwise it contains a pointer to its elements
Bit 31: Disable array instructions if set?
c3: Array object layout register
Bits 0-7: Unknown
Bits 8-11: Offset (in words) within array object of first element or of pointer to first element
Bits 12-15: Offset (in words) within array object of length
Bit 16: If set, offset to length is subtracted, otherwise added
Bits 17-19: Array length shift value (number of elements = stored length >> this)
Bits 20-21: Disable array instructions if set?
*/
static uint32_t jazelle_exit_save; AUX_MU_CNTL_REG=2;
//uart_putc('A');
__attribute__((__naked__))
static int jazelle_exec_native(const void* bytecode, const void* block) {
// inline asm parameters seems to be borking in GCC sooooo lets do it this way
(void)bytecode; (void)block; (void)&jazelle_exit_save;
asm volatile(
"push {r4-r12,lr}\n"
"mov lr, r0\n"
// init handler table pointer and stack pointer
"mov r5, r1\n"
"add r6, r5, #0x800\n"
"add r7, r5, #0x900\n"
// "r8: Pointer to constant pool? (haven't checked this yet)" -Hackspire
// set configuration valid & jazelle enable bits
"mov r0, #2\n"
"mcr p14, 7, r0, c1, c0, 0\n"
"mov r0, #1\n"
"mcr p14, 7, r0, c2, c0, 0\n"
// apparently there's no good way to find the exit point from jazelle,
// so we're going to hack that into the stuff now
"ldr r12, =jazelle_exit_save\n"
"adr r0, .Ljazend\n"
"str r0, [r12]\n"
// switch to jazelle mode
"adr r12, .Lno_jazelle\n"
"bxj r12\n"
".Ljazend:\n"
"mov r0, #0\n"
"b .Lend\n"
".Lno_jazelle:\n"
"bkpt #1\n"
"mov r0, #1\n"
".Lend:\n"
"mov r5, #0\n"
"mcr p14, 7, %r5, c1, c0, 0\n"
"mcr p14, 7, %r5, c2, c0, 0\n"
"pop {r4-r12,lr}\n"
"bx lr\n"
".pool\n"
);
}
__attribute__((__naked__))
static void handler_idiv(void) {
// r0 = 3
// r1 = 4
// r2 = 2
// editing the above has no effect
// NOTE: these depend on the stack content, i.e. it's not a moving register
// window. pushes happen in the following order: r0,r1,r2,r3
// TODO: when the 'register stack cache' is full, what happens? does
// it loop or does it act in a FIFO way, moving r0<-r1<-r2<-r3?
// how can the fillrate be known??? (libjz says r5 & 3 but i
// dont see anything like that, maybe its an ARM11 thing?)
// "r4: Copy of local variable 0. Only valid when local variable 0 is a
// single word (i.e. int, float, or Object; not long or double)"
// -Hackspire
//
// [r6-4] is stack top (2)
// [r6-8] is 4
// etc
// use the above to manipulate the stack, eg. "iadd" is implemented as:
// - add r1, r2 // or equivalently, read from stack i guess
// - str r1, [r6, #-8] // store to the place where it will be read
// - sub r6, #4 // pop off & discard stack top element
// NOTE: this input usage (with r1 and r2) is NOT robust at all, use memory
// reads instead!
asm volatile(
"bkpt #3\n"
// FIXME: read out stack contents in a better way
"add r1, r2\n"
"str r1, [r6,#-8]\n"
"sub r6, #4\n"
// return to jazelle (yes lr has to be incremented otherwise the
// current instruction keeps getting executed in a loop)
"add lr, #1\n"
"bxj r12\n" // FIXME: r12 can be modified by jazelle so it should be restored to something
);
}
__attribute__((__naked__))
static void handler_ireturn(void) {
int result;
asm volatile(
"bkpt #2\n"
"ldr %[res], [r6, #-4]!\n"
:[res]"=r"(result)
);
//iprintf("result=%d\r\n", result); // FIXME: save & restore r0-r3 if ret implemented properly
// get back to original code
// TODO: later stage: get back to previous bytecode stuff
asm volatile(
"ldr r12, %[exsav]\n"
"bx r12\n"
:
:[exsav]"m"(jazelle_exit_save)
:"r12"
);
__builtin_unreachable();
}
static int jazelle_exec(const uint8_t* bytecode) {
jazelle_block.handlers[0x6C] = handler_idiv;
jazelle_block.handlers[0xAC] = handler_ireturn;
/*
* +000-3FF: Unhandled bytecodes
The stack is flushed to memory before calling any of these handlers, so they may modify r0-r3 freely
+400: Null pointer exception
+404: Array index out of bounds exception
+40C: Jazelle mode entered with JE = 0
+410: Configuration invalid (Jazelle mode entered with CV = 0)
CV is automatically set to 1 on entering this handler
+414: Prefetch abort occurred in middle of instruction
-Hackspire
*/
const void* block = &jazelle_block;
return jazelle_exec_native(bytecode, block);
}
// https://github.com/SonoSooS/libjz/wiki/Java-instruction-set
static uint8_t bytecode_test1[] = {
0x06, // iconst_3
0x07, // iconst_4
0x05, // iconst_2
0x6C, // idiv
0x04, // iconst_1
0x60, // iadd
0x60, // iadd
0xAC, // ireturn
};
void jazelle_main(void) {
uint32_t aid = arm_get_id();
uint32_t jid = jazelle_get_id();
asm volatile("bkpt #0\n");
//iprintf("hello world! ARM coreID=0x%lx jazelle ID=0x%lx\r\n", aid, jid);
while (jid == 0) ;
int r = jazelle_exec(bytecode_test1);
//iprintf("retcode=%d\r\n", r);
while (true) ;
}
void main(void) {
jazelle_main(); jazelle_main();
}
__attribute__((__naked__, __section__(".entry"))) return 0;
void _start(void) {
asm volatile(
"ldr sp, =0x00010000\n"
"bl main\n"
"1: b 1b\n"
".pool\n"
);
} }

View File

@ -1,35 +1,44 @@
ENTRY(_start) ENTRY(_start)
MEMORY
{
ram : ORIGIN = 0x8000, LENGTH = 0x80000
}
SECTIONS SECTIONS
{ {
. = 0x00001000; /*. = 0x00001000;*/
.text : .text :
{ {
*(.entry*) *(.entry*)
*(.text*) *(.text*)
*(.rodata*) *(.rodata*)
} } > ram
.data : .data :
{ {
*(.data*) *(.data*)
} } > ram
.ARM.extab : /*.ARM.extab :
{ {
*(.ARM.extab* .gnu.linkonce.armextab.*) *(.ARM.extab* .gnu.linkonce.armextab.*)
} } > ram
__exidx_start = .; __exidx_start = .;
.ARM.exidx : .ARM.exidx :
{ {
*(.ARM.exidx* .gnu.linkonce.armexidx.*) *(.ARM.exidx* .gnu.linkonce.armexidx.*)
} } > ram
__exidx_end = .; __exidx_end = .;*/
__bss_start = .;
.bss : .bss :
{ {
*(.bss*) *(.bss*)
} } > ram
__bss_end = .;
_heap = .;
} }

113
rpi/vectors.s Normal file
View File

@ -0,0 +1,113 @@
@ vim: set ft=armv5:
.section ".entry", "awx", %progbits
.global VECTORS
VECTORS:
ldr pc, reset_handler
ldr pc, undefined_handler
ldr pc, swi_handler
ldr pc, prefetch_handler
ldr pc, data_handler
ldr pc, unused_handler
ldr pc, irq_handler
ldr pc, fiq_handler
reset_handler:
.4byte _start
undefined_handler:
.4byte hang
swi_handler:
.4byte hang
prefetch_handler:
.4byte hang
data_handler:
.4byte hang
unused_handler:
.4byte hang
irq_handler:
.4byte hang
fiq_handler:
.4byte hang
.global _start
_start:
@ copy over exception vectors
mov r0, #0x8000
mov r1, #0
ldmia r0!, {r2-r9}
stmia r1!, {r2-r9}
ldmia r0!, {r2-r9}
stmia r1!, {r2-r9}
@ IRQ mode
mov r0, #0xd2
msr cpsr_c, r0
mov sp, #0x8000
@ FIQ mode
mov r0, #0xd1
msr cpsr_c, r0
mov sp, #0x4000
@ SVC mode
mov r0, #0xd3
msr cpsr_c, r0
mov sp, #0x08000000
mov r0, #0
mcr p15, 0, r0, c3, c0, 0 @ disable write buffer
mcr p15, 0, r0, c2, c0, 0 @ disable icache & dcache
mcr p15, 0, r0, c2, c0, 1
@ disable stuff
mrc p15, 0, r0, c1, c0, 0
ldr r1, =((1<<12)|(1<<2)|(1<<0)) @ icache/dcache/mpu enable bits
bic r0, r1
mcr p15, 0, r0, c1, c0, 0
@ clear bss
ldr r0, =__bss_start
ldr r1, =__bss_end
mov r2, #0
mov r3, #0
zeroloop:
strd r2, r3, [r0], #8
cmp r0, r1
bne zeroloop
bl main
@ fallthru
hang:
b hang
.pool
/*.section ".text.utils", "ax", %progbits
.global PUT32
PUT32:
str r1,[r0]
bx lr
.global GET32
GET32:
ldr r0,[r0]
;@ bx lr
.global dummy
dummy:
bx lr*/
;@-------------------------------------------------------------------------
;@
;@ Copyright (c) 2012 David Welch dwelch@dwelch.com
;@
;@ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
;@
;@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
;@
;@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
;@
;@-------------------------------------------------------------------------