GBA: Resolve shifting negative value issue in some thumb/arm opcodes
This commit is contained in:
parent
59f76d05b8
commit
093818a1d7
|
@ -2575,10 +2575,8 @@ static INSN_REGPARM void arm9F0(uint32_t opcode)
|
|||
// B <offset>
|
||||
static INSN_REGPARM void armA00(uint32_t opcode)
|
||||
{
|
||||
int offset = opcode & 0x00FFFFFF;
|
||||
if (offset & 0x00800000)
|
||||
offset |= 0xFF000000; // negative offset
|
||||
reg[15].I += offset << 2;
|
||||
int32_t offset = ((int32_t)(opcode & 0x00FFFFFF) << 8) >> 6;
|
||||
reg[15].I += offset;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 4;
|
||||
ARM_PREFETCH;
|
||||
|
@ -2590,11 +2588,9 @@ static INSN_REGPARM void armA00(uint32_t opcode)
|
|||
// BL <offset>
|
||||
static INSN_REGPARM void armB00(uint32_t opcode)
|
||||
{
|
||||
int offset = opcode & 0x00FFFFFF;
|
||||
if (offset & 0x00800000)
|
||||
offset |= 0xFF000000; // negative offset
|
||||
int32_t offset = ((int32_t)(opcode & 0x00FFFFFF) << 8) >> 6;
|
||||
reg[14].I = reg[15].I - 4;
|
||||
reg[15].I += offset << 2;
|
||||
reg[15].I += offset;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 4;
|
||||
ARM_PREFETCH;
|
||||
|
|
|
@ -1700,215 +1700,102 @@ static INSN_REGPARM void thumbC8(uint32_t opcode)
|
|||
}
|
||||
|
||||
// Conditional branches ///////////////////////////////////////////////////
|
||||
#define THUMB_CONDITIONAL_BRANCH(COND) \
|
||||
UPDATE_OLDREG; \
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1; \
|
||||
if (COND) { \
|
||||
uint32_t offset = (uint32_t)((int8_t)(opcode & 0xFF)) << 1; \
|
||||
reg[15].I += offset; \
|
||||
armNextPC = reg[15].I; \
|
||||
reg[15].I += 2; \
|
||||
THUMB_PREFETCH; \
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) \
|
||||
+ codeTicksAccess16(armNextPC) + 2; \
|
||||
busPrefetchCount = 0; \
|
||||
}
|
||||
|
||||
// BEQ offset
|
||||
static INSN_REGPARM void thumbD0(uint32_t opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if (Z_FLAG) {
|
||||
reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
THUMB_CONDITIONAL_BRANCH(Z_FLAG);
|
||||
}
|
||||
|
||||
// BNE offset
|
||||
static INSN_REGPARM void thumbD1(uint32_t opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if (!Z_FLAG) {
|
||||
reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
THUMB_CONDITIONAL_BRANCH(!Z_FLAG);
|
||||
}
|
||||
|
||||
// BCS offset
|
||||
static INSN_REGPARM void thumbD2(uint32_t opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if (C_FLAG) {
|
||||
reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
THUMB_CONDITIONAL_BRANCH(C_FLAG);
|
||||
}
|
||||
|
||||
// BCC offset
|
||||
static INSN_REGPARM void thumbD3(uint32_t opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if (!C_FLAG) {
|
||||
reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
THUMB_CONDITIONAL_BRANCH(!C_FLAG);
|
||||
}
|
||||
|
||||
// BMI offset
|
||||
static INSN_REGPARM void thumbD4(uint32_t opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if (N_FLAG) {
|
||||
reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
THUMB_CONDITIONAL_BRANCH(N_FLAG);
|
||||
}
|
||||
|
||||
// BPL offset
|
||||
static INSN_REGPARM void thumbD5(uint32_t opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if (!N_FLAG) {
|
||||
reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
THUMB_CONDITIONAL_BRANCH(!N_FLAG);
|
||||
}
|
||||
|
||||
// BVS offset
|
||||
static INSN_REGPARM void thumbD6(uint32_t opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if (V_FLAG) {
|
||||
reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
THUMB_CONDITIONAL_BRANCH(V_FLAG);
|
||||
}
|
||||
|
||||
// BVC offset
|
||||
static INSN_REGPARM void thumbD7(uint32_t opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if (!V_FLAG) {
|
||||
reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
THUMB_CONDITIONAL_BRANCH(!V_FLAG);
|
||||
}
|
||||
|
||||
// BHI offset
|
||||
static INSN_REGPARM void thumbD8(uint32_t opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if (C_FLAG && !Z_FLAG) {
|
||||
reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
THUMB_CONDITIONAL_BRANCH(C_FLAG && !Z_FLAG);
|
||||
}
|
||||
|
||||
// BLS offset
|
||||
static INSN_REGPARM void thumbD9(uint32_t opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if (!C_FLAG || Z_FLAG) {
|
||||
reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
THUMB_CONDITIONAL_BRANCH(!C_FLAG || Z_FLAG);
|
||||
}
|
||||
|
||||
// BGE offset
|
||||
static INSN_REGPARM void thumbDA(uint32_t opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if (N_FLAG == V_FLAG) {
|
||||
reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
THUMB_CONDITIONAL_BRANCH(N_FLAG == V_FLAG);
|
||||
}
|
||||
|
||||
// BLT offset
|
||||
static INSN_REGPARM void thumbDB(uint32_t opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if (N_FLAG != V_FLAG) {
|
||||
reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
THUMB_CONDITIONAL_BRANCH(N_FLAG != V_FLAG);
|
||||
}
|
||||
|
||||
// BGT offset
|
||||
static INSN_REGPARM void thumbDC(uint32_t opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if (!Z_FLAG && (N_FLAG == V_FLAG)) {
|
||||
reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
THUMB_CONDITIONAL_BRANCH(!Z_FLAG && (N_FLAG == V_FLAG));
|
||||
}
|
||||
|
||||
// BLE offset
|
||||
static INSN_REGPARM void thumbDD(uint32_t opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC);
|
||||
if (Z_FLAG || (N_FLAG != V_FLAG)) {
|
||||
reg[15].I += ((int8_t)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
THUMB_CONDITIONAL_BRANCH(Z_FLAG || (N_FLAG != V_FLAG));
|
||||
}
|
||||
|
||||
// SWI, B, BL /////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue