📄 bootstrap.s
字号:
mov #ERR_NO_METHOD, r0 /* Illegal method; set error in R0 and spin */
method_ok:
mov.l 1f, r0
add r1, r0 /* R0 = address of method entry */
mov.l @r0, r0 /* Get method function address */
jsr @r0
nop
tst r0, r0 /* Did the method succeed ? */
bf/s fatal
mov #ERR_METHOD_FAILED, r0 /* Method failed; set error in R0 and spin */
dt r9 /* Do the next section */
bf/s next_section
add #0x10, r8
bra 3f /* Finished loading CPU */
nop
.balign 4
1: .long method_table
2: .long method_table_size
3:
/*
* Now that all sections have been relocated purge the D-cache by
* writing 0 to every OC array entry to ensure we execute what we
* relocated.
*/
#define OC_ARRAY_BASE 0xF4000000
#define OC_NUM_ENTRIES (CACHE_SIZE / 32)
mov.l 3f, r1 /* R1 = OC array base address */
mov.w 2f, r2 /* R2 = # of OC array entries */
mov #0, r0
1:
mov.l r0, @r1
dt r2
add #32, r1
bf 1b
#if defined(__SH4_300__) /* SH4-300 and newer cores */
icbi @r1 /* Ensure next instruction is re-fetched */
#else
#if !(defined(__SH4_100__) || defined(__SH4_200__) || defined(__SH4_400__) || defined(__SH4_500__))
#warning -m4-<arch> was not specified - incorrect instructions may be used
#endif
nop /* Required delay to empty pipeline/prefetch */
nop
nop
nop
nop
nop
nop
nop
#endif
bra 4f
nop
2: .word OC_NUM_ENTRIES
.balign 4
3: .long OC_ARRAY_BASE
4:
/*
* If we have a Cryptocore, we now switch on checking of all regions
* prepared as signed blocks and added to the config table, as all code
* has been loaded.
* This allows us to execute the code without the system being reset.
* The function called is a C function and may use the stack, but takes
* no parameters.
*/
#if defined(CRYPTOCORE1) || defined(CRYPTOCORE1_5)
/*
* Call cryptLLRestart() to transition to linked list mode.
*/
mov.l 1f, r0 /* R0 = cryptLLRestart() */
jsr @r0
nop
bra 2f
nop
.balign 4
1: .long _cryptLLRestart
#elif defined(CRYPTOCORE2)
/*
* Call cryptAddConfigTableRegions() to add the config table regions.
*/
mov.l 1f, r0 /* R0 = cryptAddConfigTableRegions() */
jsr @r0
nop
bra 2f
nop
.balign 4
1: .long _cryptAddConfigTableRegions
#endif /* Cryptocore versions */
2:
/*
* Now call boot image entry point.
*/
mov.l @r15+, r0 /* R0 = entry point */
jsr @r0
nop
1: bra 1b /* If return from entry point then loop forever */
nop
/*
* Method to copy a word aligned section from ROM to RAM.
*
* R4 = src, R5 = dst, R6 = length (bytes)
*/
copy_section:
add #3, r6 /* R6 = number of words */
shlr2 r6
1: mov.l @r4+, r0 /* Copy data ... */
mov.l r0, @r5
dt r6
bf/s 1b
add #4, r5
rts
mov #0, r0
/*
* Method to zero a section.
*
* R4 = src, R5 = dst, R6 = length (bytes)
*/
zero_section:
mov #4, r0 /* length < 4 bytes, do byte writes */
cmp/ge r0, r6
bt 2f
mov #0, r0
1: mov.b r0, @r5 /* Zero bytes ... */
dt r6
bf/s 1b
add #1, r5
rts
nop
/*
* length >= 4 bytes, section must be word aligned.
*/
2: add #3, r6 /* Number of words to zero */
shlr2 r6
mov #0, r0
1: mov.l r0, @r5 /* Zero words ... */
dt r6
bf/s 1b
add #4, r5
rts
nop
/*
* Method to run length decode a section.
*
* Not implemented.
*/
rl_decode_section:
rts
mov #-1, r0
/*
* Method to skip a section (do nothing).
*/
skip_section:
rts
mov #0, r0
/*
* Method to inflate a zlib compressed section.
*
* Move parameters into registers used for a C function call, and
* call the C function to do the decompress.
*
* R4 = src, R5 = dst, R6 = srclen (bytes)
*
* uncompress() function requires:
*
* R4 = dst, R5 = &dstlen, R6 = src, R7 = srclen
*/
inflate_section:
mov.l 2f, r0 /* R0 = uncompress() */
tst r0, r0 /* uncompress() available ? */
bf 1f
rts /* No */
mov #-1, r0
1: sts.l pr, @-r15 /* Preserve PR */
mov r6, r7 /* Setup parameters */
mov r4, r6
mov r5, r4
mov #-1, r5
mov.l r5, @-r15
jsr @r0 /* Call uncompress() */
mov r15, r5
add #4, r15
lds.l @r15+, pr /* Restore PR */
rts
nop
.balign 4
2: .long _uncompress
/*
* Method to iterate through a table of pokes.
* Used to configure the on-chip/board peripherals.
*
* Note that the code is executed from the I-cache, with all its
* data in the D-cache.
*/
.balign 32
poke_loop:
mov.l @r1+, r0 /* R0 = opcode */
mov.l @r1+, r2 /* R2 = address */
mov.l @r1+, r3 /* R3 = value */
/*#define END_MARKER .long 0, 0, 0*/
cmp/eq #0, r0 /* End marker ? */
bf 1f
rts /* Return */
nop
/*#define POKE_LONG(A, V) .long 4, A, V*/
1: cmp/eq #4, r0 /* 4 byte write ... */
bf 1f
mov.l r3, @r2
/* #define POKE_SHORT(A, V) .long 2, A, V*/
1: cmp/eq #2, r0 /* 2 byte write ... */
bf 1f
mov.w r3, @r2
/*#define POKE_CHAR(A, V) .long 1, A, V*/
1: cmp/eq #1, r0 /* 1 byte write ... */
bf 1f
mov.b r3, @r2
/*#define OR_LONG(A, V) .long 5, A, V*/
1: cmp/eq #5, r0 /* 4 byte OR ... */
bf 1f
mov.l @r2,r4
or r3,r4
mov.l r4,@r2
/*#define UPDATE_LONG(A, AND, OR) .long 6, A, AND, OR*/
1: cmp/eq #6, r0 /* 4 byte UPDATE ... */
bf 1f
mov.l @r2,r4
and r3,r4
mov.l @r1+,r3 /* R3 = OR value */
or r3,r4
mov.l r4,@r2
/*#define POKE_UPDATE_LONG(A1, A2, AND, SHIFT, OR) .long 8, A1, A2, AND, SHIFT, OR*/
1: cmp/eq #8, r0 /* 4 byte write UPDATE ... */
bf 1f
mov.l @r3,r4
mov.l @r1+,r3 /* R3 = AND value */
and r3,r4
mov.l @r1+,r3 /* R3 = SHIFT value */
shld r3,r4
mov.l @r1+,r3 /* R3 = OR value */
or r3,r4
mov.l r4,@r2
/*#define WHILE_NE(A, AND, VAL) .long 7, A, AND, VAL*/
1: cmp/eq #7, r0 /* WHILE != ... */
bf 1f
mov.l @r1+,r5 /* R5 = compare value */
2: mov.l @r2,r4
and r3,r4
cmp/eq r4,r5
bf 2b
/*#define IF(A, AND, VAL, COMMAND) .long 9, A, AND, VAL; COMMAND*/
1: cmp/eq #9,r0 /* IF == ... next op */
bf 1f
mov.l @r1+,r5
mov.l @r2,r4
and r3,r4
cmp/eq r4,r5
bt poke_loop /* Compare succeeded - perform next op */
2: /* Skip the next operation (read past it) */
mov.l @r1+,r0 /* R0 = opcode */
mov.l @r1+,r2 /* skip address */
mov.l @r1+,r2 /* skip value */
/* How many further reads do we need to skip? */
cmp/eq #9,r0 /* If it's another IF, skip 1 and go back to start of skip loop */
bf 3f
mov.l @r1+,r2
bra 2b
nop
3: mov #5,r2
cmp/gt r2,r0
bf 5f /* 0 further reads */
cmp/eq #8,r0 /* Is it number 8 (3 reads, otherwise 1 read) */
bf 4f
mov.l @r1+,r2 /* Skip 1 read */
mov.l @r1+,r2 /* Skip 1 read */
4: mov.l @r1+,r2 /* Skip 1 read and continue */
5: bra poke_loop
nop
1: mov #1,r0 /* Small delay (65536) */
swap.w r0, r0
2: add #-1,r0 /* Delay ... */
cmp/eq #0, r0
bf 2b
bt poke_loop
/*
* Simple implementation of memcpy() to avoid dependency on C library.
*
* R4 = dst, R5 = src, R6 = srclen (bytes)
*/
.global _memcpy
_memcpy:
mov r4, r0 /* Check if source and destination are word aligned */
or r5, r0
tst r6, r6
bt/s 3f /* ... skip zero length copy */
tst #3, r0
bf 2f
mov r6, r2
shlr2 r6
1: mov.l @r5+, r0 /* Copy words ... */
dt r6
mov.l r0, @r4
bf/s 1b
add #4, r4
mov r2, r0
and #3, r0 /* Fall through to byte copy for any odd bytes */
mov r0, r6
tst r6, r6
bt 3f
2: mov.b @r5+, r0 /* Copy bytes ... */
dt r6
mov.b r0, @r4
bf/s 2b
add #1, r4
3: rts
mov r4, r0
.balign 4
p0_mask:
.long 0x1FFFFFFF
failsafe_ics_addr:
.long FLASH_FAILSAFE_ICS
main_image_directory_ptr:
.long FLASH_MAIN_ICD_PTR
boot_signature:
.long BOOT_FLAG | CPU_NUMBER | FLASH_CPU_ARCH_SH4
.end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -