jit bcctrx and misc code cleanup. NES games launched from animal crossing work, but have major video problems...

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4504 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Shawn Hoffman 2009-11-07 17:56:01 +00:00
parent 5579a9169d
commit 42cd2838a3
6 changed files with 89 additions and 97 deletions

View File

@ -251,9 +251,7 @@ union bba_descr {
u32 word; u32 word;
}; };
bool CEXIETHERNET::cbwriteDescriptor(u32 size) { bool CEXIETHERNET::cbwriteDescriptor(u32 size) {
//if(size < 0x3C) {//60 if(size < SIZEOF_ETH_HEADER)
#define ETHERNET_HEADER_SIZE 0xE
if(size < ETHERNET_HEADER_SIZE)
{ {
DEBUGPRINT("Packet too small: %i bytes\n", size); DEBUGPRINT("Packet too small: %i bytes\n", size);
return false; return false;

View File

@ -15,7 +15,6 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <assert.h>
#include "StringUtil.h" #include "StringUtil.h"
#include "../Memmap.h" #include "../Memmap.h"
// GROSS CODE ALERT: headers need to be included in the following order // GROSS CODE ALERT: headers need to be included in the following order
@ -226,8 +225,7 @@ bool CEXIETHERNET::activate()
if ( !(info[0] > TAP_WIN32_MIN_MAJOR if ( !(info[0] > TAP_WIN32_MIN_MAJOR
|| (info[0] == TAP_WIN32_MIN_MAJOR && info[1] >= TAP_WIN32_MIN_MINOR)) ) || (info[0] == TAP_WIN32_MIN_MAJOR && info[1] >= TAP_WIN32_MIN_MINOR)) )
{ {
#define PACKAGE_NAME "Dolphin" DEBUGPRINT("ERROR: This version of Dolphin requires a TAP-Win32 driver that is at least version %d.%d -- If you recently upgraded your Dolphin distribution, a reboot is probably required at this point to get Windows to see the new driver.",
DEBUGPRINT("ERROR: This version of " PACKAGE_NAME " requires a TAP-Win32 driver that is at least version %d.%d -- If you recently upgraded your " PACKAGE_NAME " distribution, a reboot is probably required at this point to get Windows to see the new driver.",
TAP_WIN32_MIN_MAJOR, TAP_WIN32_MIN_MAJOR,
TAP_WIN32_MIN_MINOR); TAP_WIN32_MIN_MINOR);
return false; return false;
@ -279,7 +277,7 @@ bool CEXIETHERNET::CheckRecieved()
return false; return false;
} }
bool CEXIETHERNET::sendPacket(u8 *etherpckt, int size) bool CEXIETHERNET::sendPacket(u8 *etherpckt, int size)
{ {
if (!isActivated()) if (!isActivated())
activate(); activate();
@ -297,7 +295,7 @@ bool CEXIETHERNET::sendPacket(u8 *etherpckt, int size)
DWORD res = GetLastError(); DWORD res = GetLastError();
DEBUGPRINT("Failed to send packet with error 0x%X", res); DEBUGPRINT("Failed to send packet with error 0x%X", res);
} }
if (numBytesWrit != size) if (numBytesWrit != size)
{ {
DEBUGPRINT("BBA sendPacket %i only got %i bytes sent!", size, numBytesWrit); DEBUGPRINT("BBA sendPacket %i only got %i bytes sent!", size, numBytesWrit);
return false; return false;
@ -307,7 +305,7 @@ bool CEXIETHERNET::sendPacket(u8 *etherpckt, int size)
return true; return true;
} }
bool CEXIETHERNET::handleRecvdPacket() bool CEXIETHERNET::handleRecvdPacket()
{ {
int rbwpp = (int)(mCbw.p_write() + CB_OFFSET); // read buffer write page pointer int rbwpp = (int)(mCbw.p_write() + CB_OFFSET); // read buffer write page pointer
u32 available_bytes_in_cb; u32 available_bytes_in_cb;
@ -322,7 +320,7 @@ bool CEXIETHERNET::handleRecvdPacket()
//DUMPWORD(mRBRPP); //DUMPWORD(mRBRPP);
//DUMPWORD(available_bytes_in_cb); //DUMPWORD(available_bytes_in_cb);
assert(available_bytes_in_cb <= CB_SIZE); _dbg_assert_(SP1, available_bytes_in_cb <= CB_SIZE);
if (available_bytes_in_cb != CB_SIZE)//< mRecvBufferLength + SIZEOF_RECV_DESCRIPTOR) if (available_bytes_in_cb != CB_SIZE)//< mRecvBufferLength + SIZEOF_RECV_DESCRIPTOR)
return true; return true;
cbwriteDescriptor(mRecvBufferLength); cbwriteDescriptor(mRecvBufferLength);
@ -440,9 +438,7 @@ union bba_descr
bool CEXIETHERNET::cbwriteDescriptor(u32 size) bool CEXIETHERNET::cbwriteDescriptor(u32 size)
{ {
//if(size < 0x3C) {//60 if (size < SIZEOF_ETH_HEADER)
#define ETHERNET_HEADER_SIZE 0xE
if (size < ETHERNET_HEADER_SIZE)
{ {
DEBUGPRINT("Packet too small: %i bytes", size); DEBUGPRINT("Packet too small: %i bytes", size);
return false; return false;
@ -453,7 +449,7 @@ bool CEXIETHERNET::cbwriteDescriptor(u32 size)
//We should probably not implement wraparound here, //We should probably not implement wraparound here,
//since neither tmbinc, riptool.dol, or libogc does... //since neither tmbinc, riptool.dol, or libogc does...
if (mCbw.p_write() + SIZEOF_RECV_DESCRIPTOR >= CB_SIZE) if (mCbw.p_write() + SIZEOF_RECV_DESCRIPTOR >= CB_SIZE)
{ {
DEBUGPRINT("The descriptor won't fit"); DEBUGPRINT("The descriptor won't fit");
return false; return false;
@ -469,11 +465,11 @@ bool CEXIETHERNET::cbwriteDescriptor(u32 size)
descr.packet_len = size; descr.packet_len = size;
descr.status = 0; descr.status = 0;
u32 npp; u32 npp;
if (mCbw.p_write() + size < CB_SIZE) if (mCbw.p_write() + size < CB_SIZE)
{ {
npp = (u32)(mCbw.p_write() + size + CB_OFFSET); npp = (u32)(mCbw.p_write() + size + CB_OFFSET);
} }
else else
{ {
npp = (u32)(mCbw.p_write() + size + CB_OFFSET - CB_SIZE); npp = (u32)(mCbw.p_write() + size + CB_OFFSET - CB_SIZE);
} }
@ -493,4 +489,4 @@ bool CEXIETHERNET::cbwriteDescriptor(u32 size)
mCbw.write(&descr.word, SIZEOF_RECV_DESCRIPTOR); mCbw.write(&descr.word, SIZEOF_RECV_DESCRIPTOR);
return true; return true;
} }

View File

@ -116,12 +116,13 @@ private:
// TODO: convert into unions // TODO: convert into unions
enum enum
{ {
BBA_RECV_SIZE = 0x800, BBA_RECV_SIZE = 0x800,
BBA_MEM_SIZE = 0x1000, BBA_MEM_SIZE = 0x1000,
CB_OFFSET = 0x100, CB_OFFSET = 0x100,
CB_SIZE = (BBA_MEM_SIZE - CB_OFFSET), CB_SIZE = (BBA_MEM_SIZE - CB_OFFSET),
SIZEOF_RECV_DESCRIPTOR = 4, SIZEOF_ETH_HEADER = 0xe,
SIZEOF_RECV_DESCRIPTOR = 4,
EXI_DEVTYPE_ETHER = 0x04020200, EXI_DEVTYPE_ETHER = 0x04020200,

View File

@ -589,7 +589,10 @@ enum EQuantizeType
// branches // branches
enum enum
{ {
BO_DONT_DECREMENT_FLAG = 0x4, BO_BRANCH_IF_CTR_0 = 2, // 3
BO_DONT_DECREMENT_FLAG = 4, // 2
BO_BRANCH_IF_TRUE = 8, // 1
BO_DONT_CHECK_CONDITION = 16, // 0
}; };
// Special purpose register indices // Special purpose register indices

View File

@ -63,39 +63,38 @@ void bcx(UGeckoInstruction _inst)
NPC = SignExt16(_inst.BD << 2); NPC = SignExt16(_inst.BD << 2);
else else
NPC = PC + SignExt16(_inst.BD << 2); NPC = PC + SignExt16(_inst.BD << 2);
} }
m_EndBlock = true; m_EndBlock = true;
} }
void bcctrx(UGeckoInstruction _inst) void bcctrx(UGeckoInstruction _inst)
{ {
if ((_inst.BO & BO_DONT_DECREMENT_FLAG) == 0) _dbg_assert_msg_(POWERPC, _inst.BO_2 & BO_DONT_DECREMENT_FLAG, "bcctrx with decrement and test CTR option is invalid!");
CTR--;
int condition = ((_inst.BO>>4) | (GetCRBit(_inst.BI) == ((_inst.BO>>3) & 1))) & 1; int condition = ((_inst.BO_2>>4) | (GetCRBit(_inst.BI_2) == ((_inst.BO_2>>3) & 1))) & 1;
if (condition) if (condition)
{ {
if (_inst.LK)
LR = PC + 4;
NPC = CTR & (~3); NPC = CTR & (~3);
if (_inst.LK_3)
LR = PC + 4;
} }
m_EndBlock = true; m_EndBlock = true;
} }
void bclrx(UGeckoInstruction _inst) void bclrx(UGeckoInstruction _inst)
{ {
if ((_inst.BO & BO_DONT_DECREMENT_FLAG) == 0) if ((_inst.BO_2 & BO_DONT_DECREMENT_FLAG) == 0)
CTR--; CTR--;
int counter = ((_inst.BO >> 2) | ((CTR != 0) ^ (_inst.BO >> 1)))&1; int counter = ((_inst.BO_2 >> 2) | ((CTR != 0) ^ (_inst.BO_2 >> 1))) & 1;
int condition = ((_inst.BO >> 4) | (GetCRBit(_inst.BI) == ((_inst.BO >> 3) & 1))) & 1; int condition = ((_inst.BO_2 >> 4) | (GetCRBit(_inst.BI_2) == ((_inst.BO_2 >> 3) & 1))) & 1;
if (counter & condition) if (counter & condition)
{ {
NPC = LR & (~3); NPC = LR & (~3);
if (_inst.LK) if (_inst.LK_3)
LR = PC+4; LR = PC + 4;
} }
m_EndBlock = true; m_EndBlock = true;
} }

View File

@ -42,10 +42,8 @@ using namespace Gen;
void Jit64::sc(UGeckoInstruction inst) void Jit64::sc(UGeckoInstruction inst)
{ {
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITBranchOff) INSTRUCTION_START
{Default(inst); return;} // turn off from debugger JITDISABLE(Branch)
INSTRUCTION_START;
gpr.Flush(FLUSH_ALL); gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL);
@ -54,10 +52,8 @@ void Jit64::sc(UGeckoInstruction inst)
void Jit64::rfi(UGeckoInstruction inst) void Jit64::rfi(UGeckoInstruction inst)
{ {
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITBranchOff) INSTRUCTION_START
{Default(inst); return;} // turn off from debugger JITDISABLE(Branch)
INSTRUCTION_START;
gpr.Flush(FLUSH_ALL); gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL);
@ -79,10 +75,8 @@ void Jit64::rfi(UGeckoInstruction inst)
void Jit64::bx(UGeckoInstruction inst) void Jit64::bx(UGeckoInstruction inst)
{ {
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITBranchOff) INSTRUCTION_START
{Default(inst); return;} // turn off from debugger JITDISABLE(Branch)
INSTRUCTION_START;
if (inst.LK) if (inst.LK)
MOV(32, M(&LR), Imm32(js.compilerPC + 4)); MOV(32, M(&LR), Imm32(js.compilerPC + 4));
@ -121,10 +115,8 @@ void Jit64::bx(UGeckoInstruction inst)
// variants of this instruction. // variants of this instruction.
void Jit64::bcx(UGeckoInstruction inst) void Jit64::bcx(UGeckoInstruction inst)
{ {
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITBranchOff) INSTRUCTION_START
{Default(inst); return;} // turn off from debugger JITDISABLE(Branch)
INSTRUCTION_START;
// USES_CR // USES_CR
_assert_msg_(DYNA_REC, js.isLastInstruction, "bcx not last instruction of block"); _assert_msg_(DYNA_REC, js.isLastInstruction, "bcx not last instruction of block");
@ -138,13 +130,13 @@ void Jit64::bcx(UGeckoInstruction inst)
//const bool only_condition_check = (inst.BO & 4) ? true : false; //const bool only_condition_check = (inst.BO & 4) ? true : false;
//if (only_condition_check && only_counter_check) //if (only_condition_check && only_counter_check)
// PanicAlert("Bizarre bcx encountered. Likely bad or corrupt code."); // PanicAlert("Bizarre bcx encountered. Likely bad or corrupt code.");
bool doFullTest = (inst.BO & 16) == 0 && (inst.BO & 4) == 0; bool doFullTest = ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) && ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0);
bool ctrDecremented = false; bool ctrDecremented = false;
if ((inst.BO & 16) == 0) // Test a CR bit if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) // Test a CR bit
{ {
TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3))); TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3)));
if (inst.BO & 8) // Conditional branch if (inst.BO & BO_BRANCH_IF_TRUE) // Conditional branch
branch = CC_NZ; branch = CC_NZ;
else else
branch = CC_Z; branch = CC_Z;
@ -158,13 +150,13 @@ void Jit64::bcx(UGeckoInstruction inst)
MOV(32, R(EAX), Imm32(1)); MOV(32, R(EAX), Imm32(1));
} }
if ((inst.BO & 4) == 0) // Decrement and test CTR if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR
{ {
// Decrement CTR // Decrement CTR
SUB(32, M(&CTR), Imm8(1)); SUB(32, M(&CTR), Imm8(1));
ctrDecremented = true; ctrDecremented = true;
// Test whether to branch if CTR is zero or not // Test whether to branch if CTR is zero or not
if (inst.BO & 2) if (inst.BO & BO_BRANCH_IF_CTR_0)
branch = CC_Z; branch = CC_Z;
else else
branch = CC_NZ; branch = CC_NZ;
@ -217,56 +209,58 @@ void Jit64::bcx(UGeckoInstruction inst)
void Jit64::bcctrx(UGeckoInstruction inst) void Jit64::bcctrx(UGeckoInstruction inst)
{ {
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITBranchOff) INSTRUCTION_START
{Default(inst); return;} // turn off from debugger JITDISABLE(Branch)
INSTRUCTION_START;
gpr.Flush(FLUSH_ALL); gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL);
// bool fastway = true; // bcctrx doesn't decrement and/or test CTR
_dbg_assert_msg_(POWERPC, inst.BO_2 & BO_DONT_DECREMENT_FLAG, "bcctrx with decrement and test CTR option is invalid!");
if ((inst.BO & 16) == 0) if (inst.BO_2 & BO_DONT_CHECK_CONDITION)
{ {
// Rare condition usually used by NES Emulators // BO_2 == 1z1zz -> b always
// TODO: JIT does not support this
ERROR_LOG(DYNA_REC, "Bizarro bcctrx %08x, not supported.", inst.hex);
//_assert_msg_(DYNA_REC, 0, "Bizarro bcctrx");
/*
fastway = false;
MOV(32, M(&PC), Imm32(js.compilerPC+4));
MOV(32, R(EAX), M(&CR));
XOR(32, R(ECX), R(ECX));
AND(32, R(EAX), Imm32(0x80000000 >> inst.BI));
CCFlags branch; //NPC = CTR & 0xfffffffc;
if(inst.BO & 8) MOV(32, R(EAX), M(&CTR));
branch = CC_NZ; if (inst.LK_3)
else MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4;
branch = CC_Z; AND(32, R(EAX), Imm32(0xFFFFFFFC));
*/ WriteExitDestInEAX(0);
// TODO(ector): Why is this commented out? }
//SETcc(branch, R(ECX)); else
// check for EBX {
//TEST(32, R(ECX), R(ECX)); // Rare condition seen in (just some versions of?) Nintendo's NES Emulator
//linkEnd = J_CC(branch);
// BO_2 == 001zy -> b if false
// BO_2 == 011zy -> b if true
// Ripped from bclrx
TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3)));
Gen::CCFlags branch;
if (inst.BO_2 & BO_BRANCH_IF_TRUE)
branch = CC_Z;
else
branch = CC_NZ;
MOV(32, R(EAX), Imm32(js.compilerPC + 4));
FixupBranch b = J_CC(branch, false);
MOV(32, R(EAX), M(&CTR));
MOV(32, M(&PC), R(EAX));
if (inst.LK_3)
MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4;
// Would really like to continue the block here, but it ends. TODO.
SetJumpTarget(b);
WriteExitDestInEAX(0);
return;
} }
// NPC = CTR & 0xfffffffc;
MOV(32, R(EAX), M(&CTR));
if (inst.LK)
MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4;
AND(32, R(EAX), Imm32(0xFFFFFFFC));
WriteExitDestInEAX(0);
} }
void Jit64::bclrx(UGeckoInstruction inst) void Jit64::bclrx(UGeckoInstruction inst)
{ {
if (Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITBranchOff) INSTRUCTION_START
{Default(inst); return;} // turn off from debugger JITDISABLE(Branch)
INSTRUCTION_START;
gpr.Flush(FLUSH_ALL); gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL);
@ -281,13 +275,14 @@ void Jit64::bclrx(UGeckoInstruction inst)
#endif #endif
MOV(32, R(EAX), M(&LR)); MOV(32, R(EAX), M(&LR));
MOV(32, M(&PC), R(EAX)); MOV(32, M(&PC), R(EAX));
if (inst.LK) if (inst.LK_3)
MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4; MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4;
WriteExitDestInEAX(0); WriteExitDestInEAX(0);
return; return;
} else if ((inst.BO & 4) == 0) { } else if ((inst.BO_2 & BO_DONT_DECREMENT_FLAG) == 0) {
// Decrement CTR?? in bclrx?? this goes to fallback. // Decrement CTR. Not mutually exclusive...
} else if ((inst.BO & 16) == 0) { // Will fall back to int, but we should be able to do it here, sometime
} else if ((inst.BO_2 & BO_DONT_CHECK_CONDITION) == 0) {
// Test a CR bit. Not too hard. // Test a CR bit. Not too hard.
// beqlr- 4d820020 // beqlr- 4d820020
// blelr- 4c810020 // blelr- 4c810020
@ -296,7 +291,7 @@ void Jit64::bclrx(UGeckoInstruction inst)
// etc... // etc...
TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3))); TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3)));
Gen::CCFlags branch; Gen::CCFlags branch;
if (inst.BO & 8) if (inst.BO_2 & BO_BRANCH_IF_TRUE)
branch = CC_Z; branch = CC_Z;
else else
branch = CC_NZ; branch = CC_NZ;
@ -304,7 +299,7 @@ void Jit64::bclrx(UGeckoInstruction inst)
FixupBranch b = J_CC(branch, false); FixupBranch b = J_CC(branch, false);
MOV(32, R(EAX), M(&LR)); MOV(32, R(EAX), M(&LR));
MOV(32, M(&PC), R(EAX)); MOV(32, M(&PC), R(EAX));
if (inst.LK) if (inst.LK_3)
MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4; MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4;
// Would really like to continue the block here, but it ends. TODO. // Would really like to continue the block here, but it ends. TODO.
SetJumpTarget(b); SetJumpTarget(b);