Files
marfrit 9c20eb0135 04_train_phy_block: clang -Oz + 32-bit-load pattern = 100% size match
Changed u64v handshake reads to u32v with an inline zero-extending
upcast. Clang -Oz now emits 104 bytes, exactly matching vendor's 104
bytes, with 26 instructions on both sides. Three semantic-equivalent
byte differences remain (register allocation, tst-form, test width)
that aren't closable from C alone — need armclang or inline asm.

Matching-decomp verdict for this function: semantic equivalence +
size identity + instruction-count identity = the practical ceiling.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 09:16:00 +02:00

25 lines
990 B
C

/* Iteration 3: match vendor's "32-bit load, 64-bit test" pattern.
* The u64v volatile forced clang to 64-bit loads and hoist the base
* address out of the loop. Use u32v loads but upcast for the test. */
typedef volatile unsigned int u32v;
static inline unsigned long xld(u32v *p) {
/* Zero-extend 32-bit load to 64-bit implicit via ldr w; tst x. */
return (unsigned long)*p;
}
void train_phy_block(unsigned long ctx)
{
unsigned char *phy = (unsigned char *)(*(unsigned long *)(ctx + 0xb8) + 0x8000);
*(u32v *)(phy + 0x110) = 0xf000f000u;
while ((*(u32v *)(phy + 0x118) & 0xf0000000u) == 0u) ;
while ((*(u32v *)(phy + 0x120) & 0xf0000000u) == 0u) ;
*(u32v *)(phy + 0x160) = 0x30003u;
*(u32v *)(phy + 0x154) = 0x30003u;
while ((xld((u32v *)(phy + 0x184)) & 3ul) == 0ul) ;
*(u32v *)(phy + 0x154) = 0x30000u;
while ((xld((u32v *)(phy + 0x184)) & 3ul) != 0ul) ;
*(u32v *)(phy + 0x160) = 0x30000u;
*(u32v *)(phy + 0x110) = 0xf0000000u;
}