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>
|
// B <offset>
|
||||||
static INSN_REGPARM void armA00(uint32_t opcode)
|
static INSN_REGPARM void armA00(uint32_t opcode)
|
||||||
{
|
{
|
||||||
int offset = opcode & 0x00FFFFFF;
|
int32_t offset = ((int32_t)(opcode & 0x00FFFFFF) << 8) >> 6;
|
||||||
if (offset & 0x00800000)
|
reg[15].I += offset;
|
||||||
offset |= 0xFF000000; // negative offset
|
|
||||||
reg[15].I += offset << 2;
|
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 4;
|
reg[15].I += 4;
|
||||||
ARM_PREFETCH;
|
ARM_PREFETCH;
|
||||||
|
@ -2590,11 +2588,9 @@ static INSN_REGPARM void armA00(uint32_t opcode)
|
||||||
// BL <offset>
|
// BL <offset>
|
||||||
static INSN_REGPARM void armB00(uint32_t opcode)
|
static INSN_REGPARM void armB00(uint32_t opcode)
|
||||||
{
|
{
|
||||||
int offset = opcode & 0x00FFFFFF;
|
int32_t offset = ((int32_t)(opcode & 0x00FFFFFF) << 8) >> 6;
|
||||||
if (offset & 0x00800000)
|
|
||||||
offset |= 0xFF000000; // negative offset
|
|
||||||
reg[14].I = reg[15].I - 4;
|
reg[14].I = reg[15].I - 4;
|
||||||
reg[15].I += offset << 2;
|
reg[15].I += offset;
|
||||||
armNextPC = reg[15].I;
|
armNextPC = reg[15].I;
|
||||||
reg[15].I += 4;
|
reg[15].I += 4;
|
||||||
ARM_PREFETCH;
|
ARM_PREFETCH;
|
||||||
|
|
|
@ -1700,215 +1700,102 @@ static INSN_REGPARM void thumbC8(uint32_t opcode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conditional branches ///////////////////////////////////////////////////
|
// 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
|
// BEQ offset
|
||||||
static INSN_REGPARM void thumbD0(uint32_t opcode)
|
static INSN_REGPARM void thumbD0(uint32_t opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
THUMB_CONDITIONAL_BRANCH(Z_FLAG);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BNE offset
|
// BNE offset
|
||||||
static INSN_REGPARM void thumbD1(uint32_t opcode)
|
static INSN_REGPARM void thumbD1(uint32_t opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
THUMB_CONDITIONAL_BRANCH(!Z_FLAG);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BCS offset
|
// BCS offset
|
||||||
static INSN_REGPARM void thumbD2(uint32_t opcode)
|
static INSN_REGPARM void thumbD2(uint32_t opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
THUMB_CONDITIONAL_BRANCH(C_FLAG);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BCC offset
|
// BCC offset
|
||||||
static INSN_REGPARM void thumbD3(uint32_t opcode)
|
static INSN_REGPARM void thumbD3(uint32_t opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
THUMB_CONDITIONAL_BRANCH(!C_FLAG);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BMI offset
|
// BMI offset
|
||||||
static INSN_REGPARM void thumbD4(uint32_t opcode)
|
static INSN_REGPARM void thumbD4(uint32_t opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
THUMB_CONDITIONAL_BRANCH(N_FLAG);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BPL offset
|
// BPL offset
|
||||||
static INSN_REGPARM void thumbD5(uint32_t opcode)
|
static INSN_REGPARM void thumbD5(uint32_t opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
THUMB_CONDITIONAL_BRANCH(!N_FLAG);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BVS offset
|
// BVS offset
|
||||||
static INSN_REGPARM void thumbD6(uint32_t opcode)
|
static INSN_REGPARM void thumbD6(uint32_t opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
THUMB_CONDITIONAL_BRANCH(V_FLAG);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BVC offset
|
// BVC offset
|
||||||
static INSN_REGPARM void thumbD7(uint32_t opcode)
|
static INSN_REGPARM void thumbD7(uint32_t opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
THUMB_CONDITIONAL_BRANCH(!V_FLAG);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BHI offset
|
// BHI offset
|
||||||
static INSN_REGPARM void thumbD8(uint32_t opcode)
|
static INSN_REGPARM void thumbD8(uint32_t opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
THUMB_CONDITIONAL_BRANCH(C_FLAG && !Z_FLAG);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BLS offset
|
// BLS offset
|
||||||
static INSN_REGPARM void thumbD9(uint32_t opcode)
|
static INSN_REGPARM void thumbD9(uint32_t opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
THUMB_CONDITIONAL_BRANCH(!C_FLAG || Z_FLAG);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BGE offset
|
// BGE offset
|
||||||
static INSN_REGPARM void thumbDA(uint32_t opcode)
|
static INSN_REGPARM void thumbDA(uint32_t opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
THUMB_CONDITIONAL_BRANCH(N_FLAG == V_FLAG);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BLT offset
|
// BLT offset
|
||||||
static INSN_REGPARM void thumbDB(uint32_t opcode)
|
static INSN_REGPARM void thumbDB(uint32_t opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
THUMB_CONDITIONAL_BRANCH(N_FLAG != V_FLAG);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BGT offset
|
// BGT offset
|
||||||
static INSN_REGPARM void thumbDC(uint32_t opcode)
|
static INSN_REGPARM void thumbDC(uint32_t opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
THUMB_CONDITIONAL_BRANCH(!Z_FLAG && (N_FLAG == V_FLAG));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BLE offset
|
// BLE offset
|
||||||
static INSN_REGPARM void thumbDD(uint32_t opcode)
|
static INSN_REGPARM void thumbDD(uint32_t opcode)
|
||||||
{
|
{
|
||||||
UPDATE_OLDREG;
|
THUMB_CONDITIONAL_BRANCH(Z_FLAG || (N_FLAG != V_FLAG));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SWI, B, BL /////////////////////////////////////////////////////////////
|
// SWI, B, BL /////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Reference in New Issue