qemu-arm
[Top][All Lists]
Advanced

[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?



reply via email to

[Prev in Thread] Current Thread [Next in Thread]