2019-04-06 09:15:19 -04:00
# include "stdafx.h"
# include "CpuDisUtils.h"
# include "CpuTypes.h"
# include "Cpu.h"
# include "Console.h"
2020-02-07 22:55:27 -05:00
# include "EmuSettings.h"
2019-04-06 09:15:19 -04:00
# include "DisassemblyInfo.h"
2019-04-28 22:19:52 -04:00
# include "LabelManager.h"
2019-04-06 09:15:19 -04:00
# include "DummyCpu.h"
# include "../Utilities/HexUtilities.h"
# include "../Utilities/FastString.h"
2021-03-10 11:13:28 -05:00
void CpuDisUtils : : GetDisassembly ( DisassemblyInfo & info , string & out , uint32_t memoryAddr , LabelManager * labelManager , EmuSettings * settings )
2019-04-06 09:15:19 -04:00
{
2020-02-07 22:55:27 -05:00
FastString str ( settings - > CheckDebuggerFlag ( DebuggerFlags : : UseLowerCaseDisassembly ) ) ;
2019-04-06 09:15:19 -04:00
uint8_t opCode = info . GetOpCode ( ) ;
AddrMode addrMode = CpuDisUtils : : OpMode [ opCode ] ;
str . Write ( CpuDisUtils : : OpName [ opCode ] ) ;
str . Write ( ' ' ) ;
uint32_t opAddr = CpuDisUtils : : GetOperandAddress ( info , memoryAddr ) ;
2019-04-06 17:38:14 -04:00
uint32_t opSize = info . GetOpSize ( ) ;
2019-04-06 09:15:19 -04:00
2020-02-07 22:55:27 -05:00
FastString operand ( settings - > CheckDebuggerFlag ( DebuggerFlags : : UseLowerCaseDisassembly ) ) ;
2021-03-10 11:13:28 -05:00
if ( opSize > 1 ) {
if ( addrMode = = AddrMode : : Rel | | addrMode = = AddrMode : : RelLng | | opSize = = 4 ) {
AddressInfo address { ( int32_t ) opAddr , SnesMemoryType : : CpuMemory } ;
2019-04-28 22:19:52 -04:00
string label = labelManager ? labelManager - > GetLabel ( address ) : " " ;
2021-03-10 11:13:28 -05:00
if ( label . size ( ) ) {
2020-02-07 22:55:27 -05:00
operand . Write ( label , true ) ;
2021-03-10 11:13:28 -05:00
} else {
2019-07-18 16:14:32 -04:00
operand . WriteAll ( ' $ ' , HexUtilities : : ToHex24 ( opAddr ) ) ;
2019-04-28 22:19:52 -04:00
}
2021-03-10 11:13:28 -05:00
} else if ( opSize = = 2 ) {
2019-07-18 16:14:32 -04:00
operand . WriteAll ( ' $ ' , HexUtilities : : ToHex ( ( uint8_t ) opAddr ) ) ;
2021-03-10 11:13:28 -05:00
} else if ( opSize = = 3 ) {
2019-07-18 16:14:32 -04:00
operand . WriteAll ( ' $ ' , HexUtilities : : ToHex ( ( uint16_t ) opAddr ) ) ;
2019-04-06 09:15:19 -04:00
}
}
2021-03-10 11:13:28 -05:00
switch ( addrMode ) {
case AddrMode : : Abs : str . Write ( operand ) ; break ;
case AddrMode : : AbsJmp : str . Write ( operand ) ; break ;
case AddrMode : : AbsIdxXInd : str . WriteAll ( ' ( ' , operand , " ,X) " ) ; break ;
case AddrMode : : AbsIdxX : str . WriteAll ( operand , " ,X " ) ; break ;
case AddrMode : : AbsIdxY : str . WriteAll ( operand , " ,Y " ) ; break ;
case AddrMode : : AbsInd : str . WriteAll ( ' ( ' , operand , ' ) ' ) ; break ;
case AddrMode : : AbsIndLng : str . WriteAll ( ' [ ' , operand , ' ] ' ) ; break ;
case AddrMode : : AbsLngIdxX : str . WriteAll ( operand , " ,X " ) ; break ;
case AddrMode : : AbsLng : str . Write ( operand ) ; break ;
case AddrMode : : AbsLngJmp : str . Write ( operand ) ; break ;
case AddrMode : : Acc : break ;
case AddrMode : : BlkMov : str . WriteAll ( ' $ ' , operand [ 1 ] , operand [ 2 ] , ' , ' ) ; str . WriteAll ( ' $ ' , operand [ 3 ] , operand [ 4 ] ) ; break ;
case AddrMode : : DirIdxIndX : str . WriteAll ( ' ( ' , operand , " ,X) " ) ; break ;
case AddrMode : : DirIdxX : str . WriteAll ( operand , " ,X " ) ; break ;
case AddrMode : : DirIdxY : str . WriteAll ( operand , " ,Y " ) ; break ;
case AddrMode : : DirIndIdxY : str . WriteAll ( " ( " , operand , " ),Y " ) ; break ;
case AddrMode : : DirIndLngIdxY : str . WriteAll ( " [ " , operand , " ],Y " ) ; break ;
case AddrMode : : DirIndLng : str . WriteAll ( " [ " , operand , " ] " ) ; break ;
case AddrMode : : DirInd : str . WriteAll ( " ( " , operand , " ) " ) ; break ;
case AddrMode : : Dir : str . Write ( operand ) ; break ;
case AddrMode : : Imm8 : case AddrMode : : Imm16 : case AddrMode : : ImmX : case AddrMode : : ImmM :
str . WriteAll ( ' # ' , operand ) ;
break ;
case AddrMode : : Sig8 : str . WriteAll ( ' # ' , operand ) ; break ; //BRK/COP signature
case AddrMode : : Imp : break ;
case AddrMode : : RelLng : str . Write ( operand ) ; break ;
case AddrMode : : Rel : str . Write ( operand ) ; break ;
case AddrMode : : Stk : break ;
case AddrMode : : StkRel : str . WriteAll ( operand , " ,S " ) ; break ;
case AddrMode : : StkRelIndIdxY : str . WriteAll ( ' ( ' , operand , " ,S),Y " ) ; break ;
default : throw std : : runtime_error ( " invalid address mode " ) ;
2019-04-06 09:15:19 -04:00
}
out + = str . ToString ( ) ;
}
2021-03-10 11:13:28 -05:00
uint32_t CpuDisUtils : : GetOperandAddress ( DisassemblyInfo & info , uint32_t memoryAddr )
2019-04-06 09:15:19 -04:00
{
2019-04-06 17:38:14 -04:00
uint32_t opSize = info . GetOpSize ( ) ;
2019-04-06 09:15:19 -04:00
uint32_t opAddr = 0 ;
uint8_t * byteCode = info . GetByteCode ( ) ;
2021-03-10 11:13:28 -05:00
if ( opSize = = 2 ) {
2019-04-06 09:15:19 -04:00
opAddr = byteCode [ 1 ] ;
2021-03-10 11:13:28 -05:00
} else if ( opSize = = 3 ) {
2019-04-06 09:15:19 -04:00
opAddr = byteCode [ 1 ] | ( byteCode [ 2 ] < < 8 ) ;
2021-03-10 11:13:28 -05:00
} else if ( opSize = = 4 ) {
2019-04-06 09:15:19 -04:00
opAddr = byteCode [ 1 ] | ( byteCode [ 2 ] < < 8 ) | ( byteCode [ 3 ] < < 16 ) ;
}
AddrMode addrMode = CpuDisUtils : : OpMode [ byteCode [ 0 ] ] ;
2021-03-10 11:13:28 -05:00
if ( addrMode = = AddrMode : : Rel | | addrMode = = AddrMode : : RelLng ) {
if ( opSize = = 2 ) {
2019-04-06 09:15:19 -04:00
opAddr = ( memoryAddr & 0xFF0000 ) | ( ( ( int8_t ) opAddr + memoryAddr + 2 ) & 0xFFFF ) ;
2021-03-10 11:13:28 -05:00
} else {
2019-04-06 09:15:19 -04:00
opAddr = ( memoryAddr & 0xFF0000 ) | ( ( ( int16_t ) opAddr + memoryAddr + 3 ) & 0xFFFF ) ;
}
}
return opAddr ;
}
2021-03-10 11:13:28 -05:00
int32_t CpuDisUtils : : GetEffectiveAddress ( DisassemblyInfo & info , Console * console , CpuState & state , CpuType type )
2019-04-06 09:15:19 -04:00
{
2021-03-10 11:13:28 -05:00
if ( HasEffectiveAddress ( CpuDisUtils : : OpMode [ info . GetOpCode ( ) ] ) ) {
2020-02-27 19:59:41 -05:00
DummyCpu cpu ( console , type ) ;
2019-04-06 09:15:19 -04:00
state . PS & = ~ ( ProcFlags : : IndexMode8 | ProcFlags : : MemoryMode8 ) ;
state . PS | = info . GetFlags ( ) ;
cpu . SetDummyState ( state ) ;
cpu . Exec ( ) ;
return cpu . GetLastOperand ( ) ;
}
return - 1 ;
}
2019-07-16 20:38:19 -04:00
bool CpuDisUtils : : HasEffectiveAddress ( AddrMode addrMode )
{
2021-03-10 11:13:28 -05:00
switch ( addrMode ) {
case AddrMode : : Acc :
case AddrMode : : Imp :
case AddrMode : : Stk :
case AddrMode : : Sig8 :
case AddrMode : : Imm8 :
case AddrMode : : Rel :
case AddrMode : : RelLng :
case AddrMode : : Imm16 :
case AddrMode : : BlkMov :
case AddrMode : : AbsLngJmp :
case AddrMode : : AbsLng :
case AddrMode : : ImmX :
case AddrMode : : ImmM :
case AddrMode : : AbsJmp :
return false ;
case AddrMode : : DirIdxIndX :
case AddrMode : : DirIdxX :
case AddrMode : : DirIdxY :
case AddrMode : : DirIndIdxY :
case AddrMode : : DirIndLngIdxY :
case AddrMode : : DirIndLng :
case AddrMode : : DirInd :
case AddrMode : : Dir :
case AddrMode : : StkRel :
case AddrMode : : StkRelIndIdxY :
case AddrMode : : Abs :
case AddrMode : : AbsIdxXInd :
case AddrMode : : AbsIdxX :
case AddrMode : : AbsIdxY :
case AddrMode : : AbsLngIdxX :
case AddrMode : : AbsInd :
case AddrMode : : AbsIndLng :
return true ;
2019-07-16 20:38:19 -04:00
}
throw std : : runtime_error ( " Invalid mode " ) ;
}
2019-04-06 17:38:14 -04:00
uint8_t CpuDisUtils : : GetOpSize ( AddrMode addrMode , uint8_t flags )
2019-04-06 09:15:19 -04:00
{
2021-03-10 11:13:28 -05:00
if ( addrMode = = AddrMode : : ImmX ) {
2019-08-04 16:32:59 -04:00
return ( flags & ProcFlags : : IndexMode8 ) ? 2 : 3 ;
2021-03-10 11:13:28 -05:00
} else if ( addrMode = = AddrMode : : ImmM ) {
2019-08-04 16:32:59 -04:00
return ( flags & ProcFlags : : MemoryMode8 ) ? 2 : 3 ;
2019-04-06 09:15:19 -04:00
}
2019-08-04 16:32:59 -04:00
return CpuDisUtils : : OpSize [ ( int ) addrMode ] ;
2019-04-06 09:15:19 -04:00
}
2019-04-06 17:38:14 -04:00
uint8_t CpuDisUtils : : GetOpSize ( uint8_t opCode , uint8_t flags )
2019-04-06 09:15:19 -04:00
{
2019-04-06 17:38:14 -04:00
return GetOpSize ( CpuDisUtils : : OpMode [ opCode ] , flags ) ;
2019-04-06 09:15:19 -04:00
}
2019-08-04 16:32:59 -04:00
uint8_t CpuDisUtils : : OpSize [ 0x1F ] = {
2 , 2 , 3 , 0 , 0 , 3 , 3 , 3 , 3 , 3 ,
3 , 4 , 4 , 3 , 4 , 1 , 3 , 2 , 2 , 2 ,
2 , 2 , 2 , 2 , 2 , 1 , 3 , 2 , 1 , 2 ,
2
} ;
2019-04-06 09:15:19 -04:00
string CpuDisUtils : : OpName [ 256 ] = {
//0 1 2 3 4 5 6 7 8 9 A B C D E F
" BRK " , " ORA " , " COP " , " ORA " , " TSB " , " ORA " , " ASL " , " ORA " , " PHP " , " ORA " , " ASL " , " PHD " , " TSB " , " ORA " , " ASL " , " ORA " , // 0
" BPL " , " ORA " , " ORA " , " ORA " , " TRB " , " ORA " , " ASL " , " ORA " , " CLC " , " ORA " , " INC " , " TCS " , " TRB " , " ORA " , " ASL " , " ORA " , // 1
" JSR " , " AND " , " JSL " , " AND " , " BIT " , " AND " , " ROL " , " AND " , " PLP " , " AND " , " ROL " , " PLD " , " BIT " , " AND " , " ROL " , " AND " , // 2
" BMI " , " AND " , " AND " , " AND " , " BIT " , " AND " , " ROL " , " AND " , " SEC " , " AND " , " DEC " , " TSC " , " BIT " , " AND " , " ROL " , " AND " , // 3
" RTI " , " EOR " , " WDM " , " EOR " , " MVP " , " EOR " , " LSR " , " EOR " , " PHA " , " EOR " , " LSR " , " PHK " , " JMP " , " EOR " , " LSR " , " EOR " , // 4
" BVC " , " EOR " , " EOR " , " EOR " , " MVN " , " EOR " , " LSR " , " EOR " , " CLI " , " EOR " , " PHY " , " TCD " , " JMP " , " EOR " , " LSR " , " EOR " , // 5
" RTS " , " ADC " , " PER " , " ADC " , " STZ " , " ADC " , " ROR " , " ADC " , " PLA " , " ADC " , " ROR " , " RTL " , " JMP " , " ADC " , " ROR " , " ADC " , // 6
" BVS " , " ADC " , " ADC " , " ADC " , " STZ " , " ADC " , " ROR " , " ADC " , " SEI " , " ADC " , " PLY " , " TDC " , " JMP " , " ADC " , " ROR " , " ADC " , // 7
" BRA " , " STA " , " BRL " , " STA " , " STY " , " STA " , " STX " , " STA " , " DEY " , " BIT " , " TXA " , " PHB " , " STY " , " STA " , " STX " , " STA " , // 8
" BCC " , " STA " , " STA " , " STA " , " STY " , " STA " , " STX " , " STA " , " TYA " , " STA " , " TXS " , " TXY " , " STZ " , " STA " , " STZ " , " STA " , // 9
" LDY " , " LDA " , " LDX " , " LDA " , " LDY " , " LDA " , " LDX " , " LDA " , " TAY " , " LDA " , " TAX " , " PLB " , " LDY " , " LDA " , " LDX " , " LDA " , // A
" BCS " , " LDA " , " LDA " , " LDA " , " LDY " , " LDA " , " LDX " , " LDA " , " CLV " , " LDA " , " TSX " , " TYX " , " LDY " , " LDA " , " LDX " , " LDA " , // B
" CPY " , " CMP " , " REP " , " CMP " , " CPY " , " CMP " , " DEC " , " CMP " , " INY " , " CMP " , " DEX " , " WAI " , " CPY " , " CMP " , " DEC " , " CMP " , // C
" BNE " , " CMP " , " CMP " , " CMP " , " PEI " , " CMP " , " DEC " , " CMP " , " CLD " , " CMP " , " PHX " , " STP " , " JML " , " CMP " , " DEC " , " CMP " , // D
" CPX " , " SBC " , " SEP " , " SBC " , " CPX " , " SBC " , " INC " , " SBC " , " INX " , " SBC " , " NOP " , " XBA " , " CPX " , " SBC " , " INC " , " SBC " , // E
2021-03-10 11:13:28 -05:00
" BEQ " , " SBC " , " SBC " , " SBC " , " PEA " , " SBC " , " INC " , " SBC " , " SED " , " SBC " , " PLX " , " XCE " , " JSR " , " SBC " , " INC " , " SBC " // F
2019-04-06 09:15:19 -04:00
} ;
typedef AddrMode M ;
AddrMode CpuDisUtils : : OpMode [ 256 ] = {
//0 1 2 3 4 5 6 7 8 9 A B C D E F
2021-03-10 11:13:28 -05:00
M : : Sig8 , M : : DirIdxIndX , M : : Sig8 , M : : StkRel , M : : Dir , M : : Dir , M : : Dir , M : : DirIndLng , M : : Stk , M : : ImmM , M : : Acc , M : : Stk , M : : Abs , M : : Abs , M : : Abs , M : : AbsLng , // 0
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : Dir , M : : DirIdxX , M : : DirIdxX , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Acc , M : : Imp , M : : Abs , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX , // 1
M : : Abs , M : : DirIdxIndX , M : : AbsLng , M : : StkRel , M : : Dir , M : : Dir , M : : Dir , M : : DirIndLng , M : : Stk , M : : ImmM , M : : Acc , M : : Stk , M : : Abs , M : : Abs , M : : Abs , M : : AbsLng , // 2
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : DirIdxX , M : : DirIdxX , M : : DirIdxX , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Acc , M : : Imp , M : : AbsIdxX , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX , // 3
M : : Stk , M : : DirIdxIndX , M : : Imm8 , M : : StkRel , M : : BlkMov , M : : Dir , M : : Dir , M : : DirIndLng , M : : Stk , M : : ImmM , M : : Acc , M : : Stk , M : : Abs , M : : Abs , M : : Abs , M : : AbsLng , // 4
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : BlkMov , M : : DirIdxX , M : : DirIdxX , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Stk , M : : Imp , M : : AbsLng , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX , // 5
M : : Stk , M : : DirIdxIndX , M : : RelLng , M : : StkRel , M : : Dir , M : : Dir , M : : Dir , M : : DirIndLng , M : : Stk , M : : ImmM , M : : Acc , M : : Stk , M : : AbsInd , M : : Abs , M : : Abs , M : : AbsLng , // 6
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : DirIdxX , M : : DirIdxX , M : : DirIdxX , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Stk , M : : Imp , M : : AbsIdxXInd , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX , // 7
M : : Rel , M : : DirIdxIndX , M : : RelLng , M : : StkRel , M : : Dir , M : : Dir , M : : Dir , M : : DirIndLng , M : : Imp , M : : ImmM , M : : Imp , M : : Stk , M : : Abs , M : : Abs , M : : Abs , M : : AbsLng , // 8
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : DirIdxX , M : : DirIdxX , M : : DirIdxY , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Imp , M : : Imp , M : : Abs , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX , // 9
M : : ImmX , M : : DirIdxIndX , M : : ImmX , M : : StkRel , M : : Dir , M : : Dir , M : : Dir , M : : DirIndLng , M : : Imp , M : : ImmM , M : : Imp , M : : Stk , M : : Abs , M : : Abs , M : : Abs , M : : AbsLng , // A
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : DirIdxX , M : : DirIdxX , M : : DirIdxY , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Imp , M : : Imp , M : : AbsIdxX , M : : AbsIdxX , M : : AbsIdxY , M : : AbsLngIdxX , // B
M : : ImmX , M : : DirIdxIndX , M : : Imm8 , M : : StkRel , M : : Dir , M : : Dir , M : : Dir , M : : DirIndLng , M : : Imp , M : : ImmM , M : : Imp , M : : Imp , M : : Abs , M : : Abs , M : : Abs , M : : AbsLng , // C
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : Dir , M : : DirIdxX , M : : DirIdxX , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Stk , M : : Imp , M : : AbsIndLng , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX , // D
M : : ImmX , M : : DirIdxIndX , M : : Imm8 , M : : StkRel , M : : Dir , M : : Dir , M : : Dir , M : : DirIndLng , M : : Imp , M : : ImmM , M : : Imp , M : : Imp , M : : Abs , M : : Abs , M : : Abs , M : : AbsLng , // E
M : : Rel , M : : DirIndIdxY , M : : DirInd , M : : StkRelIndIdxY , M : : Imm16 , M : : DirIdxX , M : : DirIdxX , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Stk , M : : Imp , M : : AbsIdxXInd , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX // F
} ;