summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/fw_base.S44
1 files changed, 42 insertions, 2 deletions
diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index 1a3c760..6270bbc 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -27,6 +27,17 @@
add \__d4, \__s4, zero
.endm
+/*
+ * If __start_reg <= __check_reg and __check_reg < __end_reg then
+ * jump to __pass
+ */
+.macro BRANGE __start_reg, __end_reg, __check_reg, __jump_lable
+ blt \__check_reg, \__start_reg, 999f
+ bge \__check_reg, \__end_reg, 999f
+ j \__jump_lable
+999:
+.endm
+
.align 3
.section .entry, "ax", %progbits
.globl _start
@@ -45,22 +56,51 @@ _start:
REG_S t1, 0(t0)
/* Relocate if load address != link address */
+_relocate:
la t0, _link_start
REG_L t0, 0(t0)
la t1, _link_end
REG_L t1, 0(t1)
la t2, _load_start
REG_L t2, 0(t2)
+ sub t3, t1, t0
+ add t3, t3, t2
beq t0, t2, _relocate_done
la t4, _relocate_done
sub t4, t4, t2
add t4, t4, t0
-_relocate_copy:
+ blt t2, t0, _relocate_copy_to_upper
+_relocate_copy_to_lower:
+ ble t1, t2, _relocate_copy_to_lower_loop
+ la t3, _boot_hart_done
+ BRANGE t2, t1, t3, _start_hang
+ la t3, _relocate
+ la t5, _relocate_done
+ BRANGE t2, t1, t3, _start_hang
+ BRANGE t2, t1, t5, _start_hang
+ BRANGE t3, t5, t2, _start_hang
+_relocate_copy_to_lower_loop:
REG_L t3, 0(t2)
REG_S t3, 0(t0)
add t0, t0, __SIZEOF_POINTER__
add t2, t2, __SIZEOF_POINTER__
- blt t0, t1, _relocate_copy
+ blt t0, t1, _relocate_copy_to_lower_loop
+ jr t4
+_relocate_copy_to_upper:
+ ble t3, t0, _relocate_copy_to_upper_loop
+ la t2, _boot_hart_done
+ BRANGE t0, t3, t2, _start_hang
+ la t2, _relocate
+ la t5, _relocate_done
+ BRANGE t0, t3, t2, _start_hang
+ BRANGE t0, t3, t5, _start_hang
+ BRANGE t2, t5, t0, _start_hang
+_relocate_copy_to_upper_loop:
+ add t3, t3, -__SIZEOF_POINTER__
+ add t1, t1, -__SIZEOF_POINTER__
+ REG_L t2, 0(t3)
+ REG_S t2, 0(t1)
+ blt t0, t1, _relocate_copy_to_upper_loop
jr t4
_relocate_done: