Poked at this a bit. It looks like everything's all been inlined together into one big pile of instructions and interleaved, but I think I've made a bit of progress.
Consider these instructions from the beginning of Matt's assembly sequence:
0x6c1b455d50 cmp w8, #6
0x6c1b455d54 movn w9, #0x45
0x6c1b455d58 cinc w23, w9, ne
We are loading the constant ~0x45, then incrementing it if w8 is not 6. Interestingly, ~0x45 is 0xffffffba, which is precisely the mystery value that Matt found in x12. Later on, we have these instructions:
0x6c1b455d7c adrp x19, #0x6c1d6c5000
0x6c1b455d80 add x19, x19, #0x1d8
0x6c1b455d94 and x9, x23, #0xff
0x6c1b455d9c add x9, x19, x9, lsl #3
0x6c1b455da8 ldrsb w10, [x9, #1]
The first two instructions load a hardcoded pointer. The next two compute
base_address + (our_mystery_register & 0xff) << 3. This looks like we're finding an entry from the CodeSpecTable. The last instruction loads (and sign-extends) a value from the CodeSpec: specifically, nuses is at offset 1.
0xffffffba & 0xff is 0xba, which is JSOp::GetAliasedVar. 0xbb is JSOp::GetAliasedDebugVar. So the first set of instructions I pulled out maps to this code, which we can confirm by noticing that NameLocation::Kind::EnvironmentCoordinate is 6, matching the hardcoded constant.
Staring at the rest of the code, I've convinced myself that x27 is the BytecodeEmitter, and it's being used to reference the vector of bytecode we're emitting. A BytecodeEmitter contains a BytecodeSection at offset 32, which contains a BytecodeVector at offset 0. Doing the math, this means that x27+0x28 is mBegin, x27+0x30 is the length, and x27+0x38 is the capacity. With that in mind, here's another interesting sequence of instructions. In this code, x23/w23 holds
0x6c1b455d4c ldr x24, [x27, #0x30] // x24 = offset (length of buffer before writing anything)
0x6c1b455da0 ldr x10, [x27, #0x28] // x10 is address of buffer
0x6c1b455da4 strb w23, [x10, x24] // write opcode in buffer at offset
0x6c1b455dac ldr x9, [x27, #0x28] // x9 is address of buffer
0x6c1b455db4 add x11, x9, x24 // x11 is offset of opcode we just wrote
0x6c1b455db8 ldrb w12, [x11] // load the opcode
0x6c1b455dbc add x10, x19, x12, lsl #3 // look it up in the codespec table
0x6c1b455dc0 ldrsb w13, [x10, #1] // CRASH!
In short, we store the opcode in the buffer, then load it again to use as an index into the codespec table. The really interesting thing here is the ldrb. The ARM docs describe it as:
LDRB Wt, addr
Load Byte: loads a byte from memory addressed by addr, then zero-extends it to Wt.
Since we just stored
0xba, that's what x12 should contain. However, that's not what we're seeing. Looking at a dump, I see
x12 = 0x00000000ffffffba. That's not zero-extended.
I have a strong suspicion that Samsung (or whoever designed this particular chip) messed up their store forwarding, and accidentally forwarded the entire register without clearing the upper bits.