[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Undocumented behavior with CPSR_c mode
From: |
Kirill Zhumarin |
Subject: |
Undocumented behavior with CPSR_c mode |
Date: |
Tue, 27 Feb 2024 11:35:02 +0300 |
Hi all. I found a bug. But I don't know if there is a problem with
QEMU or real hardware.
My environment:
Real hardware: Infineon PMB8876 + Infineon PMB8875 (ARM926EJ-S core)
QEMU: from master, arm926ej-s
I found that the M4 bit in CPSR_c is optional when setting CPU mode.
On real hardware, modes 00010 and 10010 are actually equal.
My test code is like this:
```
#include <pmb887x.h>
#include <printf.h>
static inline uint32_t get_cpsr() {
uint32_t r;
__asm__ volatile("msr cpsr_c, #0x2");
__asm__ volatile("MRS %0, cpsr" : "=r" (r) : );
__asm__ volatile("msr cpsr_c, #0x13");
return r;
}
int main(void) {
uint32_t mode = get_cpsr();
printf("CPSR: %08X\n", mode);
printf("MODE: %d%d%d%d%d\n", (mode >> 4) & 1, (mode >> 3) & 1, (mode
>> 2) & 1, (mode >> 1) & 1, (mode) & 1);
while (1);
return 0;
}
```
And I get different results on qemu and real CPU:
--------------------------------
qemu
CPSR: 60000113
MODE: 10011
--------------------------------
pmb8876 or pmb8875
CPSR: 60000012
MODE: 10010
--------------------------------
QEMU just ignores setting invalid mode.
Of course, I understand, this is an invalid code - according to the
ARM documentation, "00010" mode does not exist.
But this is not a synthetic code. I found it in an existing bootloader
for pmb8876, and it works on a real device.
That code looks like this:
```
msr cpsr_c,#0xc2 ; go to the IRQ mode
ldr sp,[DAT_00082e28] ; set IRQ mode stack
...
msr cpsr_c,#0xc3 ; back to the Supervisor mode
ldr sp,[DAT_00082e2c] ; set Supervisor mode stack
```
Unfortunately, I do not have other ARM926EJ-S processors to test the
behavior on them.
Should QEMU repeat this undocumented behavior?
- Undocumented behavior with CPSR_c mode,
Kirill Zhumarin <=