The ARM710T in the Series 5mx is ARMv4T, but ARM710::executeInstruction has no
case for the ARMv4 "extra load/store" group (LDRH / STRH / LDRSB / LDRSH). Those
instructions fall through to the catch-all
else if ((i & 0x0C000000) == 0x00000000)
cycles += execDataProcessing(...);
and are executed as data-processing operations. There is no Undefined32
exception and no diagnostic: the instruction silently writes a garbage value to
Rd, may update the flags, and never touches memory.
Concrete example
EPOC R5's ATA media driver reads a sector through a 16-bit block-copy loop in
EpBus.dll at 0x500553d4:
500553f0 e1d020b0 ldrh r2, [r0]
500553f4 e1d030b0 ldrh r3, [r0]
500553f8 e1822803 orr r2, r2, r3, lsl #16
500553fc e4852004 str r2, [r5], #4
50055400 e1550006 cmp r5, r6
50055404 3afffff9 blo #0x500553f0
0xe1d020b0 & 0x0C000000 == 0, so it is dispatched to execDataProcessing,
which decodes bits 24:21 = 0xE as BIC with S=1 and Rd=2. The emulator therefore
computes BICS r2, r0, ... instead of loading a halfword: no bus access is
generated at all, and the condition flags are clobbered as a side effect.
Observable symptom: EPOC issues an ATA IDENTIFY DEVICE, the device asserts DRQ,
and EPOC then requests the data block — but the emulated hardware sees zero reads
of the data register, because the loop never performs a memory access.
Second, related issue
Implementing the group needs a 16-bit access size, which the memory bus does not
have:
enum ValueSize { V8 = 0, V32 = 1 };
Splitting a halfword into two V8 accesses is not equivalent for 16-bit
peripherals. On a PC card ATA task file, offset 0 is the 16-bit Data register
while offset 1 is the Error/Feature register, so two byte reads return one data
byte and one unrelated register value. A V16 that reaches readPhysical /
writePhysical is needed; for plain RAM and ROM it can be composed from two byte
accesses.
Scope
Any EPOC code path using halfword or signed loads is affected, not just PC card
access. Because the failure is silent, it presents as unrelated misbehaviour
elsewhere.
Tested against s5mx_uk16_v260.rom (Series 5mx v1.05(260), CRC32 3b25a6a4).
Investigation and testing by @ajfa, with Claude (Anthropic) assisting.
The ARM710T in the Series 5mx is ARMv4T, but
ARM710::executeInstructionhas nocase for the ARMv4 "extra load/store" group (LDRH / STRH / LDRSB / LDRSH). Those
instructions fall through to the catch-all
and are executed as data-processing operations. There is no
Undefined32exception and no diagnostic: the instruction silently writes a garbage value to
Rd, may update the flags, and never touches memory.
Concrete example
EPOC R5's ATA media driver reads a sector through a 16-bit block-copy loop in
EpBus.dll at
0x500553d4:0xe1d020b0 & 0x0C000000 == 0, so it is dispatched toexecDataProcessing,which decodes bits 24:21 = 0xE as BIC with S=1 and Rd=2. The emulator therefore
computes
BICS r2, r0, ...instead of loading a halfword: no bus access isgenerated at all, and the condition flags are clobbered as a side effect.
Observable symptom: EPOC issues an ATA
IDENTIFY DEVICE, the device asserts DRQ,and EPOC then requests the data block — but the emulated hardware sees zero reads
of the data register, because the loop never performs a memory access.
Second, related issue
Implementing the group needs a 16-bit access size, which the memory bus does not
have:
Splitting a halfword into two
V8accesses is not equivalent for 16-bitperipherals. On a PC card ATA task file, offset 0 is the 16-bit Data register
while offset 1 is the Error/Feature register, so two byte reads return one data
byte and one unrelated register value. A
V16that reachesreadPhysical/writePhysicalis needed; for plain RAM and ROM it can be composed from two byteaccesses.
Scope
Any EPOC code path using halfword or signed loads is affected, not just PC card
access. Because the failure is silent, it presents as unrelated misbehaviour
elsewhere.
Tested against
s5mx_uk16_v260.rom(Series 5mx v1.05(260), CRC323b25a6a4).Investigation and testing by @ajfa, with Claude (Anthropic) assisting.