Jump to content
Visual Boy Advance-M
abhoriel

core bug in RSBS and RSCS instructions

Recommended Posts

I'm writing a GBA emulator for fun, and was testing my own core against VBA-M's

 

I found a bug in the ARM mode RSBS and RSCS instructions, in that they set the flags wrongly. They are set wrongly according to the ARM architecture documentation, and I have tested VBA-M against real hardware (a nintendoDS in GBA mode), and have found the flags to be set differently.

 

I'm using VBA-M 1.8.0.1138, compiled from the source available from the download page.

 

for example:

 

mov r0, #0x80000000
mov r1, #0x00000001
rsb r0, r0, r1

 

on real hardware, the result is 0x80000001 and flags should be 0x90000001f (N..V..)

in VBA-M, the result is 0x80000001 and flags are 0x8000001f (N.C...)

 

the issue can be fixed with the following patch for VBA-M's C core:

--- GBA-arm.cpp.old	2013-02-01 13:34:42.591850606 +0000
+++ GBA-arm.cpp	2013-02-01 14:01:38.395172242 +0000
@@ -951,9 +951,9 @@
#endif
#ifndef OP_RSB
 #define OP_RSB \
-    u32 lhs = reg[(opcode>>16)&15].I;                   \
-    u32 rhs = value;                                    \
-    u32 res = rhs - lhs;                                \
+    u32 lhs = value;                                    \
+    u32 rhs = reg[(opcode>>16)&15].I;                   \
+    u32 res = lhs - rhs;                                \
    reg[dest].I = res;
#endif
#ifndef OP_RSBS
@@ -991,9 +991,9 @@
#endif
#ifndef OP_RSC
 #define OP_RSC \
-    u32 lhs = reg[(opcode>>16)&15].I;                   \
-    u32 rhs = value;                                    \
-    u32 res = rhs - lhs - !((u32)C_FLAG);               \
+    u32 lhs = value;                                    \
+    u32 rhs = reg[(opcode>>16)&15].I;                   \
+    u32 res = lhs - rhs - !((u32)C_FLAG);               \
    reg[dest].I = res;
#endif
#ifndef OP_RSCS

 

I have not tested the asm core, and haven't even bothered to read the source. When enabled, it will not compile on my machine, but it is possible that the bug is present there too.

 

If anyone wants to test the issue themselves, here is the code I used. I will attach a pre-compiled ROM for testing too. [.gba files cannot be uploaded, perhaps for good reason - you will have to compile this yourself if you want to test it]

 

main.c

#include 
#include 
#include 
#include 

#define GET_BIT(x, b) ((x) & (1 << (b)))

u32 testFunc(u32 a, u32 b);

int main() {
   u32 flags;

irqInit();
irqEnable(IRQ_VBLANK);
consoleInit(0, 4, 0, NULL, 0, 15);

BG_COLORS[0] = RGB5(0, 0, 0);
BG_COLORS[241] = RGB5(31, 31, 31);
REG_DISPCNT = MODE_0 | BG0_ON;

   u32 v1 = 0x80000000;
   u32 v2 = 0x00000001;

   printf("test: rsbs %08x, %08x\n", v1, v2);

   flags = testFunc(v1, v2);

   printf("flags: %08x (", flags);

   printf("%c", GET_BIT(flags, 31) ? 'N' : '.');
   printf("%c", GET_BIT(flags, 30) ? 'Z' : '.');
   printf("%c", GET_BIT(flags, 29) ? 'C' : '.');
   printf("%c", GET_BIT(flags, 28) ? 'V' : '.');
   printf("%c", GET_BIT(flags, 27) ? 'Q' : '.');
   printf("%c", GET_BIT(flags, 5) ? 'T' : '.');
   printf(")\n");
   return 0;
}

 

asm.s

.arch armv4t

.section .iwram, "ax", %progbits @ use fast 32k RAM for ARM code
.align 2

.global testFunc
testFunc:
   rsbs r0, r0, r1
   mrs r0, cpsr
   bx lr

 

regards,

Share this post


Link to post
Share on other sites

instruction bug is critical as it could leads to other bugs, i hope someone could fix it, including the asm one :)

 

the last time i found a flag bug it was causing flickering in vrally3 but i forgot which instruction :msn_embarrassed: i wonder if it's the same instruction, i only remember the fix was for asm

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×