2020-05-18 16:10:53 -04:00
# include"stdafx.h"
# include"GameboyDisUtils.h"
# include"Console.h"
# include"DisassemblyInfo.h"
# include"EmuSettings.h"
# include"LabelManager.h"
# include".. / Utilities / FastString.h"
# include".. / Utilities / HexUtilities.h"
constexpr const char * _opTemplate [ 256 ] = {
2020-06-06 22:27:54 -04:00
" NOP " , " LD BC, e " , " LD (BC), A " , " INC BC " , " INC B " , " DEC B " , " LD B, d " , " RLCA " , " LD (a), SP " , " ADD HL, BC " , " LD A, (BC) " , " DEC BC " , " INC C " , " DEC C " , " LD C, d " , " RRCA " ,
2020-05-18 16:10:53 -04:00
" STOP " , " LD DE, e " , " LD (DE), A " , " INC DE " , " INC D " , " DEC D " , " LD D, d " , " RLA " , " JR r " , " ADD HL, DE " , " LD A, (DE) " , " DEC DE " , " INC E " , " DEC E " , " LD E, d " , " RRA " ,
2020-06-01 20:07:20 -04:00
" JR NZ, r " , " LD HL, e " , " LD (HL+), A " , " INC HL " , " INC H " , " DEC H " , " LD H, d " , " DAA " , " JR Z, r " , " ADD HL, HL " , " LD A, (HL+) " , " DEC HL " , " INC L " , " DEC L " , " LD L, d " , " CPL " ,
" JR NC, r " , " LD SP, e " , " LD (HL-), A " , " INC SP " , " INC (HL) " , " DEC (HL) " , " LD (HL), d " , " SCF " , " JR C, r " , " ADD HL, SP " , " LD A, (HL-) " , " DEC SP " , " INC A " , " DEC A " , " LD A, d " , " CCF " ,
2020-05-18 16:10:53 -04:00
" LD B, B " , " LD B, C " , " LD B, D " , " LD B, E " , " LD B, H " , " LD B, L " , " LD B, (HL) " , " LD B, A " , " LD C, B " , " LD C, C " , " LD C, D " , " LD C, E " , " LD C, H " , " LD C, L " , " LD C, (HL) " , " LD C, A " ,
" LD D, B " , " LD D, C " , " LD D, D " , " LD D, E " , " LD D, H " , " LD D, L " , " LD D, (HL) " , " LD D, A " , " LD E, B " , " LD E, C " , " LD E, D " , " LD E, E " , " LD E, H " , " LD E, L " , " LD E, (HL) " , " LD E, A " ,
" LD H, B " , " LD H, C " , " LD H, D " , " LD H, E " , " LD H, H " , " LD H, L " , " LD H, (HL) " , " LD H, A " , " LD L, B " , " LD L, C " , " LD L, D " , " LD L, E " , " LD L, H " , " LD L, L " , " LD L, (HL) " , " LD L, A " ,
2020-06-06 22:27:54 -04:00
" LD (HL), B " , " LD (HL), C " , " LD (HL), D " , " LD (HL), E " , " LD (HL), H " , " LD (HL), L " , " HALT " , " LD (HL), A " , " LD A, B " , " LD A, C " , " LD A, D " , " LD A, E " , " LD A, H " , " LD A, L " , " LD A, (HL) " , " LD A, A " ,
2020-05-18 16:10:53 -04:00
" ADD A, B " , " ADD A, C " , " ADD A, D " , " ADD A, E " , " ADD A, H " , " ADD A, L " , " ADD A, (HL) " , " ADD A, A " , " ADC A, B " , " ADC A, C " , " ADC A, D " , " ADC A, E " , " ADC A, H " , " ADC A, L " , " ADC A, (HL) " , " ADC A, A " ,
" SUB B " , " SUB C " , " SUB D " , " SUB E " , " SUB H " , " SUB L " , " SUB (HL) " , " SUB A " , " SBC A, B " , " SBC A, C " , " SBC A, D " , " SBC A, E " , " SBC A, H " , " SBC A, L " , " SBC A, (HL) " , " SBC A, A " ,
" AND B " , " AND C " , " AND D " , " AND E " , " AND H " , " AND L " , " AND (HL) " , " AND A " , " XOR B " , " XOR C " , " XOR D " , " XOR E " , " XOR H " , " XOR L " , " XOR (HL) " , " XOR A " ,
" OR B " , " OR C " , " OR D " , " OR E " , " OR H " , " OR L " , " OR (HL) " , " OR A " , " CP B " , " CP C " , " CP D " , " CP E " , " CP H " , " CP L " , " CP (HL) " , " CP A " ,
" RET NZ " , " POP BC " , " JP NZ, a " , " JP a " , " CALL NZ, a " , " PUSH BC " , " ADD A, d " , " RST 00H " , " RET Z " , " RET " , " JP Z, a " , " PREFIX " , " CALL Z, a " , " CALL a " , " ADC A, d " , " RST 08H " ,
" RET NC " , " POP DE " , " JP NC, a " , " ILL_D3 " , " CALL NC, a " , " PUSH DE " , " SUB d " , " RST 10H " , " RET C " , " RETI " , " JP C, a " , " ILL_DB " , " CALL C, a " , " ILL_DD " , " SBC A, d " , " RST 18H " ,
" LDH (c), A " , " POP HL " , " LD ($FF00+C), A " , " ILL_E3 " , " ILL_E4 " , " PUSH HL " , " AND d " , " RST 20H " , " ADD SP, d " , " JP HL " , " LD (a), A " , " ILL_EB " , " ILL_EC " , " ILL_ED " , " XOR d " , " RST 28H " ,
2020-06-06 22:27:54 -04:00
" LDH A, (c) " , " POP AF " , " LD A, ($FF00+C) " , " DI " , " ILL_F4 " , " PUSH AF " , " OR d " , " RST 30H " , " LD HL, SP+d " , " LD SP, HL " , " LD A, (a) " , " EI " , " ILL_FC " , " ILL_FD " , " CP d " , " RST 38H "
2020-05-18 16:10:53 -04:00
} ;
constexpr const char * _cbTemplate [ 256 ] = {
" RLC B " , " RLC C " , " RLC D " , " RLC E " , " RLC H " , " RLC L " , " RLC (HL) " , " RLC A " , " RRC B " , " RRC C " , " RRC D " , " RRC E " , " RRC H " , " RRC L " , " RRC (HL) " , " RRC A " ,
" RL B " , " RL C " , " RL D " , " RL E " , " RL H " , " RL L " , " RL (HL) " , " RL A " , " RR B " , " RR C " , " RR D " , " RR E " , " RR H " , " RR L " , " RR (HL) " , " RR A " ,
" SLA B " , " SLA C " , " SLA D " , " SLA E " , " SLA H " , " SLA L " , " SLA (HL) " , " SLA A " , " SRA B " , " SRA C " , " SRA D " , " SRA E " , " SRA H " , " SRA L " , " SRA (HL) " , " SRA A " ,
" SWAP B " , " SWAP C " , " SWAP D " , " SWAP E " , " SWAP H " , " SWAP L " , " SWAP (HL) " , " SWAP A " , " SRL B " , " SRL C " , " SRL D " , " SRL E " , " SRL H " , " SRL L " , " SRL (HL) " , " SRL A " ,
" BIT 0, B " , " BIT 0, C " , " BIT 0, D " , " BIT 0, E " , " BIT 0, H " , " BIT 0, L " , " BIT 0, (HL) " , " BIT 0, A " , " BIT 1, B " , " BIT 1, C " , " BIT 1, D " , " BIT 1, E " , " BIT 1, H " , " BIT 1, L " , " BIT 1, (HL) " , " BIT 1, A " ,
" BIT 2, B " , " BIT 2, C " , " BIT 2, D " , " BIT 2, E " , " BIT 2, H " , " BIT 2, L " , " BIT 2, (HL) " , " BIT 2, A " , " BIT 3, B " , " BIT 3, C " , " BIT 3, D " , " BIT 3, E " , " BIT 3, H " , " BIT 3, L " , " BIT 3, (HL) " , " BIT 3, A " ,
" BIT 4, B " , " BIT 4, C " , " BIT 4, D " , " BIT 4, E " , " BIT 4, H " , " BIT 4, L " , " BIT 4, (HL) " , " BIT 4, A " , " BIT 5, B " , " BIT 5, C " , " BIT 5, D " , " BIT 5, E " , " BIT 5, H " , " BIT 5, L " , " BIT 5, (HL) " , " BIT 5, A " ,
" BIT 6, B " , " BIT 6, C " , " BIT 6, D " , " BIT 6, E " , " BIT 6, H " , " BIT 6, L " , " BIT 6, (HL) " , " BIT 6, A " , " BIT 7, B " , " BIT 7, C " , " BIT 7, D " , " BIT 7, E " , " BIT 7, H " , " BIT 7, L " , " BIT 7, (HL) " , " BIT 7, A " ,
" RES 0, B " , " RES 0, C " , " RES 0, D " , " RES 0, E " , " RES 0, H " , " RES 0, L " , " RES 0, (HL) " , " RES 0, A " , " RES 1, B " , " RES 1, C " , " RES 1, D " , " RES 1, E " , " RES 1, H " , " RES 1, L " , " RES 1, (HL) " , " RES 1, A " ,
" RES 2, B " , " RES 2, C " , " RES 2, D " , " RES 2, E " , " RES 2, H " , " RES 2, L " , " RES 2, (HL) " , " RES 2, A " , " RES 3, B " , " RES 3, C " , " RES 3, D " , " RES 3, E " , " RES 3, H " , " RES 3, L " , " RES 3, (HL) " , " RES 3, A " ,
" RES 4, B " , " RES 4, C " , " RES 4, D " , " RES 4, E " , " RES 4, H " , " RES 4, L " , " RES 4, (HL) " , " RES 4, A " , " RES 5, B " , " RES 5, C " , " RES 5, D " , " RES 5, E " , " RES 5, H " , " RES 5, L " , " RES 5, (HL) " , " RES 5, A " ,
" RES 6, B " , " RES 6, C " , " RES 6, D " , " RES 6, E " , " RES 6, H " , " RES 6, L " , " RES 6, (HL) " , " RES 6, A " , " RES 7, B " , " RES 7, C " , " RES 7, D " , " RES 7, E " , " RES 7, H " , " RES 7, L " , " RES 7, (HL) " , " RES 7, A " ,
" SET 0, B " , " SET 0, C " , " SET 0, D " , " SET 0, E " , " SET 0, H " , " SET 0, L " , " SET 0, (HL) " , " SET 0, A " , " SET 1, B " , " SET 1, C " , " SET 1, D " , " SET 1, E " , " SET 1, H " , " SET 1, L " , " SET 1, (HL) " , " SET 1, A " ,
" SET 2, B " , " SET 2, C " , " SET 2, D " , " SET 2, E " , " SET 2, H " , " SET 2, L " , " SET 2, (HL) " , " SET 2, A " , " SET 3, B " , " SET 3, C " , " SET 3, D " , " SET 3, E " , " SET 3, H " , " SET 3, L " , " SET 3, (HL) " , " SET 3, A " ,
" SET 4, B " , " SET 4, C " , " SET 4, D " , " SET 4, E " , " SET 4, H " , " SET 4, L " , " SET 4, (HL) " , " SET 4, A " , " SET 5, B " , " SET 5, C " , " SET 5, D " , " SET 5, E " , " SET 5, H " , " SET 5, L " , " SET 5, (HL) " , " SET 5, A " ,
" SET 6, B " , " SET 6, C " , " SET 6, D " , " SET 6, E " , " SET 6, H " , " SET 6, L " , " SET 6, (HL) " , " SET 6, A " , " SET 7, B " , " SET 7, C " , " SET 7, D " , " SET 7, E " , " SET 7, H " , " SET 7, L " , " SET 7, (HL) " , " SET 7, A " ,
} ;
constexpr const uint8_t _opSize [ 256 ] = {
1 , 3 , 1 , 1 , 1 , 1 , 2 , 1 , 3 , 1 , 1 , 1 , 1 , 1 , 2 , 1 ,
1 , 3 , 1 , 1 , 1 , 1 , 2 , 1 , 2 , 1 , 1 , 1 , 1 , 1 , 2 , 1 ,
2 , 3 , 1 , 1 , 1 , 1 , 2 , 1 , 2 , 1 , 1 , 1 , 1 , 1 , 2 , 1 ,
2 , 3 , 1 , 1 , 1 , 1 , 2 , 1 , 2 , 1 , 1 , 1 , 1 , 1 , 2 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
2020-05-26 23:56:34 -04:00
1 , 1 , 3 , 3 , 3 , 1 , 2 , 1 , 1 , 1 , 3 , 2 , 3 , 3 , 2 , 1 ,
2020-05-18 16:10:53 -04:00
1 , 1 , 3 , 1 , 3 , 1 , 2 , 1 , 1 , 1 , 3 , 1 , 3 , 1 , 2 , 1 ,
2 , 1 , 1 , 1 , 1 , 1 , 2 , 1 , 2 , 1 , 3 , 1 , 1 , 1 , 2 , 1 ,
2 , 1 , 1 , 1 , 1 , 1 , 2 , 1 , 2 , 1 , 3 , 1 , 1 , 1 , 2 , 1 ,
} ;
2020-07-03 23:38:02 -04:00
enum class AddrType : uint8_t
2020-07-03 15:45:07 -04:00
{
None ,
BC ,
DE ,
HL ,
C ,
Suff
} ;
static constexpr const AddrType _gbEffAddrType [ 256 ] = {
AddrType : : None , AddrType : : None , AddrType : : BC , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : BC , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None ,
AddrType : : None , AddrType : : None , AddrType : : DE , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : DE , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None ,
AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None ,
AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None , AddrType : : HL , AddrType : : HL , AddrType : : HL , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None ,
AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None ,
AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None ,
AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None ,
AddrType : : HL , AddrType : : HL , AddrType : : HL , AddrType : : HL , AddrType : : HL , AddrType : : HL , AddrType : : None , AddrType : : HL , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None ,
AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None ,
AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None ,
AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None ,
AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : HL , AddrType : : None ,
AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : Suff , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None ,
AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None ,
AddrType : : None , AddrType : : None , AddrType : : C , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None ,
AddrType : : None , AddrType : : None , AddrType : : C , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None , AddrType : : None
} ;
2020-05-18 16:10:53 -04:00
void GameboyDisUtils : : GetDisassembly ( DisassemblyInfo & info , string & out , uint32_t memoryAddr , LabelManager * labelManager , EmuSettings * settings )
{
FastString str ( settings - > CheckDebuggerFlag ( DebuggerFlags : : UseLowerCaseDisassembly ) ) ;
AddressInfo addrInfo { 0 , SnesMemoryType : : GameboyMemory } ;
auto getOperand = [ & str , & addrInfo , labelManager ] ( uint16_t addr ) {
addrInfo . Address = addr ;
string label = labelManager ? labelManager - > GetLabel ( addrInfo ) : " " ;
if ( label . empty ( ) ) {
str . WriteAll ( ' $ ' , HexUtilities : : ToHex ( addr ) ) ;
} else {
str . Write ( label , true ) ;
}
} ;
uint8_t * byteCode = info . GetByteCode ( ) ;
2020-05-26 23:56:34 -04:00
const char * op = byteCode [ 0 ] = = 0xCB ? _cbTemplate [ byteCode [ 1 ] ] : _opTemplate [ byteCode [ 0 ] ] ;
2020-05-18 16:10:53 -04:00
if ( byteCode [ 0 ] = = 0xCB ) {
byteCode + + ;
}
int i = 0 ;
while ( op [ i ] ) {
switch ( op [ i ] ) {
2020-06-01 20:07:20 -04:00
//Relative jumps
2020-05-18 16:10:53 -04:00
case ' r ' : getOperand ( ( uint16_t ) ( memoryAddr + ( int8_t ) byteCode [ 1 ] + GetOpSize ( byteCode [ 0 ] ) ) ) ; break ;
2020-06-01 20:07:20 -04:00
//Jump addresses, memory addresses
2020-05-18 16:10:53 -04:00
case ' a ' : getOperand ( ( uint16_t ) ( byteCode [ 1 ] | ( byteCode [ 2 ] < < 8 ) ) ) ; break ;
2020-06-06 22:27:54 -04:00
case ' c ' : getOperand ( ( uint16_t ) ( 0xFF00 | byteCode [ 1 ] ) ) ; break ;
2020-05-18 16:10:53 -04:00
2020-06-01 20:07:20 -04:00
//Immediate values
case ' d ' : str . WriteAll ( " $ " , HexUtilities : : ToHex ( byteCode [ 1 ] ) ) ; break ;
case ' e ' : str . WriteAll ( " $ " , HexUtilities : : ToHex ( ( uint16_t ) ( byteCode [ 1 ] | ( byteCode [ 2 ] < < 8 ) ) ) ) ; break ;
2020-05-18 16:10:53 -04:00
default : str . Write ( op [ i ] ) ; break ;
}
i + + ;
}
out + = str . ToString ( ) ;
}
int32_t GameboyDisUtils : : GetEffectiveAddress ( DisassemblyInfo & info , Console * console , GbCpuState & state )
{
2020-07-03 15:45:07 -04:00
switch ( _gbEffAddrType [ info . GetOpCode ( ) ] ) {
default :
case AddrType : : None : return - 1 ;
case AddrType : : BC : return ( state . B < < 8 ) | state . C ;
case AddrType : : DE : return ( state . D < < 8 ) | state . E ;
case AddrType : : HL : return ( state . H < < 8 ) | state . L ;
case AddrType : : C : return 0xFF00 + state . C ;
case AddrType : : Suff :
if ( ( info . GetByteCode ( ) [ 1 ] & 0x07 ) = = 0x06 ) {
return ( state . H < < 8 ) | state . L ;
}
return - 1 ;
}
2020-05-18 16:10:53 -04:00
}
uint8_t GameboyDisUtils : : GetOpSize ( uint8_t opCode )
{
return _opSize [ opCode ] ;
}
bool GameboyDisUtils : : IsJumpToSub ( uint8_t opCode )
{
return (
opCode = = 0xC4 | | opCode = = 0xCC | | opCode = = 0xD4 | | opCode = = 0xDC | | //CALL conditional
opCode = = 0xCD | | //Unconditional CALL
opCode = = 0xC7 | | opCode = = 0xCF | | opCode = = 0xD7 | | opCode = = 0xDF | | opCode = = 0xE7 | | opCode = = 0xEF | | opCode = = 0xF7 | | opCode = = 0xFF //RST unconditional
) ;
}
bool GameboyDisUtils : : IsReturnInstruction ( uint8_t opCode )
{
return (
opCode = = 0xC0 | | opCode = = 0xC8 | | opCode = = 0xD0 | | opCode = = 0xD8 | | //Conditional RET
opCode = = 0xC9 | | opCode = = 0xD9 //Unconditional RET/RETI
) ;
2020-06-06 22:27:54 -04:00
}
string GameboyDisUtils : : GetOpTemplate ( uint8_t op , bool prefixed )
{
return prefixed ? _cbTemplate [ op ] : _opTemplate [ op ] ;
2020-05-18 16:10:53 -04:00
}