Question

I am developing a program that will bootstrap another program, so as a result I need to preserve the registers being passed to my program so that i can restore them before jumping to the program that should have loaded. It's a bare metal system, no OS, no MMU (present, but unsed at the moment).

Here is my code, I would just like to know if it is correct or not since i don't have an arm board to test on and i have to submit this soon,

also is it true that pc relative stores can use only source registers lower registers (r0-r7), i thought this was only thumb problem of not having access to high registers in certain instructions due to limited instruction width.

reset: @ entry point, mapped in reset vector

/* Store registers for bootstrapping */
STR     R0, [PC, #128]
STR     R1, [PC, #128]
STR     R2, [PC, #128]
STR     R3, [PC, #128]
STR     R4, [PC, #128]
STR     R5, [PC, #128]
STR     R6, [PC, #128]
STR     R7, [PC, #128]

/* Following registers can't be used in pc relative load/store */
MOV     R0, R8
STR     R0, [PC, #128]
MOV     R0, R9
STR     R0, [PC, #128]
MOV     R0, R10
STR     R0, [PC, #128]
MOV     R0, R11
STR     R0, [PC, #128]
MOV     R0, R12
STR     R0, [PC, #128]
MOV     R0, SP
STR     R0, [PC, #128]
MOV     R0, LR
STR     R0, [PC, #128]
MRS     R0, CPSR
STR     R0, [PC, #128]
MRS     R0, SPSR
STR     R0, [PC, #128]
ISB     SY
B       clear_regs

saved_regs:
.rept 32
    .word 0x00000000
.endr

.align
clear_regs:
MOV     R0,  #0
MOV     R1,  #0
MOV     R2,  #0
MOV     R3,  #0
MOV     R4,  #0
MOV     R5,  #0
MOV     R6,  #0
MOV     R7,  #0
MOV     R8,  #0
MOV     R9,  #0
MOV     R10, #0
MOV     R11, #0
MOV     R12, #0
MOV     SP,  #0
MOV     LR,  #0
Was it helpful?

Solution

In ARM mode (vs Thumb mode) it's fine to use the high registers in a PC relative store. Your assembler will warn you if something like that is not allowed. You might also want to consider using the STM (Store Multiple) instruction which allows you to specify a list of registers rather than doing them individually.

You should probably let the assembler do the 'hard' work of calculating the PC offsets by using symbols instead of specifying the offsets by hand.

reset: @ entry point, mapped in reset vector

/* Store registers for bootstrapping */
STR     R0, saved_regs
ADR     R0, saved_regs + 4

STMIA r0!, {r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15}

MRS     R1, CPSR
MRS     R2, SPSR
STMIA   R0, {r1, r2}
ISB     SY
B       clear_regs

saved_regs:
.rept 32
.word 0x00000000
.endr
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top