Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Wrong label-calculation for JUMP-Bytecode on Raspberry Pi, due to unaligned access #3201
I'm trying to port micropython bare-metal to Raspberry Pi (see repository). The folder bare-rpi contains my code and config-files for the compilation of both a Raspberry Pi kernel-Image as well as an Qemu-Image from the same code (for testing purposes).
I'm using a Raspberry Pi Model A and the codebase is from version 1.8.7.
I have tried to execute several "files" of Python-code and emitting the code works for most of them, except ones containing any sort of JUMP-Bytecode. There it seems the label gets trashed or is calculated wrongly. This behaviour is only visible on the Raspberry Pi Platform not in Qemu.
In the main.c-code is only one statement at the moment for the following python-code:
for i in range(10): print(i)
This code is compiled to the following bytecode on the Raspberry Pi:
In Qemu (using the same code!) this will be translated to:
In Qemu the code is executed correctly, on the Raspberry Pi the execution probably hits
I currently believe it is due to a wrong calculation / computation of the JUMP-Label. I have yet to try to single step both my Qemu and my RPi-Port together to see the differences.
Does someone know what might be the problem (if I did something wrong) or can someone help fix the issue?
Can you please post the actual bytecode? The best way to do this would be to enable the
Yes, no problem. This is the Bytecode generated on the Raspberry Pi:
This is the Bytecode generated on my QEMU-port:
Thanks. The relevant opcode is
@naums thanks for the disasm. The relevant asm for the JUMP opcode is:
The register r0 contains the ip pointer to the bytecode, which on entry to the JUMP label above points to the JUMP bytecode (ie the
arg = ip | (ip << 8);
is optimised to:
arg = *(uint16_t)(ip + 1);
It looks like the problem is that this load is from an unaligned pointer, because ip+1 is an odd value. And so the RPi hardware is loading from the even address
Does the RPi allow unaligned loads like this?
If the analysis above is true, and the RPi compiler is buggy, then I'm very surprised and wonder why it wasn't caught before...?
This page regarding unaligned accesses is related: http://antirez.com/news/111 . It looks like there are 2 options to fix it: 1) make GCC (or whatever your compiler is) not emit unaligned loads/stores; 2) provide a custom fault handler to fix up the accesses at runtime.
Thank you very much. I'm going to take a deeper look into the problem and possible fixes tomorrow. One question though: I should not add inline assembly for the Raspberry Pi-port, right?
You've said before that there are two places in the code which might be faulty. Can you tell me the place of the second one?
I'll report back, when I have found and tested a solution.
If you mean the
If you fix the issue with showbc.c then the VM should also be fixed.
At first I tried to solve the issue by editing the makro
This was when I basically searched for a better solution other than going through the interpreter code and aligning all the structs. I began to search in the manual for the ARM1176jzf-s processor and found that it can load unaligned data by itself (without calling the kernel for that).
So I solved the issue by setting the processor (or to be exact the system coprocessor) into a state, which allows it to load unaligned data. The manual states I have to set the U-Bit (bit 22) of the c1-control register of C15-coprocessor.
With the help of this post I managed to read and write from/to that register and set the corresponding value.
So this is the ARM-assembler-code which I added to my startup-assembler-code:
/// load C15 control register c1-c1,0,0 (c1 Control Register) into r0 mrc p15, 0, r0, c1, c0, 0 ldr r1, =0x00400000 /// set bit 22 (U-bit) orr r0, r1 mcr p15, 0, r0, c1, c0, 0
Again, thank you very much for identifying the issue.