• Please review our updated Terms and Rules here

question about RPCemu and ARM instruction sets


Experienced Member
Jan 19, 2020
I have a detailed manual pertaining to an ARM7TDMI CPU, which I believe suports the "ARM4" instruction set. I don't by any means have a solid grasp of what the differences are between each generation of instruction set or each generation of hardware architecture, or which corresponds to which. But I also have an instruction chart with labels indicating which generation an instruction first appeared. So I wrote some code, which I don't think uses any instruction exclusive to ARM4 or later. It runs on a Gameboy Advance emulator, but it does not run under RISC OS inside the RPCemu. Specifically, RPCemu complains that a certain opcode is invalid. The opcode is $E1DC80B0, which should be a perfectly valid LDRH instruction.

The RPCemu readme.txt says it emulates an "ARM7500" so I looked up a datasheet for that. It says that it contains an "ARM7" core but nevertheless makes no mention of LDRH or half-words. Very confusing. Was there really an early version of ARM that could not load a 16-bit word? Or is there a different reason that RPCemu doesn't handle the opcode?
Yes, ARM7TDMI and ARM7500 are both ARMv4. That looks to me like it's just "ldrh r8, [r12, #0]" ? P=1,W=0 (offset addressing), I=1 (8-bit immediate in addr_mode field of opcode), U=1 (add offset to base). Note that the result is defined as UNPREDICTABLE if the effective address is not 16-bit aligned... a real ARM7 will swizzle the load (but it's been long enough since I had to care that I've forgotten exactly how ;)), but maybe RPCemu is generating an error instead? What's the value of r12 when this happens?
Shouldn't be a misaligned load. The address was $B078 or some such. I went looking through the RISC OS filesystem and picked out a few "ff8" files of decent size and disassembled them to see if they use a similar opcode. I found that they are mostly unrecognizable data and very little ARM code. I would guess the programs are compressed. So I learned nothing from that exercise.

There are 'Interpreter' and 'Recompiler' variants of the RPCemu. In the configuration there are also several CPU options, but I tried them all and the ones which actually boot present the same behavior. The 'Interpreter' pops up an error message (on the host, not in RISC OS) about the controversial opcode, then the emu closes. The 'Recompiler' does not stop on this opcode, instead it continues to execute but with R8 having incorrect data which eventually leads to an out-of-bounds memory access. Then an error message "Internal error: abort on data transfer" appears in RISC OS and the program closes. At this point I can only assume this version of RPCemu is buggy. There is a newer version but that one doesn't run at all. Maybe I'll fool with Nintendo DS instead.
Ok, I double-checked just to make sure I wasn't making some dumb mistake:

dhcp-194:thorpej$ cat oink.s         
    .globl    _start
    ldrh    r8, [r12, #0]
    .word    0xE1DC80B0
dhcp-194:thorpej$ armv4--netbsdelf-eabi-as oink.s
dhcp-194:thorpej$ armv4--netbsdelf-eabi-ld -o oink a.out
dhcp-194:thorpej$ armv4--netbsdelf-eabi-objdump --disassemble oink   

oink:     file format elf32-littlearm

Disassembly of section .text:

00010054 <_start>:
   10054:    e1dc80b0     ldrh    r8, [ip]
   10058:    e1dc80b0     .word    0xe1dc80b0
dhcp-194:thorpej$ armv4--netbsdelf-eabi-objcopy -O binary oink oink.bin
dhcp-194:thorpej$ hexdump -C oink.bin
00000000  b0 80 dc e1 b0 80 dc e1                           |........|

So, yah, I don't know why objdump insists on disassembling it as a ".word" directive when, as far as my eyes can see, the bytes of the instruction are identical in both forms.