PTR_LI t0, CONFIG_SYS_MONITOR_BASE
PTR_SUB s1, s2, t0 # s1 <-- relocation offset
- PTR_LA t3, in_ram
- PTR_L t2, -(3 * PTRSIZE)(t3) # t2 <-- __image_copy_end
+ PTR_LA t2, __image_copy_end
move t1, a2
- PTR_ADD gp, s1 # adjust gp
-
/*
* t0 = source address
* t1 = target address
blt t0, t2, 1b
PTR_ADDU t1, PTRSIZE
- /* If caches were enabled, we would have to flush them here. */
- PTR_SUB a1, t1, s2 # a1 <-- size
- PTR_LA t9, flush_cache
- jalr t9
- move a0, s2 # a0 <-- destination address
-
- /* Jump to where we've relocated ourselves */
- PTR_ADDIU t0, s2, in_ram - _start
- jr t0
- nop
-
- PTR __rel_dyn_end
- PTR __rel_dyn_start
- PTR __image_copy_end
- PTR _GLOBAL_OFFSET_TABLE_
- PTR num_got_entries
-
-in_ram:
/*
* Now we want to update GOT.
*
* GOT[0] is reserved. GOT[1] is also reserved for the dynamic object
* generated by GNU ld. Skip these reserved entries from relocation.
*/
- PTR_L t3, -(1 * PTRSIZE)(t0) # t3 <-- num_got_entries
- PTR_L t8, -(2 * PTRSIZE)(t0) # t8 <-- _GLOBAL_OFFSET_TABLE_
+ PTR_LA t3, num_got_entries
+ PTR_LA t8, _GLOBAL_OFFSET_TABLE_
PTR_ADD t8, s1 # t8 now holds relocated _G_O_T_
PTR_ADDIU t8, t8, 2 * PTRSIZE # skipping first two entries
PTR_LI t2, 2
PTR_ADDIU t8, PTRSIZE
/* Update dynamic relocations */
- PTR_L t1, -(4 * PTRSIZE)(t0) # t1 <-- __rel_dyn_start
- PTR_L t2, -(5 * PTRSIZE)(t0) # t2 <-- __rel_dyn_end
+ PTR_LA t1, __rel_dyn_start
+ PTR_LA t2, __rel_dyn_end
b 2f # skip first reserved entry
PTR_ADDIU t1, 2 * PTRSIZE
blt t1, t2, 1b
PTR_ADDIU t1, 2 * PTRSIZE # each rel.dyn entry is 2*PTRSIZE bytes
+ /*
+ * Flush caches to ensure our newly modified instructions are visible
+ * to the instruction cache. We're still running with the old GOT, so
+ * apply the reloc offset to the start address.
+ */
+ PTR_LA a0, __text_start
+ PTR_LA a1, __text_end
+ PTR_SUB a1, a1, a0
+ PTR_LA t9, flush_cache
+ jalr t9
+ PTR_ADD a0, s1
+
+ PTR_ADD gp, s1 # adjust gp
+
/*
* Clear BSS
*