Firmware Fn getNodeVidArmMP0 - krcenov/RNS510-Map-Viewer GitHub Wiki

getNodeVidArmMP0 โ€” RoutePath::getNodeVidArmMP0

Part of Firmware Reversing.

  • File offset: 0x80c7d4 (true prologue start; the naive symbol-table field-4 address, 0x80c87c, lands 168 bytes into the function's body)
  • VA: 0xf709a4c8 (= 0x80c7d4 + 0xf688dcf4)
  • Status: ๐ŸŸข Fully traced
  • Real name source: symbol/EH-descriptor table, loose (non-strict) match

Directly relevant to this project's own topology work: the name combines "Vid" (this project's own vnodeID terminology, README ยง2.6/ยง3.2), "Arm" (a junction's connected segment), and "MP0" (the already-cracked tile format).

Disassembly

0x80c7d4: stwu     r1, -0x140(r1)
0x80c7d8: mflr     r0
0x80c7dc: stw      r23, 0x11c(r1)
0x80c7e0: stw      r24, 0x120(r1)
0x80c7e4: stw      r25, 0x124(r1)
0x80c7e8: stw      r26, 0x128(r1)
0x80c7ec: stw      r27, 0x12c(r1)
0x80c7f0: stw      r28, 0x130(r1)
0x80c7f4: stw      r29, 0x134(r1)
0x80c7f8: stw      r30, 0x138(r1)
0x80c7fc: stw      r31, 0x13c(r1)
0x80c800: stw      r0, 0x144(r1)
0x80c804: or.      r31, r5, r5              ; arg3 (bitmask?) tested for zero
0x80c808: mr       r30, r3                  ; arg1 = this
0x80c80c: mr       r23, r4                  ; arg2
0x80c810: beq      0x80c8f0                 ; arg3==0 -> jump into shared partial epilogue
0x80c814: li       r11, 0x1f                ; loop 31 times
0x80c818: lis      r0, -0x1248
0x80c81c: mtctr    r11
0x80c820: ori      r0, r0, 0x8320
0x80c824: stw      r0, 0x90(r1)
0x80c828: addi     r9, r1, 0x94
0x80c82c: li       r0, 1
0x80c830: stw      r0, 0(r9)                ; build [1, 2, 4, 8, ...] on the stack
0x80c834: addi     r9, r9, 4
0x80c838: slwi     r0, r0, 1
0x80c83c: bdnz     0x80c830                 ; power-of-2 lookup table, 31 entries
0x80c840: lis      r9, -0x8ba
0x80c844: addi     r29, r1, 0x90
0x80c848: addi     r27, r9, -0x3d34
0x80c84c: addi     r28, r1, 0x10
0x80c850: mtlr     r27
0x80c854: mr       r4, r29
0x80c858: mr       r3, r28
0x80c85c: mr       r25, r29
0x80c860: mr       r24, r28
0x80c864: mr       r26, r27
0x80c868: blrl                              ; virtual call #1
0x80c86c: mr       r3, r29
0x80c870: mtlr     r27
0x80c874: mr       r4, r28                  ; <- loop-back target (see 0x80c8d8)
0x80c878: blrl                              ; virtual call #2
0x80c87c: lis      r9, -0x8ba
0x80c880: addi     r29, r9, -0x3d64
0x80c884: mr       r3, r24
0x80c888: mtlr     r26
0x80c88c: mr       r4, r25
0x80c890: blrl                              ; virtual call #3
0x80c894: andi.    r0, r31, 1               ; test LOW BIT of arg3
0x80c898: beq      0x80c8b0
0x80c89c: mr       r4, r30
0x80c8a0: mtlr     r29
0x80c8a4: mr       r3, r24
0x80c8a8: blrl                              ; virtual call #4 -- only if bit set
0x80c8ac: mr       r30, r3
0x80c8b0: srawi.   r31, r31, 1              ; shift to next bit
0x80c8b4: beq      0x80c8ec                 ; no more set bits -> fall into epilogue
0x80c8b8: mr       r3, r25
0x80c8bc: mtlr     r26
0x80c8c0: mr       r4, r24
0x80c8c4: <data>    000d0029   ; not a valid instruction -- likely an EH-descriptor table entry
0x80c8c8: <data>    00000008   ; not a valid instruction -- likely an EH-descriptor table entry
0x80c8cc: mr       r3, r25
0x80c8d0: <data>    000d0019   ; not a valid instruction -- likely an EH-descriptor table entry
0x80c8d4: <data>    00000070   ; not a valid instruction -- likely an EH-descriptor table entry
0x80c8d8: bne      0x80c874                 ; LOOP: back to virtual call #2
0x80c8dc: xor      r3, r30, r23
0x80c8e0: lwz      r0, 0x144(r1)
0x80c8e4: mtlr     r0
0x80c8e8: lwz      r23, 0x11c(r1)
0x80c8ec: lwz      r24, 0x120(r1)           ; <- arg3==0 early-exit joins here
0x80c8f0: lwz      r25, 0x124(r1)
0x80c8f4: lwz      r26, 0x128(r1)
0x80c8f8: lwz      r27, 0x12c(r1)
0x80c8fc: lwz      r28, 0x130(r1)
0x80c900: lwz      r29, 0x134(r1)
0x80c904: lwz      r30, 0x138(r1)
0x80c908: lwz      r31, 0x13c(r1)
0x80c90c: addi     r1, r1, 0x140
0x80c910: <data>    02190021   ; not a valid instruction -- likely an EH-descriptor table entry
0x80c914: <data>    00000048   ; not a valid instruction -- likely an EH-descriptor table entry
0x80c918: lis      r11, -0x8ba              ; <- a DIFFERENT function starts here

Analysis

arg3 (r5) is a bitmask, tested for zero up front โ€” if zero, execution jumps straight into the middle of the register-restore sequence at 0x80c8f0 (a real compiler-generated shared partial epilogue entry point, not a bug). Otherwise: builds a 31-entry power-of-2 lookup table (1, 2, 4, ... 2^30) on the stack, then walks arg3 bit by bit (andi./srawi. peeling off the low bit each iteration), calling a virtual method for each SET bit found, with a real backward branch (0x80c8d8: bne 0x80c874) closing the loop back to the per-bit virtual-call site. Consistent with "for each requested arm in this bitmask, resolve its VID individually."

The exact final blr wasn't pinned down: the words right after addi r1,r1,0x140 (0x80c910/0x80c914) don't decode as valid instructions, and a genuinely different function's prologue (lis r11,-0x8ba at 0x80c918) starts immediately after โ€” most likely an EH-descriptor table entry sits between the two functions, same pattern seen elsewhere in this file. Noted honestly rather than assumed; doesn't affect the function's traced logic above.

Callees โ€” checked, unreachable (corrects an earlier claim)

Its own virtual-call targets (computed via lis r9,-0x8ba + addi ...,-0x3d34 and ...,-0x3d64, both at 0x80c840-0x80c880) resolve to file offsets 0xbce5d8 and 0xbce5a8. This page originally, wrongly, called these "within the reliable <9MB range." They are actually ~12.4MB in, past the confirmed 9MB boundary โ€” the same already-known readNodeMP0 limitation (Firmware-Fn-readNodeMP0), not new territory. Neither is a valid prologue, no real function start exists within 3,000 bytes of either, and 0xbce5d8 itself lands on readable text (a mangled-name fragment, "...iptor__C...") rather than code.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ