2019-02-12 22:13:09 -05:00
# include "stdafx.h"
2019-02-13 13:32:21 -05:00
# include <algorithm>
2019-02-12 22:13:09 -05:00
# include "DisassemblyInfo.h"
# include "CpuTypes.h"
# include "MemoryManager.h"
2019-02-28 16:53:04 -05:00
# include "DummyCpu.h"
2019-02-12 22:13:09 -05:00
# include "../Utilities/HexUtilities.h"
2019-02-13 13:32:21 -05:00
# include "../Utilities/FastString.h"
2019-02-12 22:13:09 -05:00
DisassemblyInfo : : DisassemblyInfo ( )
{
}
2019-02-27 19:49:26 -05:00
DisassemblyInfo : : DisassemblyInfo ( uint8_t * opPointer , uint8_t cpuFlags )
2019-02-12 22:13:09 -05:00
{
2019-02-27 19:49:26 -05:00
Initialize ( opPointer , cpuFlags ) ;
}
void DisassemblyInfo : : Initialize ( uint8_t * opPointer , uint8_t cpuFlags )
{
2019-02-28 16:53:04 -05:00
_flags = cpuFlags & ( ProcFlags : : MemoryMode8 | ProcFlags : : IndexMode8 ) ;
2019-02-13 13:32:21 -05:00
2019-02-27 19:49:26 -05:00
_byteCode [ 0 ] = opPointer [ 0 ] ;
2019-02-12 22:13:09 -05:00
_addrMode = DisassemblyInfo : : OpMode [ _byteCode [ 0 ] ] ;
2019-02-27 19:49:26 -05:00
_opSize = GetOperandSize ( _addrMode , _flags ) + 1 ;
2019-02-12 22:13:09 -05:00
for ( int i = 1 ; i < _opSize ; i + + ) {
2019-02-27 19:49:26 -05:00
_byteCode [ i ] = opPointer [ i ] ;
2019-02-12 22:13:09 -05:00
}
}
2019-02-13 13:32:21 -05:00
void DisassemblyInfo : : GetDisassembly ( string & out , uint32_t memoryAddr )
2019-02-12 22:13:09 -05:00
{
2019-02-13 13:32:21 -05:00
FastString str ;
str . Write ( DisassemblyInfo : : OpName [ _byteCode [ 0 ] ] ) ;
str . Write ( ' ' ) ;
uint32_t opAddr = GetOperandAddress ( memoryAddr ) ;
FastString operand ;
if ( _opSize > 1 ) {
operand . Write ( ' $ ' ) ;
operand . Write ( HexUtilities : : ToHex ( opAddr ) ) ;
}
switch ( _addrMode ) {
case AddrMode : : Abs : str . Write ( operand ) ; break ;
2019-02-13 18:44:12 -05:00
case AddrMode : : AbsJmp : str . Write ( operand ) ; break ;
2019-02-13 13:32:21 -05:00
case AddrMode : : AbsIdxXInd : str . Write ( ' ( ' , operand , " ,X) " ) ; break ;
case AddrMode : : AbsIdxX : str . Write ( operand , " ,X " ) ; break ;
case AddrMode : : AbsIdxY : str . Write ( operand , " ,Y " ) ; break ;
case AddrMode : : AbsInd : str . Write ( ' ( ' , operand , ' ) ' ) ; break ;
case AddrMode : : AbsIndLng : str . Write ( ' [ ' , operand , ' ] ' ) ; break ;
case AddrMode : : AbsLngIdxX : str . Write ( operand , " ,X " ) ; break ;
case AddrMode : : AbsLng : str . Write ( operand ) ; break ;
2019-02-13 18:44:12 -05:00
case AddrMode : : AbsLngJmp : str . Write ( operand ) ; break ;
2019-02-13 13:32:21 -05:00
case AddrMode : : Acc : break ;
2019-02-28 16:53:04 -05:00
case AddrMode : : BlkMov : str . Write ( ' $ ' , operand [ 1 ] , operand [ 2 ] , " -> " ) ; str . Write ( ' $ ' , operand [ 3 ] , operand [ 4 ] ) ; break ;
2019-02-13 13:32:21 -05:00
case AddrMode : : DirIdxIndX : str . Write ( ' ( ' , operand , " ,X) " ) ; break ;
case AddrMode : : DirIdxX : str . Write ( operand , " ,X " ) ; break ;
case AddrMode : : DirIdxY : str . Write ( operand , " ,Y " ) ; break ;
case AddrMode : : DirIndIdxY : str . Write ( " ( " , operand , " ),Y " ) ; break ;
case AddrMode : : DirIndLngIdxY : str . Write ( " [ " , operand , " ],Y " ) ; break ;
case AddrMode : : DirIndLng : str . Write ( " [ " , operand , " ] " ) ; break ;
case AddrMode : : DirInd : str . Write ( " ( " , operand , " ) " ) ; break ;
case AddrMode : : Dir : str . Write ( operand ) ; break ;
2019-02-14 19:00:17 -05:00
case AddrMode : : Imm8 : case AddrMode : : Imm16 : case AddrMode : : ImmX : case AddrMode : : ImmM :
2019-02-13 13:32:21 -05:00
str . Write ( ' # ' , operand ) ;
break ;
case AddrMode : : Imp : break ; ;
case AddrMode : : RelLng : str . Write ( operand ) ;
case AddrMode : : Rel : str . Write ( operand ) ;
case AddrMode : : Stk : break ;
case AddrMode : : StkRel : str . Write ( operand , " ,S " ) ; break ;
case AddrMode : : StkRelIndIdxY : str . Write ( ' ( ' , operand , " ,S),Y " ) ; break ;
2019-02-13 18:44:12 -05:00
2019-02-21 18:18:25 -05:00
default : throw std : : runtime_error ( " invalid address mode " ) ;
2019-02-12 22:13:09 -05:00
}
2019-02-13 13:32:21 -05:00
out + = str . ToString ( ) ;
}
uint32_t DisassemblyInfo : : GetOperandAddress ( uint32_t memoryAddr )
{
uint32_t opAddr = 0 ;
if ( _opSize = = 2 ) {
opAddr = _byteCode [ 1 ] ;
} else if ( _opSize = = 3 ) {
opAddr = _byteCode [ 1 ] | ( _byteCode [ 2 ] < < 8 ) ;
} else if ( _opSize = = 4 ) {
opAddr = _byteCode [ 1 ] | ( _byteCode [ 2 ] < < 8 ) | ( _byteCode [ 3 ] < < 16 ) ;
}
if ( _addrMode = = AddrMode : : Rel ) {
if ( _opSize = = 2 ) {
opAddr = ( int8_t ) opAddr + memoryAddr + 2 ;
} else {
opAddr = ( int16_t ) opAddr + memoryAddr + 2 ;
}
}
return opAddr ;
2019-02-12 22:13:09 -05:00
}
uint8_t DisassemblyInfo : : GetOperandSize ( )
{
2019-02-27 19:49:26 -05:00
return _opSize - 1 ;
}
uint8_t DisassemblyInfo : : GetOperandSize ( AddrMode addrMode , uint8_t flags )
{
switch ( addrMode ) {
2019-02-13 18:44:12 -05:00
case AddrMode : : Acc :
case AddrMode : : Imp :
case AddrMode : : Stk :
return 0 ;
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 : : Imm8 :
case AddrMode : : Rel :
case AddrMode : : StkRel :
case AddrMode : : StkRelIndIdxY :
return 1 ;
case AddrMode : : Abs :
case AddrMode : : AbsIdxXInd :
case AddrMode : : AbsIdxX :
case AddrMode : : AbsIdxY :
case AddrMode : : AbsInd :
case AddrMode : : AbsIndLng :
case AddrMode : : AbsJmp :
case AddrMode : : BlkMov :
2019-02-14 19:00:17 -05:00
case AddrMode : : Imm16 :
case AddrMode : : RelLng :
2019-02-13 18:44:12 -05:00
return 2 ;
case AddrMode : : AbsLngJmp :
case AddrMode : : AbsLngIdxX :
case AddrMode : : AbsLng :
return 3 ;
2019-02-13 13:32:21 -05:00
2019-02-27 19:49:26 -05:00
case AddrMode : : ImmX : return ( flags & ProcFlags : : IndexMode8 ) ? 1 : 2 ;
case AddrMode : : ImmM : return ( flags & ProcFlags : : MemoryMode8 ) ? 1 : 2 ;
2019-02-12 22:13:09 -05:00
}
2019-02-21 18:18:25 -05:00
throw std : : runtime_error ( " Invalid mode " ) ;
2019-02-12 22:13:09 -05:00
}
2019-02-27 19:49:26 -05:00
uint8_t DisassemblyInfo : : GetOperandSize ( uint8_t opCode , uint8_t flags )
{
return GetOperandSize ( DisassemblyInfo : : OpMode [ opCode ] , flags ) ;
}
void DisassemblyInfo : : GetByteCode ( uint8_t copyBuffer [ 4 ] )
{
memcpy ( copyBuffer , _byteCode , _opSize ) ;
}
2019-02-12 22:13:09 -05:00
void DisassemblyInfo : : GetByteCode ( string & out )
{
2019-02-13 13:32:21 -05:00
FastString str ;
2019-02-12 22:13:09 -05:00
for ( int i = 0 ; i < _opSize ; i + + ) {
2019-02-13 13:32:21 -05:00
str . Write ( ' $ ' , HexUtilities : : ToHex ( _byteCode [ i ] ) ) ;
if ( i < _opSize - 1 ) {
str . Write ( ' ' ) ;
}
}
out + = str . ToString ( ) ;
}
2019-02-28 16:53:04 -05:00
void DisassemblyInfo : : GetEffectiveAddressString ( string & out , CpuState & state , MemoryManager * memoryManager )
2019-02-13 13:32:21 -05:00
{
2019-02-28 16:53:04 -05:00
int32_t effectiveAddress = GetEffectiveAddress ( state , memoryManager ) ;
2019-02-13 18:44:12 -05:00
if ( effectiveAddress > = 0 ) {
out + = " [ " + HexUtilities : : ToHex24 ( effectiveAddress ) + " ] " ;
}
}
2019-02-28 16:53:04 -05:00
int32_t DisassemblyInfo : : GetEffectiveAddress ( CpuState & state , MemoryManager * memoryManager )
2019-02-13 18:44:12 -05:00
{
2019-02-28 16:53:04 -05:00
if ( _addrMode > AddrMode : : ImmM & & _addrMode ! = AddrMode : : Acc & & _addrMode ! = AddrMode : : Imp & & _addrMode ! = AddrMode : : Stk & & _addrMode ! = AddrMode : : Rel & & _addrMode ! = AddrMode : : RelLng & & _addrMode ! = AddrMode : : BlkMov ) {
DummyCpu cpu ( memoryManager ) ;
state . PS & = ~ ( ProcFlags : : IndexMode8 | ProcFlags : : MemoryMode8 ) ;
state . PS | = _flags ;
cpu . SetDummyState ( state ) ;
cpu . Exec ( ) ;
return cpu . GetLastOperand ( ) ;
}
return - 1 ;
2019-02-13 18:44:12 -05:00
}
2019-02-13 13:32:21 -05:00
2019-02-28 16:53:04 -05:00
uint16_t DisassemblyInfo : : GetMemoryValue ( uint32_t effectiveAddress , MemoryManager * memoryManager , uint8_t & valueSize )
2019-02-13 18:44:12 -05:00
{
2019-02-28 16:53:04 -05:00
if ( _flags & ProcFlags : : MemoryMode8 ) {
valueSize = 1 ;
return memoryManager - > Peek ( effectiveAddress ) ;
} else {
valueSize = 2 ;
return memoryManager - > PeekWord ( effectiveAddress ) ;
2019-02-12 22:13:09 -05:00
}
}
string DisassemblyInfo : : 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
" BEQ " , " SBC " , " SBC " , " SBC " , " PEA " , " SBC " , " INC " , " SBC " , " SED " , " SBC " , " PLX " , " XCE " , " JSR " , " SBC " , " INC " , " SBC " // F
} ;
typedef AddrMode M ;
AddrMode DisassemblyInfo : : OpMode [ 256 ] = {
//0 1 2 3 4 5 6 7 8 9 A B C D E F
M : : Stk , M : : DirIdxIndX , M : : Stk , 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 : : Stk , 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 : : Stk , 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 : : Stk , M : : DirIdxX , M : : DirIdxX , M : : DirIndLngIdxY , M : : Imp , M : : AbsIdxY , M : : Stk , M : : Imp , M : : AbsIdxXInd , M : : AbsIdxX , M : : AbsIdxX , M : : AbsLngIdxX // F
} ;