clang-format everything
This commit is contained in:
parent
a5c63c1b09
commit
0ab9380be3
|
@ -0,0 +1,78 @@
|
|||
Language: Cpp
|
||||
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveDeclarations: false
|
||||
#AlignConsecutiveMacros: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: false
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
#AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
#BreakInheritanceList: BeforeComma
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 100
|
||||
CompactNamespaces: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
FixNamespaceComments: true
|
||||
IncludeBlocks: Preserve
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: None
|
||||
PenaltyBreakAssignment: 50
|
||||
PenaltyBreakBeforeFirstCallParameter: 0
|
||||
PenaltyBreakComment: 100
|
||||
PenaltyBreakFirstLessLess: 200
|
||||
PenaltyBreakString: 100
|
||||
#PenaltyBreakTemplateDeclaration: 0
|
||||
PenaltyExcessCharacter: 10
|
||||
PenaltyReturnTypeOnItsOwnLine: 1000
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SpaceAfterCStyleCast: false
|
||||
#SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
#SpaceBeforeCpp11BracedList: true
|
||||
#SpaceBeforeCtorInitializerColon: false
|
||||
#SpaceBeforeInheritanceColon: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
#SpaceBeforeRangeBasedForLoopColon: false
|
||||
#SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 4
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
#Standard: c++17
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
|
@ -22,23 +22,22 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
// The Power-specific opcodes for the processor - ppcopcodes.cpp
|
||||
// Any shared opcodes are in ppcopcodes.cpp
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include <iostream>
|
||||
#include <array>
|
||||
#include <stdio.h>
|
||||
#include <stdexcept>
|
||||
#include "ppcemu.h"
|
||||
#include "ppcmmu.h"
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
void power_abs() {
|
||||
ppc_grab_regsda();
|
||||
if (ppc_result_a == 0x80000000) {
|
||||
ppc_result_d = ppc_result_a;
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_store_result_regd();
|
||||
|
@ -50,8 +49,7 @@ void power_absdot() {
|
|||
if (ppc_result_a == 0x80000000) {
|
||||
ppc_result_d = ppc_result_a;
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
@ -64,8 +62,7 @@ void power_abso() {
|
|||
ppc_result_d = ppc_result_a;
|
||||
ppc_state.spr[SPR::XER] |= 0x40000000;
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_store_result_regd();
|
||||
|
@ -77,8 +74,7 @@ void power_absodot() {
|
|||
ppc_result_d = ppc_result_a;
|
||||
ppc_state.spr[SPR::XER] |= 0x40000000;
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
@ -164,8 +160,7 @@ void power_doz() {
|
|||
ppc_grab_regsdab();
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
ppc_store_result_rega();
|
||||
|
@ -175,8 +170,7 @@ void power_dozdot() {
|
|||
ppc_grab_regsdab();
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
@ -186,8 +180,7 @@ void power_dozdot() {
|
|||
void power_dozo() {
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
}
|
||||
|
@ -195,8 +188,7 @@ void power_dozo() {
|
|||
void power_dozodot() {
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
}
|
||||
|
@ -205,8 +197,7 @@ void power_dozi() {
|
|||
ppc_grab_regsdab();
|
||||
if (((int32_t)ppc_result_a) > simm) {
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ~ppc_result_a + simm + 1;
|
||||
}
|
||||
ppc_store_result_rega();
|
||||
|
@ -260,8 +251,7 @@ void power_lscbx() {
|
|||
if (shift_amount == 3) {
|
||||
shift_amount = 0;
|
||||
reg_d = (reg_d + 1) & 0x1F;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
shift_amount++;
|
||||
}
|
||||
} while (bytes_to_load > 0);
|
||||
|
@ -283,11 +273,9 @@ void power_maskg() {
|
|||
for (uint32_t i = mask_start; i < mask_end; i++) {
|
||||
insert_mask |= (0x80000000 >> i);
|
||||
}
|
||||
}
|
||||
else if (mask_start == (mask_end + 1)) {
|
||||
} else if (mask_start == (mask_end + 1)) {
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
for (uint32_t i = (mask_end + 1); i < (mask_start - 1); i++) {
|
||||
insert_mask &= (~(0x80000000 >> i));
|
||||
|
@ -308,11 +296,9 @@ void power_maskgdot() {
|
|||
for (uint32_t i = mask_start; i < mask_end; i++) {
|
||||
insert_mask |= (0x80000000 >> i);
|
||||
}
|
||||
}
|
||||
else if (mask_start == (mask_end + 1)) {
|
||||
} else if (mask_start == (mask_end + 1)) {
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
for (uint32_t i = (mask_end + 1); i < (mask_start - 1); i++) {
|
||||
insert_mask &= (~(0x80000000 >> i));
|
||||
|
@ -364,7 +350,6 @@ void power_mul() {
|
|||
ppc_result_d = ((uint32_t)(product >> 32));
|
||||
ppc_state.spr[SPR::MQ] = ((uint32_t)(product));
|
||||
ppc_store_result_regd();
|
||||
|
||||
}
|
||||
|
||||
void power_muldot() {
|
||||
|
@ -376,7 +361,6 @@ void power_muldot() {
|
|||
ppc_state.spr[SPR::MQ] = ((uint32_t)(product));
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
ppc_store_result_regd();
|
||||
|
||||
}
|
||||
|
||||
void power_mulo() {
|
||||
|
@ -385,7 +369,6 @@ void power_mulo() {
|
|||
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
|
||||
ppc_result_d = ((uint32_t)(product >> 32));
|
||||
ppc_state.spr[SPR::MQ] = ((uint32_t)(product));
|
||||
|
||||
}
|
||||
|
||||
void power_mulodot() {
|
||||
|
@ -394,7 +377,6 @@ void power_mulodot() {
|
|||
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
|
||||
ppc_result_d = ((uint32_t)(product >> 32));
|
||||
ppc_state.spr[SPR::MQ] = ((uint32_t)(product));
|
||||
|
||||
}
|
||||
|
||||
void power_nabs() {
|
||||
|
@ -426,11 +408,9 @@ void power_rlmi() {
|
|||
for (uint32_t i = rot_mb; i < rot_me; i++) {
|
||||
insert_mask |= (0x80000000 >> i);
|
||||
}
|
||||
}
|
||||
else if (rot_mb == (rot_me + 1)) {
|
||||
} else if (rot_mb == (rot_me + 1)) {
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
for (uint32_t i = (rot_me + 1); i < (rot_mb - 1); i++) {
|
||||
insert_mask &= (~(0x80000000 >> i));
|
||||
|
@ -446,8 +426,7 @@ void power_rrib() {
|
|||
ppc_grab_regssab();
|
||||
if (ppc_result_d & 0x80000000) {
|
||||
ppc_result_a |= (0x80000000 >> ppc_result_b);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_a &= ~(0x80000000 >> ppc_result_b);
|
||||
}
|
||||
ppc_store_result_rega();
|
||||
|
@ -457,8 +436,7 @@ void power_rribdot() {
|
|||
ppc_grab_regssab();
|
||||
if (ppc_result_d & 0x80000000) {
|
||||
ppc_result_a |= (0x80000000 >> ppc_result_b);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_a &= ~(0x80000000 >> ppc_result_b);
|
||||
}
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -32,11 +32,11 @@ typedef struct PPCDisasmContext {
|
|||
bool simplified; /* true if we should output simplified mnemonics */
|
||||
} PPCDisasmContext;
|
||||
|
||||
std::string disassemble_single(PPCDisasmContext *ctx);
|
||||
std::string disassemble_single(PPCDisasmContext* ctx);
|
||||
|
||||
int test_ppc_disasm(void);
|
||||
|
||||
/** sign-extend an integer. */
|
||||
#define SIGNEXT(x, sb) ((x) | (((x) & (1 << (sb))) ? ~((1 << (sb))-1) : 0))
|
||||
#define SIGNEXT(x, sb) ((x) | (((x) & (1 << (sb))) ? ~((1 << (sb)) - 1) : 0))
|
||||
|
||||
#endif /* PPCDISASM_H */
|
||||
|
|
|
@ -22,22 +22,22 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef PPCEMU_H
|
||||
#define PPCEMU_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
#include <setjmp.h>
|
||||
#include "endianswap.h"
|
||||
#include "devices/memctrlbase.h"
|
||||
#include "endianswap.h"
|
||||
#include <cinttypes>
|
||||
#include <setjmp.h>
|
||||
#include <string>
|
||||
|
||||
//Uncomment this to help debug the emulator further
|
||||
// Uncomment this to help debug the emulator further
|
||||
//#define EXHAUSTIVE_DEBUG 1
|
||||
|
||||
//Uncomment this to have a more graceful approach to illegal opcodes
|
||||
// Uncomment this to have a more graceful approach to illegal opcodes
|
||||
//#define ILLEGAL_OP_SAFE 1
|
||||
|
||||
//Uncomment this to use GCC built-in functions.
|
||||
// Uncomment this to use GCC built-in functions.
|
||||
//#define USE_GCC_BUILTINS 1
|
||||
|
||||
//Uncomment this to use Visual Studio built-in functions.
|
||||
// Uncomment this to use Visual Studio built-in functions.
|
||||
//#define USE_VS_BUILTINS 1
|
||||
|
||||
enum endian_switch { big_end = 0, little_end = 1 };
|
||||
|
@ -65,7 +65,7 @@ fpscr = FP Status and Condition Register
|
|||
|
||||
typedef struct struct_ppc_state {
|
||||
FPR_storage fpr[32];
|
||||
uint32_t pc; //Referred as the CIA in the PPC manual
|
||||
uint32_t pc; // Referred as the CIA in the PPC manual
|
||||
uint32_t gpr[32];
|
||||
uint32_t cr;
|
||||
uint32_t fpscr;
|
||||
|
@ -73,7 +73,7 @@ typedef struct struct_ppc_state {
|
|||
uint32_t spr[1024];
|
||||
uint32_t msr;
|
||||
uint32_t sr[16];
|
||||
bool reserve; //reserve bit used for lwarx and stcwx
|
||||
bool reserve; // reserve bit used for lwarx and stcwx
|
||||
} SetPRS;
|
||||
|
||||
extern SetPRS ppc_state;
|
||||
|
@ -94,10 +94,7 @@ enum SPR : int {
|
|||
};
|
||||
|
||||
/** symbolic names for frequently used SPRs */
|
||||
enum TBR : int {
|
||||
TBL = 0,
|
||||
TBU = 1
|
||||
};
|
||||
enum TBR : int { TBL = 0, TBU = 1 };
|
||||
|
||||
/** symbolic names for common PPC processors */
|
||||
enum PPC_VER : uint32_t {
|
||||
|
@ -147,10 +144,10 @@ SUPERVISOR MODEL
|
|||
536 - 543 are the Data BAT registers
|
||||
**/
|
||||
|
||||
extern uint32_t opcode_value; //used for interpreting opcodes
|
||||
extern uint64_t timebase_counter; //used for storing time base value
|
||||
extern uint32_t opcode_value; // used for interpreting opcodes
|
||||
extern uint64_t timebase_counter; // used for storing time base value
|
||||
|
||||
//Additional steps to prevent overflow?
|
||||
// Additional steps to prevent overflow?
|
||||
extern int32_t add_result;
|
||||
extern int32_t simult_result;
|
||||
extern uint32_t uiadd_result;
|
||||
|
@ -176,19 +173,19 @@ extern uint32_t rot_mb;
|
|||
extern uint32_t rot_me;
|
||||
extern uint32_t uimm;
|
||||
extern uint32_t grab_sr;
|
||||
extern uint32_t grab_inb; //This is for grabbing the number of immediate bytes for loading and storing
|
||||
extern uint32_t grab_inb; // This is for grabbing the number of immediate bytes for loading and storing
|
||||
extern uint32_t ppc_to;
|
||||
extern int32_t simm;
|
||||
extern int32_t adr_li;
|
||||
extern int32_t br_bd;
|
||||
|
||||
//Used for GP calcs
|
||||
// Used for GP calcs
|
||||
extern uint32_t ppc_result_a;
|
||||
extern uint32_t ppc_result_b;
|
||||
extern uint32_t ppc_result_c;
|
||||
extern uint32_t ppc_result_d;
|
||||
|
||||
//Used for FP calcs
|
||||
// Used for FP calcs
|
||||
extern uint64_t ppc_result64_a;
|
||||
extern uint64_t ppc_result64_b;
|
||||
extern uint64_t ppc_result64_c;
|
||||
|
@ -218,7 +215,7 @@ enum class Except_Type {
|
|||
EXC_TRACE = 13
|
||||
};
|
||||
|
||||
//extern bool bb_end;
|
||||
// extern bool bb_end;
|
||||
extern BB_end_kind bb_kind;
|
||||
|
||||
extern jmp_buf exc_env;
|
||||
|
@ -229,23 +226,23 @@ extern bool grab_return;
|
|||
|
||||
extern bool power_on;
|
||||
|
||||
extern bool is_601; //For PowerPC 601 Emulation
|
||||
extern bool is_gekko; //For GameCube Emulation
|
||||
extern bool is_altivec; //For Altivec Emulation
|
||||
extern bool is_64bit; //For PowerPC G5 Emulation
|
||||
extern bool is_601; // For PowerPC 601 Emulation
|
||||
extern bool is_gekko; // For GameCube Emulation
|
||||
extern bool is_altivec; // For Altivec Emulation
|
||||
extern bool is_64bit; // For PowerPC G5 Emulation
|
||||
|
||||
//Important Addressing Integers
|
||||
// Important Addressing Integers
|
||||
extern uint32_t ppc_cur_instruction;
|
||||
extern uint32_t ppc_effective_address;
|
||||
extern uint32_t ppc_next_instruction_address;
|
||||
|
||||
//Profiling Stats
|
||||
// Profiling Stats
|
||||
extern uint32_t mmu_translations_num;
|
||||
extern uint32_t exceptions_performed;
|
||||
extern uint32_t supervisor_inst_num;
|
||||
|
||||
//Function prototypes
|
||||
extern void ppc_cpu_init(MemCtrlBase *mem_ctrl, uint32_t proc_version);
|
||||
// Function prototypes
|
||||
extern void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t proc_version);
|
||||
extern void ppc_mmu_init();
|
||||
|
||||
void ppc_illegalop();
|
||||
|
@ -293,15 +290,13 @@ void ppc_fp_changecrf1();
|
|||
void ppc_tbr_update();
|
||||
|
||||
/* Exception handlers. */
|
||||
[[noreturn]] void ppc_exception_handler(Except_Type exception_type,
|
||||
uint32_t srr1_bits);
|
||||
[[noreturn]] void dbg_exception_handler(Except_Type exception_type,
|
||||
uint32_t srr1_bits);
|
||||
[[noreturn]] void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits);
|
||||
[[noreturn]] void dbg_exception_handler(Except_Type exception_type, uint32_t srr1_bits);
|
||||
|
||||
//MEMORY DECLARATIONS
|
||||
// MEMORY DECLARATIONS
|
||||
extern MemCtrlBase* mem_ctrl_instance;
|
||||
|
||||
//The functions used by the PowerPC processor
|
||||
// The functions used by the PowerPC processor
|
||||
extern void ppc_bcctr();
|
||||
extern void ppc_bcctrl();
|
||||
extern void ppc_bclr();
|
||||
|
@ -599,7 +594,7 @@ extern void ppc_fsqrtsdot();
|
|||
extern void ppc_fcmpo();
|
||||
extern void ppc_fcmpu();
|
||||
|
||||
//Power-specific instructions
|
||||
// Power-specific instructions
|
||||
extern void power_abs();
|
||||
extern void power_absdot();
|
||||
extern void power_abso();
|
||||
|
@ -667,17 +662,17 @@ extern void power_srlqdot();
|
|||
extern void power_srq();
|
||||
extern void power_srqdot();
|
||||
|
||||
//Gekko instructions
|
||||
// Gekko instructions
|
||||
extern void ppc_psq_l();
|
||||
extern void ppc_psq_lu();
|
||||
extern void ppc_psq_st();
|
||||
extern void ppc_psq_stu();
|
||||
|
||||
//AltiVec instructions
|
||||
// AltiVec instructions
|
||||
|
||||
//64-bit instructions
|
||||
// 64-bit instructions
|
||||
|
||||
//G5+ instructions
|
||||
// G5+ instructions
|
||||
|
||||
extern void ppc_main_opcode(void);
|
||||
extern void ppc_exec(void);
|
||||
|
@ -687,7 +682,7 @@ extern void ppc_exec_until(uint32_t goal_addr);
|
|||
/* debugging support API */
|
||||
void print_gprs(void); /* print content of the general purpose registers */
|
||||
void print_fprs(void); /* print content of the floating-point registers */
|
||||
uint64_t get_reg(std::string ®_name); /* get content of the register reg_name */
|
||||
void set_reg(std::string ®_name, uint64_t val); /* set reg_name to val */
|
||||
uint64_t get_reg(std::string& reg_name); /* get content of the register reg_name */
|
||||
void set_reg(std::string& reg_name, uint64_t val); /* set reg_name to val */
|
||||
|
||||
#endif /* PPCEMU_H */
|
||||
|
|
|
@ -21,23 +21,21 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
/** @file Handling of low-level PPC exceptions. */
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include "ppcemu.h"
|
||||
#include <setjmp.h>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
jmp_buf exc_env; /* Global exception environment. */
|
||||
|
||||
[[noreturn]] void ppc_exception_handler(Except_Type exception_type,
|
||||
uint32_t srr1_bits)
|
||||
{
|
||||
[[noreturn]] void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits) {
|
||||
grab_exception = true;
|
||||
#ifdef PROFILER
|
||||
#ifdef PROFILER
|
||||
exceptions_performed++;
|
||||
#endif
|
||||
#endif
|
||||
bb_kind = BB_end_kind::BB_EXCEPTION;
|
||||
|
||||
switch(exception_type) {
|
||||
switch (exception_type) {
|
||||
case Except_Type::EXC_SYSTEM_RESET:
|
||||
ppc_state.spr[SPR::SRR0] = ppc_state.pc & 0xFFFFFFFC;
|
||||
ppc_next_instruction_address = 0x0100;
|
||||
|
@ -97,16 +95,15 @@ jmp_buf exc_env; /* Global exception environment. */
|
|||
break;
|
||||
|
||||
default:
|
||||
//printf("Unknown exception occured: %X\n", exception_type);
|
||||
//exit(-1);
|
||||
// printf("Unknown exception occured: %X\n", exception_type);
|
||||
// exit(-1);
|
||||
break;
|
||||
}
|
||||
|
||||
ppc_state.spr[SPR::SRR1] = (ppc_state.msr & 0x0000FF73) | srr1_bits;
|
||||
ppc_state.msr &= 0xFFFB1041;
|
||||
/* copy MSR[ILE] to MSR[LE] */
|
||||
ppc_state.msr = (ppc_state.msr & 0xFFFFFFFE) |
|
||||
((ppc_state.msr >> 16) & 1);
|
||||
ppc_state.msr = (ppc_state.msr & 0xFFFFFFFE) | ((ppc_state.msr >> 16) & 1);
|
||||
|
||||
if (ppc_state.msr & 0x40) {
|
||||
ppc_next_instruction_address |= 0xFFF00000;
|
||||
|
@ -116,12 +113,10 @@ jmp_buf exc_env; /* Global exception environment. */
|
|||
}
|
||||
|
||||
|
||||
[[noreturn]] void dbg_exception_handler(Except_Type exception_type,
|
||||
uint32_t srr1_bits)
|
||||
{
|
||||
[[noreturn]] void dbg_exception_handler(Except_Type exception_type, uint32_t srr1_bits) {
|
||||
std::string exc_descriptor;
|
||||
|
||||
switch(exception_type) {
|
||||
switch (exception_type) {
|
||||
case Except_Type::EXC_SYSTEM_RESET:
|
||||
exc_descriptor = "System reset exception occured";
|
||||
break;
|
||||
|
|
|
@ -19,23 +19,23 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <setjmp.h>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include <unordered_map>
|
||||
#include <chrono>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "ppcemu.h"
|
||||
#include "ppcmmu.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
MemCtrlBase *mem_ctrl_instance = 0;
|
||||
MemCtrlBase* mem_ctrl_instance = 0;
|
||||
|
||||
bool power_on = 1;
|
||||
|
||||
|
@ -46,385 +46,358 @@ bool grab_exception;
|
|||
bool grab_return;
|
||||
bool grab_breakpoint;
|
||||
|
||||
uint32_t ppc_cur_instruction; //Current instruction for the PPC
|
||||
uint32_t ppc_cur_instruction; // Current instruction for the PPC
|
||||
uint32_t ppc_effective_address;
|
||||
uint32_t ppc_next_instruction_address; //Used for branching, setting up the NIA
|
||||
uint32_t ppc_next_instruction_address; // Used for branching, setting up the NIA
|
||||
|
||||
BB_end_kind bb_kind; /* basic block end */
|
||||
|
||||
uint64_t timebase_counter; /* internal timebase counter */
|
||||
|
||||
clock_t clock_test_begin; //Used to make sure the TBR does not increment so quickly.
|
||||
clock_t clock_test_begin; // Used to make sure the TBR does not increment so quickly.
|
||||
|
||||
/** Opcode lookup tables. */
|
||||
|
||||
/** Primary opcode (bits 0...5) lookup table. */
|
||||
static PPCOpcode OpcodeGrabber[] = {
|
||||
ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_twi, ppc_opcode4,
|
||||
ppc_illegalop, ppc_illegalop, ppc_mulli, ppc_subfic, power_dozi,
|
||||
ppc_cmpli, ppc_cmpi, ppc_addic, ppc_addicdot, ppc_addi,
|
||||
ppc_addis, ppc_opcode16, ppc_sc, ppc_opcode18, ppc_opcode19,
|
||||
ppc_rlwimi, ppc_rlwinm, power_rlmi, ppc_rlwnm, ppc_ori,
|
||||
ppc_oris, ppc_xori, ppc_xoris, ppc_andidot, ppc_andisdot,
|
||||
ppc_illegalop, ppc_opcode31, ppc_lwz, ppc_lwzu, ppc_lbz,
|
||||
ppc_lbzu, ppc_stw, ppc_stwu, ppc_stb, ppc_stbu,
|
||||
ppc_lhz, ppc_lhzu, ppc_lha, ppc_lhau, ppc_sth,
|
||||
ppc_sthu, ppc_lmw, ppc_stmw, ppc_lfs, ppc_lfsu,
|
||||
ppc_lfd, ppc_lfdu, ppc_stfs, ppc_stfsu, ppc_stfd,
|
||||
ppc_stfdu, ppc_psq_l, ppc_psq_lu, ppc_illegalop, ppc_illegalop,
|
||||
ppc_psq_st, ppc_psq_stu, ppc_illegalop, ppc_opcode63
|
||||
};
|
||||
ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_twi, ppc_opcode4, ppc_illegalop,
|
||||
ppc_illegalop, ppc_mulli, ppc_subfic, power_dozi, ppc_cmpli, ppc_cmpi,
|
||||
ppc_addic, ppc_addicdot, ppc_addi, ppc_addis, ppc_opcode16, ppc_sc,
|
||||
ppc_opcode18, ppc_opcode19, ppc_rlwimi, ppc_rlwinm, power_rlmi, ppc_rlwnm,
|
||||
ppc_ori, ppc_oris, ppc_xori, ppc_xoris, ppc_andidot, ppc_andisdot,
|
||||
ppc_illegalop, ppc_opcode31, ppc_lwz, ppc_lwzu, ppc_lbz, ppc_lbzu,
|
||||
ppc_stw, ppc_stwu, ppc_stb, ppc_stbu, ppc_lhz, ppc_lhzu,
|
||||
ppc_lha, ppc_lhau, ppc_sth, ppc_sthu, ppc_lmw, ppc_stmw,
|
||||
ppc_lfs, ppc_lfsu, ppc_lfd, ppc_lfdu, ppc_stfs, ppc_stfsu,
|
||||
ppc_stfd, ppc_stfdu, ppc_psq_l, ppc_psq_lu, ppc_illegalop, ppc_illegalop,
|
||||
ppc_psq_st, ppc_psq_stu, ppc_illegalop, ppc_opcode63};
|
||||
|
||||
/** Lookup tables for branch instructions. */
|
||||
static PPCOpcode SubOpcode16Grabber[] = {
|
||||
ppc_bc, ppc_bcl, ppc_bca, ppc_bcla
|
||||
};
|
||||
static PPCOpcode SubOpcode16Grabber[] = {ppc_bc, ppc_bcl, ppc_bca, ppc_bcla};
|
||||
|
||||
static PPCOpcode SubOpcode18Grabber[] = {
|
||||
ppc_b, ppc_bl, ppc_ba, ppc_bla
|
||||
};
|
||||
static PPCOpcode SubOpcode18Grabber[] = {ppc_b, ppc_bl, ppc_ba, ppc_bla};
|
||||
|
||||
/** General conditional register instructions decoding table. */
|
||||
static std::unordered_map<uint16_t, PPCOpcode> SubOpcode19Grabber = {
|
||||
{ 32, &ppc_bclr}, { 33, &ppc_bclrl}, { 66, &ppc_crnor}, {100, &ppc_rfi},
|
||||
{ 258, &ppc_crandc}, { 300, &ppc_isync}, {386, &ppc_crxor}, {450, &ppc_crnand},
|
||||
{ 514, &ppc_crand}, { 578, &ppc_creqv}, {834, &ppc_crorc}, {898, &ppc_cror},
|
||||
{1056, &ppc_bcctr}, {1057, &ppc_bcctrl}
|
||||
};
|
||||
{32, &ppc_bclr},
|
||||
{33, &ppc_bclrl},
|
||||
{66, &ppc_crnor},
|
||||
{100, &ppc_rfi},
|
||||
{258, &ppc_crandc},
|
||||
{300, &ppc_isync},
|
||||
{386, &ppc_crxor},
|
||||
{450, &ppc_crnand},
|
||||
{514, &ppc_crand},
|
||||
{578, &ppc_creqv},
|
||||
{834, &ppc_crorc},
|
||||
{898, &ppc_cror},
|
||||
{1056, &ppc_bcctr},
|
||||
{1057, &ppc_bcctrl}};
|
||||
|
||||
/** General integer instructions decoding table. */
|
||||
static std::unordered_map<uint16_t, PPCOpcode> SubOpcode31Grabber = {
|
||||
{ 0, &ppc_cmp}, { 8, &ppc_tw}, { 16, &ppc_subfc},
|
||||
{ 17, &ppc_subfcdot}, { 20, &ppc_addc}, { 21, &ppc_addcdot},
|
||||
{ 22, &ppc_mulhwu}, { 23, &ppc_mulhwudot}, { 38, &ppc_mfcr},
|
||||
{ 40, &ppc_lwarx}, { 46, &ppc_lwzx}, { 48, &ppc_slw},
|
||||
{ 49, &ppc_slwdot}, { 52, &ppc_cntlzw}, { 53, &ppc_cntlzwdot},
|
||||
{ 56, &ppc_and}, { 57, &ppc_anddot}, { 58, &power_maskg},
|
||||
{ 59, &power_maskgdot}, { 64, &ppc_cmpl}, { 80, &ppc_subf},
|
||||
{ 81, &ppc_subfdot}, { 108, &ppc_dcbst}, { 110, &ppc_lwzux},
|
||||
{ 120, &ppc_andc}, { 121, &ppc_andcdot}, { 150, &ppc_mulhw},
|
||||
{ 151, &ppc_mulhwdot}, { 166, &ppc_mfmsr}, { 172, &ppc_dcbf},
|
||||
{ 174, &ppc_lbzx}, { 208, &ppc_neg}, { 209, &ppc_negdot},
|
||||
{ 214, &power_mul}, { 215, &power_muldot}, { 238, &ppc_lbzux},
|
||||
{ 248, &ppc_nor}, { 249, &ppc_nordot}, { 272, &ppc_subfe},
|
||||
{ 273, &ppc_subfedot}, { 276, &ppc_adde}, { 277, &ppc_addedot},
|
||||
{ 288, &ppc_mtcrf}, { 292, &ppc_mtmsr}, { 301, &ppc_stwcx},
|
||||
{ 302, &ppc_stwx}, { 304, &power_slq}, { 305, &power_slqdot},
|
||||
{ 306, &power_sle}, { 307, &power_sledot}, { 366, &ppc_stwux},
|
||||
{ 368, &power_sliq}, { 400, &ppc_subfze}, { 401, &ppc_subfzedot},
|
||||
{ 404, &ppc_addze}, { 405, &ppc_addzedot}, { 420, &ppc_mtsr},
|
||||
{ 430, &ppc_stbx}, { 432, &power_sllq}, { 433, &power_sllqdot},
|
||||
{ 434, &power_sleq}, { 436, &power_sleqdot}, { 464, &ppc_subfme},
|
||||
{ 465, &ppc_subfmedot}, { 468, &ppc_addme}, { 469, &ppc_addmedot},
|
||||
{ 470, &ppc_mullw}, { 471, &ppc_mullwdot}, { 484, &ppc_mtsrin},
|
||||
{ 492, &ppc_dcbtst}, { 494, &ppc_stbux}, { 496, &power_slliq},
|
||||
{ 497, &power_slliqdot}, { 528, &power_doz}, { 529, &power_dozdot},
|
||||
{ 532, &ppc_add}, { 533, &ppc_adddot}, { 554, &power_lscbx},
|
||||
{ 555, &power_lscbxdot}, { 556, &ppc_dcbt}, { 558, &ppc_lhzx},
|
||||
{ 568, &ppc_eqv}, { 569, &ppc_eqvdot}, { 612, &ppc_tlbie},
|
||||
{ 622, &ppc_lhzux}, { 632, &ppc_xor}, { 633, &ppc_xordot},
|
||||
{ 662, &power_div}, { 663, &power_divdot}, { 678, &ppc_mfspr},
|
||||
{ 686, &ppc_lhax}, { 720, &power_abs}, { 721, &power_absdot},
|
||||
{ 726, &power_divs}, { 727, &power_divsdot}, { 740, &ppc_tlbia},
|
||||
{ 742, &ppc_mftb}, { 750, &ppc_lhaux}, { 814, &ppc_sthx},
|
||||
{ 824, &ppc_orc}, { 825, &ppc_orcdot}, { 878, &ppc_sthx},
|
||||
{ 888, &ppc_or}, { 889, &ppc_ordot}, { 918, &ppc_divwu},
|
||||
{ 919, &ppc_divwudot}, { 934, &ppc_mtspr}, { 940, &ppc_dcbi},
|
||||
{ 952, &ppc_nand}, { 953, &ppc_nanddot}, { 976, &power_nabs},
|
||||
{ 977, &power_nabsdot}, { 982, &ppc_divw}, { 983, &ppc_divwdot},
|
||||
{1024, &ppc_mcrxr}, {1040, &ppc_subfco}, {1041, &ppc_subfcodot},
|
||||
{1044, &ppc_addco}, {1045, &ppc_addcodot}, {1062, &power_clcs},
|
||||
{1063, &power_clcsdot}, {1066, &ppc_lswx}, {1068, &ppc_lwbrx},
|
||||
{1070, &ppc_lfsx}, {1072, &ppc_srw}, {1073, &ppc_srwdot},
|
||||
{1074, &power_rrib}, {1075, &power_rribdot}, {1082, &power_maskir},
|
||||
{1083, &power_maskirdot}, {1104, &ppc_subfo}, {1105, &ppc_subfodot},
|
||||
{1132, &ppc_tlbsync}, {1134, &ppc_lfsux}, {1190, &ppc_mfsr},
|
||||
{1194, &ppc_lswi}, {1196, &ppc_sync}, {1198, &ppc_lfdx},
|
||||
{1232, &ppc_nego}, {1233, &ppc_negodot}, {1238, &power_mulo},
|
||||
{1239, &power_mulodot}, {1262, &ppc_lfdux}, {1296, &ppc_subfeo},
|
||||
{1297, &ppc_subfeodot}, {1300, &ppc_addeo}, {1301, &ppc_addeodot},
|
||||
{1318, &ppc_mfsrin}, {1322, &ppc_stswx}, {1324, &ppc_stwbrx},
|
||||
{1326, &ppc_stfsx}, {1328, &power_srq}, {1329, &power_srqdot},
|
||||
{1330, &power_sre}, {1331, &power_sredot}, {1390, &ppc_stfsux},
|
||||
{1392, &power_sriq}, {1393, &power_sriqdot}, {1424, &ppc_subfzeo},
|
||||
{1425, &ppc_subfzeodot}, {1428, &ppc_addzeo}, {1429, &ppc_addzeodot},
|
||||
{1450, &ppc_stswi}, {1454, &ppc_stfdx}, {1456, &power_srlq},
|
||||
{1457, &power_srlqdot}, {1458, &power_sreq}, {1459, &power_sreqdot},
|
||||
{1488, &ppc_subfmeo}, {1489, &ppc_subfmeodot}, {1492, &ppc_addmeo},
|
||||
{1493, &ppc_addmeodot}, {1494, &ppc_mullwo}, {1495, &ppc_mullwodot},
|
||||
{1518, &ppc_stfdux}, {1520, &power_srliq}, {1521, &power_srliqdot},
|
||||
{1552, &power_dozo}, {1553, &power_dozodot}, {1556, &ppc_addo},
|
||||
{1557, &ppc_addodot}, {1580, &ppc_lhbrx}, {1584, &ppc_sraw},
|
||||
{1585, &ppc_srawdot}, {1648, &ppc_srawi}, {1649, &ppc_srawidot},
|
||||
{1686, &power_divo}, {1687, &power_divodot}, {1708, &ppc_eieio},
|
||||
{1744, &power_abso}, {1745, &power_absodot}, {1750, &power_divso},
|
||||
{1751, &power_divsodot}, {1836, &ppc_sthbrx}, {1840, &power_sraq},
|
||||
{1841, &power_sraqdot}, {1842, &power_srea}, {1843, &power_sreadot},
|
||||
{1844, &ppc_extsh}, {1845, &ppc_extshdot}, {1904, &power_sraiq},
|
||||
{1905, &power_sraiqdot}, {1908, &ppc_extsb}, {1909, &ppc_extsbdot},
|
||||
{1942, &ppc_divwuo}, {1943, &ppc_divwuodot}, {1956, &ppc_tlbld},
|
||||
{1964, &ppc_icbi}, {1966, &ppc_stfiwx}, {2000, &power_nabso},
|
||||
{2001, &power_nabsodot}, {2006, &ppc_divwo}, {2007, &ppc_divwodot},
|
||||
{2020, &ppc_tlbli}, {2028, &ppc_dcbz}
|
||||
};
|
||||
{0, &ppc_cmp}, {8, &ppc_tw},
|
||||
{16, &ppc_subfc}, {17, &ppc_subfcdot},
|
||||
{20, &ppc_addc}, {21, &ppc_addcdot},
|
||||
{22, &ppc_mulhwu}, {23, &ppc_mulhwudot},
|
||||
{38, &ppc_mfcr}, {40, &ppc_lwarx},
|
||||
{46, &ppc_lwzx}, {48, &ppc_slw},
|
||||
{49, &ppc_slwdot}, {52, &ppc_cntlzw},
|
||||
{53, &ppc_cntlzwdot}, {56, &ppc_and},
|
||||
{57, &ppc_anddot}, {58, &power_maskg},
|
||||
{59, &power_maskgdot}, {64, &ppc_cmpl},
|
||||
{80, &ppc_subf}, {81, &ppc_subfdot},
|
||||
{108, &ppc_dcbst}, {110, &ppc_lwzux},
|
||||
{120, &ppc_andc}, {121, &ppc_andcdot},
|
||||
{150, &ppc_mulhw}, {151, &ppc_mulhwdot},
|
||||
{166, &ppc_mfmsr}, {172, &ppc_dcbf},
|
||||
{174, &ppc_lbzx}, {208, &ppc_neg},
|
||||
{209, &ppc_negdot}, {214, &power_mul},
|
||||
{215, &power_muldot}, {238, &ppc_lbzux},
|
||||
{248, &ppc_nor}, {249, &ppc_nordot},
|
||||
{272, &ppc_subfe}, {273, &ppc_subfedot},
|
||||
{276, &ppc_adde}, {277, &ppc_addedot},
|
||||
{288, &ppc_mtcrf}, {292, &ppc_mtmsr},
|
||||
{301, &ppc_stwcx}, {302, &ppc_stwx},
|
||||
{304, &power_slq}, {305, &power_slqdot},
|
||||
{306, &power_sle}, {307, &power_sledot},
|
||||
{366, &ppc_stwux}, {368, &power_sliq},
|
||||
{400, &ppc_subfze}, {401, &ppc_subfzedot},
|
||||
{404, &ppc_addze}, {405, &ppc_addzedot},
|
||||
{420, &ppc_mtsr}, {430, &ppc_stbx},
|
||||
{432, &power_sllq}, {433, &power_sllqdot},
|
||||
{434, &power_sleq}, {436, &power_sleqdot},
|
||||
{464, &ppc_subfme}, {465, &ppc_subfmedot},
|
||||
{468, &ppc_addme}, {469, &ppc_addmedot},
|
||||
{470, &ppc_mullw}, {471, &ppc_mullwdot},
|
||||
{484, &ppc_mtsrin}, {492, &ppc_dcbtst},
|
||||
{494, &ppc_stbux}, {496, &power_slliq},
|
||||
{497, &power_slliqdot}, {528, &power_doz},
|
||||
{529, &power_dozdot}, {532, &ppc_add},
|
||||
{533, &ppc_adddot}, {554, &power_lscbx},
|
||||
{555, &power_lscbxdot}, {556, &ppc_dcbt},
|
||||
{558, &ppc_lhzx}, {568, &ppc_eqv},
|
||||
{569, &ppc_eqvdot}, {612, &ppc_tlbie},
|
||||
{622, &ppc_lhzux}, {632, &ppc_xor},
|
||||
{633, &ppc_xordot}, {662, &power_div},
|
||||
{663, &power_divdot}, {678, &ppc_mfspr},
|
||||
{686, &ppc_lhax}, {720, &power_abs},
|
||||
{721, &power_absdot}, {726, &power_divs},
|
||||
{727, &power_divsdot}, {740, &ppc_tlbia},
|
||||
{742, &ppc_mftb}, {750, &ppc_lhaux},
|
||||
{814, &ppc_sthx}, {824, &ppc_orc},
|
||||
{825, &ppc_orcdot}, {878, &ppc_sthx},
|
||||
{888, &ppc_or}, {889, &ppc_ordot},
|
||||
{918, &ppc_divwu}, {919, &ppc_divwudot},
|
||||
{934, &ppc_mtspr}, {940, &ppc_dcbi},
|
||||
{952, &ppc_nand}, {953, &ppc_nanddot},
|
||||
{976, &power_nabs}, {977, &power_nabsdot},
|
||||
{982, &ppc_divw}, {983, &ppc_divwdot},
|
||||
{1024, &ppc_mcrxr}, {1040, &ppc_subfco},
|
||||
{1041, &ppc_subfcodot}, {1044, &ppc_addco},
|
||||
{1045, &ppc_addcodot}, {1062, &power_clcs},
|
||||
{1063, &power_clcsdot}, {1066, &ppc_lswx},
|
||||
{1068, &ppc_lwbrx}, {1070, &ppc_lfsx},
|
||||
{1072, &ppc_srw}, {1073, &ppc_srwdot},
|
||||
{1074, &power_rrib}, {1075, &power_rribdot},
|
||||
{1082, &power_maskir}, {1083, &power_maskirdot},
|
||||
{1104, &ppc_subfo}, {1105, &ppc_subfodot},
|
||||
{1132, &ppc_tlbsync}, {1134, &ppc_lfsux},
|
||||
{1190, &ppc_mfsr}, {1194, &ppc_lswi},
|
||||
{1196, &ppc_sync}, {1198, &ppc_lfdx},
|
||||
{1232, &ppc_nego}, {1233, &ppc_negodot},
|
||||
{1238, &power_mulo}, {1239, &power_mulodot},
|
||||
{1262, &ppc_lfdux}, {1296, &ppc_subfeo},
|
||||
{1297, &ppc_subfeodot}, {1300, &ppc_addeo},
|
||||
{1301, &ppc_addeodot}, {1318, &ppc_mfsrin},
|
||||
{1322, &ppc_stswx}, {1324, &ppc_stwbrx},
|
||||
{1326, &ppc_stfsx}, {1328, &power_srq},
|
||||
{1329, &power_srqdot}, {1330, &power_sre},
|
||||
{1331, &power_sredot}, {1390, &ppc_stfsux},
|
||||
{1392, &power_sriq}, {1393, &power_sriqdot},
|
||||
{1424, &ppc_subfzeo}, {1425, &ppc_subfzeodot},
|
||||
{1428, &ppc_addzeo}, {1429, &ppc_addzeodot},
|
||||
{1450, &ppc_stswi}, {1454, &ppc_stfdx},
|
||||
{1456, &power_srlq}, {1457, &power_srlqdot},
|
||||
{1458, &power_sreq}, {1459, &power_sreqdot},
|
||||
{1488, &ppc_subfmeo}, {1489, &ppc_subfmeodot},
|
||||
{1492, &ppc_addmeo}, {1493, &ppc_addmeodot},
|
||||
{1494, &ppc_mullwo}, {1495, &ppc_mullwodot},
|
||||
{1518, &ppc_stfdux}, {1520, &power_srliq},
|
||||
{1521, &power_srliqdot}, {1552, &power_dozo},
|
||||
{1553, &power_dozodot}, {1556, &ppc_addo},
|
||||
{1557, &ppc_addodot}, {1580, &ppc_lhbrx},
|
||||
{1584, &ppc_sraw}, {1585, &ppc_srawdot},
|
||||
{1648, &ppc_srawi}, {1649, &ppc_srawidot},
|
||||
{1686, &power_divo}, {1687, &power_divodot},
|
||||
{1708, &ppc_eieio}, {1744, &power_abso},
|
||||
{1745, &power_absodot}, {1750, &power_divso},
|
||||
{1751, &power_divsodot}, {1836, &ppc_sthbrx},
|
||||
{1840, &power_sraq}, {1841, &power_sraqdot},
|
||||
{1842, &power_srea}, {1843, &power_sreadot},
|
||||
{1844, &ppc_extsh}, {1845, &ppc_extshdot},
|
||||
{1904, &power_sraiq}, {1905, &power_sraiqdot},
|
||||
{1908, &ppc_extsb}, {1909, &ppc_extsbdot},
|
||||
{1942, &ppc_divwuo}, {1943, &ppc_divwuodot},
|
||||
{1956, &ppc_tlbld}, {1964, &ppc_icbi},
|
||||
{1966, &ppc_stfiwx}, {2000, &power_nabso},
|
||||
{2001, &power_nabsodot}, {2006, &ppc_divwo},
|
||||
{2007, &ppc_divwodot}, {2020, &ppc_tlbli},
|
||||
{2028, &ppc_dcbz}};
|
||||
|
||||
/** Single-precision floating-point instructions decoding table. */
|
||||
static std::unordered_map<uint16_t, PPCOpcode> SubOpcode59Grabber = {
|
||||
{ 36, &ppc_fdivs}, { 37, &ppc_fdivsdot}, { 40, &ppc_fsubs},
|
||||
{ 41, &ppc_fsubsdot}, { 42, &ppc_fadds}, { 43, &ppc_faddsdot},
|
||||
{ 44, &ppc_fsqrts}, { 45, &ppc_fsqrtsdot}, { 48, &ppc_fres},
|
||||
{ 49, &ppc_fresdot}, { 50, &ppc_fmults}, { 51, &ppc_fmultsdot},
|
||||
{ 56, &ppc_fmsubs}, { 57, &ppc_fmsubsdot}, { 58, &ppc_fmadds},
|
||||
{ 59, &ppc_fmaddsdot}, { 60, &ppc_fnmsubs}, { 61, &ppc_fnmsubsdot},
|
||||
{ 62, &ppc_fnmadds}, { 63, &ppc_fnmaddsdot}, { 114, &ppc_fmults},
|
||||
{ 115, &ppc_fmultsdot}, { 120, &ppc_fmsubs}, { 121, &ppc_fmsubsdot},
|
||||
{ 122, &ppc_fmadds}, { 123, &ppc_fmadds}, { 124, &ppc_fnmsubs},
|
||||
{ 125, &ppc_fnmsubsdot}, { 126, &ppc_fnmadds}, { 127, &ppc_fnmaddsdot},
|
||||
{ 178, &ppc_fmults}, { 179, &ppc_fmultsdot}, { 184, &ppc_fmsubs},
|
||||
{ 185, &ppc_fmsubsdot}, { 186, &ppc_fmadds}, { 187, &ppc_fmaddsdot},
|
||||
{ 188, &ppc_fnmsubs}, { 189, &ppc_fnmsubsdot}, { 190, &ppc_fnmadds},
|
||||
{ 191, &ppc_fnmaddsdot}, { 242, &ppc_fmults}, { 243, &ppc_fmultsdot},
|
||||
{ 248, &ppc_fmsubs}, { 249, &ppc_fmsubsdot}, { 250, &ppc_fmadds},
|
||||
{ 251, &ppc_fmaddsdot}, { 252, &ppc_fnmsubs}, { 253, &ppc_fnmsubsdot},
|
||||
{ 254, &ppc_fnmadds}, { 255, &ppc_fnmaddsdot}, { 306, &ppc_fmults},
|
||||
{ 307, &ppc_fmultsdot}, { 312, &ppc_fmsubs}, { 313, &ppc_fmsubsdot},
|
||||
{ 314, &ppc_fmadds}, { 315, &ppc_fmaddsdot}, { 316, &ppc_fnmsubs},
|
||||
{ 317, &ppc_fnmsubsdot}, { 318, &ppc_fnmadds}, { 319, &ppc_fnmaddsdot},
|
||||
{ 370, &ppc_fmults}, { 371, &ppc_fmultsdot}, { 376, &ppc_fmsubs},
|
||||
{ 377, &ppc_fmsubsdot}, { 378, &ppc_fmadds}, { 379, &ppc_fmaddsdot},
|
||||
{ 380, &ppc_fnmsubs}, { 381, &ppc_fnmsubsdot}, { 382, &ppc_fnmadds},
|
||||
{ 383, &ppc_fnmaddsdot}, { 434, &ppc_fmults}, { 435, &ppc_fmultsdot},
|
||||
{ 440, &ppc_fmsubs}, { 441, &ppc_fmsubsdot}, { 442, &ppc_fmadds},
|
||||
{ 443, &ppc_fmaddsdot}, { 444, &ppc_fnmsubs}, { 445, &ppc_fnmsubsdot},
|
||||
{ 446, &ppc_fnmadds}, { 447, &ppc_fnmaddsdot}, { 498, &ppc_fmults},
|
||||
{ 499, &ppc_fmultsdot}, { 504, &ppc_fmsubs}, { 505, &ppc_fmsubsdot},
|
||||
{ 506, &ppc_fmadds}, { 507, &ppc_fmaddsdot}, { 508, &ppc_fnmsubs},
|
||||
{ 509, &ppc_fnmsubsdot}, { 510, &ppc_fnmadds}, { 511, &ppc_fnmaddsdot},
|
||||
{ 562, &ppc_fmults}, { 563, &ppc_fmultsdot}, { 568, &ppc_fmsubs},
|
||||
{ 569, &ppc_fmsubsdot}, { 570, &ppc_fmadds}, { 571, &ppc_fmaddsdot},
|
||||
{ 572, &ppc_fnmsubs}, { 573, &ppc_fnmsubsdot}, { 574, &ppc_fnmadds},
|
||||
{ 575, &ppc_fnmaddsdot}, { 626, &ppc_fmults}, { 627, &ppc_fmultsdot},
|
||||
{ 632, &ppc_fmsubs}, { 633, &ppc_fmsubsdot}, { 634, &ppc_fmadds},
|
||||
{ 635, &ppc_fmaddsdot}, { 636, &ppc_fnmsubs}, { 637, &ppc_fnmsubsdot},
|
||||
{ 638, &ppc_fnmadds}, { 639, &ppc_fnmaddsdot}, { 690, &ppc_fmults},
|
||||
{ 691, &ppc_fmultsdot}, { 696, &ppc_fmsubs}, { 697, &ppc_fmsubsdot},
|
||||
{ 698, &ppc_fmadds}, { 699, &ppc_fmaddsdot}, { 700, &ppc_fnmsubs},
|
||||
{ 701, &ppc_fnmsubsdot}, { 702, &ppc_fnmadds}, { 703, &ppc_fnmaddsdot},
|
||||
{ 754, &ppc_fmults}, { 755, &ppc_fmultsdot}, { 760, &ppc_fmsubs},
|
||||
{ 761, &ppc_fmsubsdot}, { 762, &ppc_fmadds}, { 763, &ppc_fmaddsdot},
|
||||
{ 764, &ppc_fnmsubs}, { 765, &ppc_fnmsubsdot}, { 766, &ppc_fnmadds},
|
||||
{ 767, &ppc_fnmaddsdot}, { 818, &ppc_fmults}, { 819, &ppc_fmultsdot},
|
||||
{ 824, &ppc_fmsubs}, { 825, &ppc_fmsubsdot}, { 826, &ppc_fmadds},
|
||||
{ 827, &ppc_fmaddsdot}, { 828, &ppc_fnmsubs}, { 829, &ppc_fnmsubsdot},
|
||||
{ 830, &ppc_fnmadds}, { 831, &ppc_fnmaddsdot}, { 882, &ppc_fmults},
|
||||
{ 883, &ppc_fmultsdot}, { 888, &ppc_fmsubs}, { 889, &ppc_fmsubsdot},
|
||||
{ 890, &ppc_fmadds}, { 891, &ppc_fmaddsdot}, { 892, &ppc_fnmsubs},
|
||||
{ 893, &ppc_fnmsubsdot}, { 894, &ppc_fnmadds}, { 895, &ppc_fnmaddsdot},
|
||||
{ 946, &ppc_fmults}, { 947, &ppc_fmultsdot}, { 952, &ppc_fmsubs},
|
||||
{ 953, &ppc_fmsubsdot}, { 954, &ppc_fmadds}, { 955, &ppc_fmaddsdot},
|
||||
{ 957, &ppc_fnmsubs}, { 958, &ppc_fnmsubsdot}, { 958, &ppc_fnmadds},
|
||||
{ 959, &ppc_fnmaddsdot}, {1010, &ppc_fmults}, {1011, &ppc_fmultsdot},
|
||||
{1016, &ppc_fmsubs}, {1017, &ppc_fmsubsdot}, {1018, &ppc_fmadds},
|
||||
{1019, &ppc_fmaddsdot}, {1020, &ppc_fnmsubs}, {1021, &ppc_fnmsubsdot},
|
||||
{1022, &ppc_fnmadds}, {1023, &ppc_fnmaddsdot}, {1074, &ppc_fmults},
|
||||
{1075, &ppc_fmultsdot}, {1080, &ppc_fmsubs}, {1081, &ppc_fmsubsdot},
|
||||
{1082, &ppc_fmadds}, {1083, &ppc_fmaddsdot}, {1084, &ppc_fnmsubs},
|
||||
{1085, &ppc_fnmsubsdot}, {1086, &ppc_fnmadds}, {1087, &ppc_fnmaddsdot},
|
||||
{1138, &ppc_fmults}, {1139, &ppc_fmultsdot}, {1144, &ppc_fmsubs},
|
||||
{1145, &ppc_fmsubsdot}, {1146, &ppc_fmadds}, {1147, &ppc_fmaddsdot},
|
||||
{1148, &ppc_fnmsubs}, {1149, &ppc_fnmsubsdot}, {1150, &ppc_fnmadds},
|
||||
{1151, &ppc_fnmaddsdot}, {1202, &ppc_fmults}, {1203, &ppc_fmultsdot},
|
||||
{1208, &ppc_fmsubs}, {1209, &ppc_fmsubsdot}, {1210, &ppc_fmadds},
|
||||
{1211, &ppc_fmaddsdot}, {1212, &ppc_fnmsubs}, {1213, &ppc_fnmsubsdot},
|
||||
{1214, &ppc_fnmadds}, {1215, &ppc_fnmaddsdot}, {1266, &ppc_fmults},
|
||||
{1267, &ppc_fmultsdot}, {1272, &ppc_fmsubs}, {1273, &ppc_fmsubsdot},
|
||||
{1274, &ppc_fmadds}, {1275, &ppc_fmaddsdot}, {1276, &ppc_fnmsubs},
|
||||
{1277, &ppc_fnmsubsdot}, {1278, &ppc_fnmadds}, {1279, &ppc_fnmaddsdot},
|
||||
{1330, &ppc_fmults}, {1331, &ppc_fmultsdot}, {1336, &ppc_fmsubs},
|
||||
{1337, &ppc_fmsubsdot}, {1338, &ppc_fmadds}, {1339, &ppc_fmaddsdot},
|
||||
{1340, &ppc_fnmsubs}, {1341, &ppc_fnmsubsdot}, {1342, &ppc_fnmadds},
|
||||
{1343, &ppc_fnmaddsdot}, {1394, &ppc_fmults}, {1395, &ppc_fmultsdot},
|
||||
{1400, &ppc_fmsubs}, {1401, &ppc_fmsubsdot}, {1402, &ppc_fmadds},
|
||||
{1403, &ppc_fmaddsdot}, {1404, &ppc_fnmsubs}, {1405, &ppc_fnmsubsdot},
|
||||
{1406, &ppc_fnmadds}, {1407, &ppc_fnmaddsdot}, {1458, &ppc_fmults},
|
||||
{1459, &ppc_fmultsdot}, {1464, &ppc_fmsubs}, {1465, &ppc_fmsubsdot},
|
||||
{1466, &ppc_fmadds}, {1467, &ppc_fmaddsdot}, {1468, &ppc_fnmsubs},
|
||||
{1469, &ppc_fnmsubsdot}, {1470, &ppc_fnmadds}, {1471, &ppc_fnmaddsdot},
|
||||
{1522, &ppc_fmults}, {1523, &ppc_fmultsdot}, {1528, &ppc_fmsubs},
|
||||
{1529, &ppc_fmsubsdot}, {1530, &ppc_fmadds}, {1531, &ppc_fmaddsdot},
|
||||
{1532, &ppc_fnmsubs}, {1533, &ppc_fnmsubsdot}, {1534, &ppc_fnmadds},
|
||||
{1535, &ppc_fnmaddsdot}, {1586, &ppc_fmults}, {1587, &ppc_fmultsdot},
|
||||
{1592, &ppc_fmsubs}, {1593, &ppc_fmsubsdot}, {1594, &ppc_fmadds},
|
||||
{1595, &ppc_fmaddsdot}, {1596, &ppc_fnmsubs}, {1597, &ppc_fnmsubsdot},
|
||||
{1598, &ppc_fnmadds}, {1599, &ppc_fnmaddsdot}, {1650, &ppc_fmults},
|
||||
{1651, &ppc_fmultsdot}, {1656, &ppc_fmsubs}, {1657, &ppc_fmsubsdot},
|
||||
{1658, &ppc_fmadds}, {1659, &ppc_fmaddsdot}, {1660, &ppc_fnmsubs},
|
||||
{1661, &ppc_fnmsubsdot}, {1662, &ppc_fnmadds}, {1663, &ppc_fnmaddsdot},
|
||||
{1714, &ppc_fmults}, {1715, &ppc_fmultsdot}, {1720, &ppc_fmsubs},
|
||||
{1721, &ppc_fmsubsdot}, {1722, &ppc_fmadds}, {1723, &ppc_fmaddsdot},
|
||||
{1724, &ppc_fnmsubs}, {1725, &ppc_fnmsubsdot}, {1726, &ppc_fnmadds},
|
||||
{1727, &ppc_fnmaddsdot}, {1778, &ppc_fmults}, {1779, &ppc_fmultsdot},
|
||||
{1784, &ppc_fmsubs}, {1785, &ppc_fmsubsdot}, {1786, &ppc_fmadds},
|
||||
{1787, &ppc_fmaddsdot}, {1788, &ppc_fnmsubs}, {1789, &ppc_fnmsubsdot},
|
||||
{1790, &ppc_fnmadds}, {1791, &ppc_fnmaddsdot}, {1842, &ppc_fmults},
|
||||
{1843, &ppc_fmultsdot}, {1848, &ppc_fmsubs}, {1849, &ppc_fmsubsdot},
|
||||
{1850, &ppc_fmadds}, {1851, &ppc_fmaddsdot}, {1852, &ppc_fnmsubs},
|
||||
{1853, &ppc_fnmsubsdot}, {1854, &ppc_fnmadds}, {1855, &ppc_fnmaddsdot},
|
||||
{1906, &ppc_fmults}, {1907, &ppc_fmultsdot}, {1912, &ppc_fmsubs},
|
||||
{1913, &ppc_fmsubsdot}, {1914, &ppc_fmadds}, {1915, &ppc_fmaddsdot},
|
||||
{1916, &ppc_fnmsubs}, {1917, &ppc_fnmsubsdot}, {1918, &ppc_fnmadds},
|
||||
{1919, &ppc_fnmaddsdot}, {1970, &ppc_fmults}, {1971, &ppc_fmultsdot},
|
||||
{1976, &ppc_fmsubs}, {1977, &ppc_fmsubsdot}, {1978, &ppc_fmadds},
|
||||
{1979, &ppc_fmaddsdot}, {1980, &ppc_fnmsubs}, {1981, &ppc_fnmsubsdot},
|
||||
{1982, &ppc_fnmadds}, {1983, &ppc_fnmaddsdot}, {2034, &ppc_fmults},
|
||||
{2035, &ppc_fmultsdot}, {2040, &ppc_fmsubs}, {2041, &ppc_fmsubsdot},
|
||||
{2042, &ppc_fmadds}, {2043, &ppc_fmaddsdot}, {2044, &ppc_fnmsubs},
|
||||
{2045, &ppc_fnmsubsdot}, {2046, &ppc_fnmadds}, {2047, &ppc_fnmaddsdot}
|
||||
};
|
||||
{36, &ppc_fdivs}, {37, &ppc_fdivsdot}, {40, &ppc_fsubs}, {41, &ppc_fsubsdot},
|
||||
{42, &ppc_fadds}, {43, &ppc_faddsdot}, {44, &ppc_fsqrts}, {45, &ppc_fsqrtsdot},
|
||||
{48, &ppc_fres}, {49, &ppc_fresdot}, {50, &ppc_fmults}, {51, &ppc_fmultsdot},
|
||||
{56, &ppc_fmsubs}, {57, &ppc_fmsubsdot}, {58, &ppc_fmadds}, {59, &ppc_fmaddsdot},
|
||||
{60, &ppc_fnmsubs}, {61, &ppc_fnmsubsdot}, {62, &ppc_fnmadds}, {63, &ppc_fnmaddsdot},
|
||||
{114, &ppc_fmults}, {115, &ppc_fmultsdot}, {120, &ppc_fmsubs}, {121, &ppc_fmsubsdot},
|
||||
{122, &ppc_fmadds}, {123, &ppc_fmadds}, {124, &ppc_fnmsubs}, {125, &ppc_fnmsubsdot},
|
||||
{126, &ppc_fnmadds}, {127, &ppc_fnmaddsdot}, {178, &ppc_fmults}, {179, &ppc_fmultsdot},
|
||||
{184, &ppc_fmsubs}, {185, &ppc_fmsubsdot}, {186, &ppc_fmadds}, {187, &ppc_fmaddsdot},
|
||||
{188, &ppc_fnmsubs}, {189, &ppc_fnmsubsdot}, {190, &ppc_fnmadds}, {191, &ppc_fnmaddsdot},
|
||||
{242, &ppc_fmults}, {243, &ppc_fmultsdot}, {248, &ppc_fmsubs}, {249, &ppc_fmsubsdot},
|
||||
{250, &ppc_fmadds}, {251, &ppc_fmaddsdot}, {252, &ppc_fnmsubs}, {253, &ppc_fnmsubsdot},
|
||||
{254, &ppc_fnmadds}, {255, &ppc_fnmaddsdot}, {306, &ppc_fmults}, {307, &ppc_fmultsdot},
|
||||
{312, &ppc_fmsubs}, {313, &ppc_fmsubsdot}, {314, &ppc_fmadds}, {315, &ppc_fmaddsdot},
|
||||
{316, &ppc_fnmsubs}, {317, &ppc_fnmsubsdot}, {318, &ppc_fnmadds}, {319, &ppc_fnmaddsdot},
|
||||
{370, &ppc_fmults}, {371, &ppc_fmultsdot}, {376, &ppc_fmsubs}, {377, &ppc_fmsubsdot},
|
||||
{378, &ppc_fmadds}, {379, &ppc_fmaddsdot}, {380, &ppc_fnmsubs}, {381, &ppc_fnmsubsdot},
|
||||
{382, &ppc_fnmadds}, {383, &ppc_fnmaddsdot}, {434, &ppc_fmults}, {435, &ppc_fmultsdot},
|
||||
{440, &ppc_fmsubs}, {441, &ppc_fmsubsdot}, {442, &ppc_fmadds}, {443, &ppc_fmaddsdot},
|
||||
{444, &ppc_fnmsubs}, {445, &ppc_fnmsubsdot}, {446, &ppc_fnmadds}, {447, &ppc_fnmaddsdot},
|
||||
{498, &ppc_fmults}, {499, &ppc_fmultsdot}, {504, &ppc_fmsubs}, {505, &ppc_fmsubsdot},
|
||||
{506, &ppc_fmadds}, {507, &ppc_fmaddsdot}, {508, &ppc_fnmsubs}, {509, &ppc_fnmsubsdot},
|
||||
{510, &ppc_fnmadds}, {511, &ppc_fnmaddsdot}, {562, &ppc_fmults}, {563, &ppc_fmultsdot},
|
||||
{568, &ppc_fmsubs}, {569, &ppc_fmsubsdot}, {570, &ppc_fmadds}, {571, &ppc_fmaddsdot},
|
||||
{572, &ppc_fnmsubs}, {573, &ppc_fnmsubsdot}, {574, &ppc_fnmadds}, {575, &ppc_fnmaddsdot},
|
||||
{626, &ppc_fmults}, {627, &ppc_fmultsdot}, {632, &ppc_fmsubs}, {633, &ppc_fmsubsdot},
|
||||
{634, &ppc_fmadds}, {635, &ppc_fmaddsdot}, {636, &ppc_fnmsubs}, {637, &ppc_fnmsubsdot},
|
||||
{638, &ppc_fnmadds}, {639, &ppc_fnmaddsdot}, {690, &ppc_fmults}, {691, &ppc_fmultsdot},
|
||||
{696, &ppc_fmsubs}, {697, &ppc_fmsubsdot}, {698, &ppc_fmadds}, {699, &ppc_fmaddsdot},
|
||||
{700, &ppc_fnmsubs}, {701, &ppc_fnmsubsdot}, {702, &ppc_fnmadds}, {703, &ppc_fnmaddsdot},
|
||||
{754, &ppc_fmults}, {755, &ppc_fmultsdot}, {760, &ppc_fmsubs}, {761, &ppc_fmsubsdot},
|
||||
{762, &ppc_fmadds}, {763, &ppc_fmaddsdot}, {764, &ppc_fnmsubs}, {765, &ppc_fnmsubsdot},
|
||||
{766, &ppc_fnmadds}, {767, &ppc_fnmaddsdot}, {818, &ppc_fmults}, {819, &ppc_fmultsdot},
|
||||
{824, &ppc_fmsubs}, {825, &ppc_fmsubsdot}, {826, &ppc_fmadds}, {827, &ppc_fmaddsdot},
|
||||
{828, &ppc_fnmsubs}, {829, &ppc_fnmsubsdot}, {830, &ppc_fnmadds}, {831, &ppc_fnmaddsdot},
|
||||
{882, &ppc_fmults}, {883, &ppc_fmultsdot}, {888, &ppc_fmsubs}, {889, &ppc_fmsubsdot},
|
||||
{890, &ppc_fmadds}, {891, &ppc_fmaddsdot}, {892, &ppc_fnmsubs}, {893, &ppc_fnmsubsdot},
|
||||
{894, &ppc_fnmadds}, {895, &ppc_fnmaddsdot}, {946, &ppc_fmults}, {947, &ppc_fmultsdot},
|
||||
{952, &ppc_fmsubs}, {953, &ppc_fmsubsdot}, {954, &ppc_fmadds}, {955, &ppc_fmaddsdot},
|
||||
{957, &ppc_fnmsubs}, {958, &ppc_fnmsubsdot}, {958, &ppc_fnmadds}, {959, &ppc_fnmaddsdot},
|
||||
{1010, &ppc_fmults}, {1011, &ppc_fmultsdot}, {1016, &ppc_fmsubs}, {1017, &ppc_fmsubsdot},
|
||||
{1018, &ppc_fmadds}, {1019, &ppc_fmaddsdot}, {1020, &ppc_fnmsubs}, {1021, &ppc_fnmsubsdot},
|
||||
{1022, &ppc_fnmadds}, {1023, &ppc_fnmaddsdot}, {1074, &ppc_fmults}, {1075, &ppc_fmultsdot},
|
||||
{1080, &ppc_fmsubs}, {1081, &ppc_fmsubsdot}, {1082, &ppc_fmadds}, {1083, &ppc_fmaddsdot},
|
||||
{1084, &ppc_fnmsubs}, {1085, &ppc_fnmsubsdot}, {1086, &ppc_fnmadds}, {1087, &ppc_fnmaddsdot},
|
||||
{1138, &ppc_fmults}, {1139, &ppc_fmultsdot}, {1144, &ppc_fmsubs}, {1145, &ppc_fmsubsdot},
|
||||
{1146, &ppc_fmadds}, {1147, &ppc_fmaddsdot}, {1148, &ppc_fnmsubs}, {1149, &ppc_fnmsubsdot},
|
||||
{1150, &ppc_fnmadds}, {1151, &ppc_fnmaddsdot}, {1202, &ppc_fmults}, {1203, &ppc_fmultsdot},
|
||||
{1208, &ppc_fmsubs}, {1209, &ppc_fmsubsdot}, {1210, &ppc_fmadds}, {1211, &ppc_fmaddsdot},
|
||||
{1212, &ppc_fnmsubs}, {1213, &ppc_fnmsubsdot}, {1214, &ppc_fnmadds}, {1215, &ppc_fnmaddsdot},
|
||||
{1266, &ppc_fmults}, {1267, &ppc_fmultsdot}, {1272, &ppc_fmsubs}, {1273, &ppc_fmsubsdot},
|
||||
{1274, &ppc_fmadds}, {1275, &ppc_fmaddsdot}, {1276, &ppc_fnmsubs}, {1277, &ppc_fnmsubsdot},
|
||||
{1278, &ppc_fnmadds}, {1279, &ppc_fnmaddsdot}, {1330, &ppc_fmults}, {1331, &ppc_fmultsdot},
|
||||
{1336, &ppc_fmsubs}, {1337, &ppc_fmsubsdot}, {1338, &ppc_fmadds}, {1339, &ppc_fmaddsdot},
|
||||
{1340, &ppc_fnmsubs}, {1341, &ppc_fnmsubsdot}, {1342, &ppc_fnmadds}, {1343, &ppc_fnmaddsdot},
|
||||
{1394, &ppc_fmults}, {1395, &ppc_fmultsdot}, {1400, &ppc_fmsubs}, {1401, &ppc_fmsubsdot},
|
||||
{1402, &ppc_fmadds}, {1403, &ppc_fmaddsdot}, {1404, &ppc_fnmsubs}, {1405, &ppc_fnmsubsdot},
|
||||
{1406, &ppc_fnmadds}, {1407, &ppc_fnmaddsdot}, {1458, &ppc_fmults}, {1459, &ppc_fmultsdot},
|
||||
{1464, &ppc_fmsubs}, {1465, &ppc_fmsubsdot}, {1466, &ppc_fmadds}, {1467, &ppc_fmaddsdot},
|
||||
{1468, &ppc_fnmsubs}, {1469, &ppc_fnmsubsdot}, {1470, &ppc_fnmadds}, {1471, &ppc_fnmaddsdot},
|
||||
{1522, &ppc_fmults}, {1523, &ppc_fmultsdot}, {1528, &ppc_fmsubs}, {1529, &ppc_fmsubsdot},
|
||||
{1530, &ppc_fmadds}, {1531, &ppc_fmaddsdot}, {1532, &ppc_fnmsubs}, {1533, &ppc_fnmsubsdot},
|
||||
{1534, &ppc_fnmadds}, {1535, &ppc_fnmaddsdot}, {1586, &ppc_fmults}, {1587, &ppc_fmultsdot},
|
||||
{1592, &ppc_fmsubs}, {1593, &ppc_fmsubsdot}, {1594, &ppc_fmadds}, {1595, &ppc_fmaddsdot},
|
||||
{1596, &ppc_fnmsubs}, {1597, &ppc_fnmsubsdot}, {1598, &ppc_fnmadds}, {1599, &ppc_fnmaddsdot},
|
||||
{1650, &ppc_fmults}, {1651, &ppc_fmultsdot}, {1656, &ppc_fmsubs}, {1657, &ppc_fmsubsdot},
|
||||
{1658, &ppc_fmadds}, {1659, &ppc_fmaddsdot}, {1660, &ppc_fnmsubs}, {1661, &ppc_fnmsubsdot},
|
||||
{1662, &ppc_fnmadds}, {1663, &ppc_fnmaddsdot}, {1714, &ppc_fmults}, {1715, &ppc_fmultsdot},
|
||||
{1720, &ppc_fmsubs}, {1721, &ppc_fmsubsdot}, {1722, &ppc_fmadds}, {1723, &ppc_fmaddsdot},
|
||||
{1724, &ppc_fnmsubs}, {1725, &ppc_fnmsubsdot}, {1726, &ppc_fnmadds}, {1727, &ppc_fnmaddsdot},
|
||||
{1778, &ppc_fmults}, {1779, &ppc_fmultsdot}, {1784, &ppc_fmsubs}, {1785, &ppc_fmsubsdot},
|
||||
{1786, &ppc_fmadds}, {1787, &ppc_fmaddsdot}, {1788, &ppc_fnmsubs}, {1789, &ppc_fnmsubsdot},
|
||||
{1790, &ppc_fnmadds}, {1791, &ppc_fnmaddsdot}, {1842, &ppc_fmults}, {1843, &ppc_fmultsdot},
|
||||
{1848, &ppc_fmsubs}, {1849, &ppc_fmsubsdot}, {1850, &ppc_fmadds}, {1851, &ppc_fmaddsdot},
|
||||
{1852, &ppc_fnmsubs}, {1853, &ppc_fnmsubsdot}, {1854, &ppc_fnmadds}, {1855, &ppc_fnmaddsdot},
|
||||
{1906, &ppc_fmults}, {1907, &ppc_fmultsdot}, {1912, &ppc_fmsubs}, {1913, &ppc_fmsubsdot},
|
||||
{1914, &ppc_fmadds}, {1915, &ppc_fmaddsdot}, {1916, &ppc_fnmsubs}, {1917, &ppc_fnmsubsdot},
|
||||
{1918, &ppc_fnmadds}, {1919, &ppc_fnmaddsdot}, {1970, &ppc_fmults}, {1971, &ppc_fmultsdot},
|
||||
{1976, &ppc_fmsubs}, {1977, &ppc_fmsubsdot}, {1978, &ppc_fmadds}, {1979, &ppc_fmaddsdot},
|
||||
{1980, &ppc_fnmsubs}, {1981, &ppc_fnmsubsdot}, {1982, &ppc_fnmadds}, {1983, &ppc_fnmaddsdot},
|
||||
{2034, &ppc_fmults}, {2035, &ppc_fmultsdot}, {2040, &ppc_fmsubs}, {2041, &ppc_fmsubsdot},
|
||||
{2042, &ppc_fmadds}, {2043, &ppc_fmaddsdot}, {2044, &ppc_fnmsubs}, {2045, &ppc_fnmsubsdot},
|
||||
{2046, &ppc_fnmadds}, {2047, &ppc_fnmaddsdot}};
|
||||
|
||||
/** Double-precision floating-point instructions decoding table. */
|
||||
static std::unordered_map<uint16_t, PPCOpcode> SubOpcode63Grabber = {
|
||||
{ 0, &ppc_fcmpu}, { 24, &ppc_frsp}, { 25, &ppc_frspdot},
|
||||
{ 28, &ppc_fctiw}, { 29, &ppc_fctiwdot}, { 30, &ppc_fctiwz},
|
||||
{ 31, &ppc_fctiwzdot}, { 36, &ppc_fdiv}, { 37, &ppc_fdivdot},
|
||||
{ 40, &ppc_fsub}, { 41, &ppc_fsubdot}, { 42, &ppc_fadd},
|
||||
{ 43, &ppc_fadddot}, { 44, &ppc_fsqrt}, { 45, &ppc_fsqrtdot},
|
||||
{ 46, &ppc_fsel}, { 47, &ppc_fseldot}, { 50, &ppc_fmult},
|
||||
{ 51, &ppc_fmultdot}, { 52, &ppc_frsqrte}, { 53, &ppc_frsqrtedot},
|
||||
{ 56, &ppc_fmsub}, { 57, &ppc_fmsubdot}, { 58, &ppc_fmadd},
|
||||
{ 59, &ppc_fmadddot}, { 60, &ppc_fnmsub}, { 61, &ppc_fnmsubdot},
|
||||
{ 62, &ppc_fnmadd}, { 63, &ppc_fnmadddot}, { 64, &ppc_fcmpo},
|
||||
{ 76, &ppc_mtfsb1}, { 77, &ppc_mtfsb1dot}, { 80, &ppc_fneg},
|
||||
{ 81, &ppc_fnegdot}, { 110, &ppc_fsel}, { 111, &ppc_fseldot},
|
||||
{ 114, &ppc_fmult}, { 115, &ppc_fmultdot}, { 120, &ppc_fmsub},
|
||||
{ 121, &ppc_fmsubdot}, { 122, &ppc_fmadd}, { 123, &ppc_fmadd},
|
||||
{ 124, &ppc_fnmsub}, { 125, &ppc_fnmsubdot}, { 126, &ppc_fnmadd},
|
||||
{ 127, &ppc_fnmadddot}, { 128, &ppc_mcrfs}, { 140, &ppc_mtfsb0},
|
||||
{ 141, &ppc_mtfsb0dot}, { 144, &ppc_fmr}, { 174, &ppc_fsel},
|
||||
{ 175, &ppc_fseldot}, { 178, &ppc_fmult}, { 179, &ppc_fmultdot},
|
||||
{ 184, &ppc_fmsub}, { 185, &ppc_fmsubdot}, { 186, &ppc_fmadd},
|
||||
{ 187, &ppc_fmadddot}, { 188, &ppc_fnmsub}, { 189, &ppc_fnmsubdot},
|
||||
{ 190, &ppc_fnmadd}, { 191, &ppc_fnmadddot}, { 238, &ppc_fsel},
|
||||
{ 239, &ppc_fseldot}, { 242, &ppc_fmult}, { 243, &ppc_fmultdot},
|
||||
{ 248, &ppc_fmsub}, { 249, &ppc_fmsubdot}, { 250, &ppc_fmadd},
|
||||
{ 251, &ppc_fmadddot}, { 252, &ppc_fnmsub}, { 253, &ppc_fnmsubdot},
|
||||
{ 254, &ppc_fnmadd}, { 255, &ppc_fnmadddot}, { 268, &ppc_mtfsfi},
|
||||
{ 272, &ppc_fnabs}, { 273, &ppc_fnabsdot}, { 302, &ppc_fsel},
|
||||
{ 303, &ppc_fseldot}, { 306, &ppc_fmult}, { 307, &ppc_fmultdot},
|
||||
{ 312, &ppc_fmsub}, { 313, &ppc_fmsubdot}, { 314, &ppc_fmadd},
|
||||
{ 315, &ppc_fmadddot}, { 316, &ppc_fnmsub}, { 317, &ppc_fnmsubdot},
|
||||
{ 318, &ppc_fnmadd}, { 319, &ppc_fnmadddot}, { 366, &ppc_fsel},
|
||||
{ 367, &ppc_fseldot}, { 370, &ppc_fmult}, { 371, &ppc_fmultdot},
|
||||
{ 376, &ppc_fmsub}, { 377, &ppc_fmsubdot}, { 378, &ppc_fmadd},
|
||||
{ 379, &ppc_fmadddot}, { 380, &ppc_fnmsub}, { 381, &ppc_fnmsubdot},
|
||||
{ 382, &ppc_fnmadd}, { 383, &ppc_fnmadddot}, { 430, &ppc_fsel},
|
||||
{ 431, &ppc_fseldot}, { 434, &ppc_fmult}, { 435, &ppc_fmultdot},
|
||||
{ 440, &ppc_fmsub}, { 441, &ppc_fmsubdot}, { 442, &ppc_fmadd},
|
||||
{ 443, &ppc_fmadddot}, { 444, &ppc_fnmsub}, { 445, &ppc_fnmsubdot},
|
||||
{ 446, &ppc_fnmadd}, { 447, &ppc_fnmadddot}, { 494, &ppc_fsel},
|
||||
{ 495, &ppc_fseldot}, { 498, &ppc_fmult}, { 499, &ppc_fmultdot},
|
||||
{ 504, &ppc_fmsub}, { 505, &ppc_fmsubdot}, { 506, &ppc_fmadd},
|
||||
{ 507, &ppc_fmadddot}, { 508, &ppc_fnmsub}, { 509, &ppc_fnmsubdot},
|
||||
{ 510, &ppc_fnmadd}, { 511, &ppc_fnmadddot}, { 528, &ppc_fabs},
|
||||
{ 529, &ppc_fabsdot}, { 536, &ppc_mtfsfidot}, { 558, &ppc_fsel},
|
||||
{ 559, &ppc_fseldot}, { 562, &ppc_fmult}, { 563, &ppc_fmultdot},
|
||||
{ 568, &ppc_fmsub}, { 569, &ppc_fmsubdot}, { 570, &ppc_fmadd},
|
||||
{ 571, &ppc_fmadddot}, { 572, &ppc_fnmsub}, { 573, &ppc_fnmsubdot},
|
||||
{ 574, &ppc_fnmadd}, { 575, &ppc_fnmadddot}, { 622, &ppc_fsel},
|
||||
{ 623, &ppc_fseldot}, { 626, &ppc_fmult}, { 627, &ppc_fmultdot},
|
||||
{ 632, &ppc_fmsub}, { 633, &ppc_fmsubdot}, { 634, &ppc_fmadd},
|
||||
{ 635, &ppc_fmadddot}, { 636, &ppc_fnmsub}, { 637, &ppc_fnmsubdot},
|
||||
{ 638, &ppc_fnmadd}, { 639, &ppc_fnmadddot}, { 686, &ppc_fsel},
|
||||
{ 687, &ppc_fseldot}, { 690, &ppc_fmult}, { 691, &ppc_fmultdot},
|
||||
{ 696, &ppc_fmsub}, { 697, &ppc_fmsubdot}, { 698, &ppc_fmadd},
|
||||
{ 699, &ppc_fmadddot}, { 700, &ppc_fnmsub}, { 701, &ppc_fnmsubdot},
|
||||
{ 702, &ppc_fnmadd}, { 703, &ppc_fnmadddot}, { 750, &ppc_fsel},
|
||||
{ 751, &ppc_fseldot}, { 754, &ppc_fmult}, { 755, &ppc_fmultdot},
|
||||
{ 760, &ppc_fmsub}, { 761, &ppc_fmsubdot}, { 762, &ppc_fmadd},
|
||||
{ 763, &ppc_fmadddot}, { 764, &ppc_fnmsub}, { 765, &ppc_fnmsubdot},
|
||||
{ 766, &ppc_fnmadd}, { 767, &ppc_fnmadddot}, { 814, &ppc_fsel},
|
||||
{ 815, &ppc_fseldot}, { 818, &ppc_fmult}, { 819, &ppc_fmultdot},
|
||||
{ 824, &ppc_fmsub}, { 825, &ppc_fmsubdot}, { 826, &ppc_fmadd},
|
||||
{ 827, &ppc_fmadddot}, { 828, &ppc_fnmsub}, { 829, &ppc_fnmsubdot},
|
||||
{ 830, &ppc_fnmadd}, { 831, &ppc_fnmadddot}, { 878, &ppc_fsel},
|
||||
{ 879, &ppc_fseldot}, { 882, &ppc_fmult}, { 883, &ppc_fmultdot},
|
||||
{ 888, &ppc_fmsub}, { 889, &ppc_fmsubdot}, { 890, &ppc_fmadd},
|
||||
{ 891, &ppc_fmadddot}, { 892, &ppc_fnmsub}, { 893, &ppc_fnmsubdot},
|
||||
{ 894, &ppc_fnmadd}, { 895, &ppc_fnmadddot}, { 942, &ppc_fsel},
|
||||
{ 943, &ppc_fseldot}, { 946, &ppc_fmult}, { 947, &ppc_fmultdot},
|
||||
{ 952, &ppc_fmsub}, { 953, &ppc_fmsubdot}, { 954, &ppc_fmadd},
|
||||
{ 955, &ppc_fmadddot}, { 957, &ppc_fnmsub}, { 958, &ppc_fnmsubdot},
|
||||
{ 958, &ppc_fnmadd}, { 959, &ppc_fnmadddot}, {1006, &ppc_fsel},
|
||||
{1007, &ppc_fseldot}, {1010, &ppc_fmult}, {1011, &ppc_fmultdot},
|
||||
{1016, &ppc_fmsub}, {1017, &ppc_fmsubdot}, {1018, &ppc_fmadd},
|
||||
{1019, &ppc_fmadddot}, {1020, &ppc_fnmsub}, {1021, &ppc_fnmsubdot},
|
||||
{1022, &ppc_fnmadd}, {1023, &ppc_fnmadddot}, {1070, &ppc_fsel},
|
||||
{1071, &ppc_fseldot}, {1074, &ppc_fmult}, {1075, &ppc_fmultdot},
|
||||
{1080, &ppc_fmsub}, {1081, &ppc_fmsubdot}, {1082, &ppc_fmadd},
|
||||
{1083, &ppc_fmadddot}, {1084, &ppc_fnmsub}, {1085, &ppc_fnmsubdot},
|
||||
{1086, &ppc_fnmadd}, {1087, &ppc_fnmadddot}, {1134, &ppc_fsel},
|
||||
{1135, &ppc_fseldot}, {1138, &ppc_fmult}, {1139, &ppc_fmultdot},
|
||||
{1144, &ppc_fmsub}, {1145, &ppc_fmsubdot}, {1146, &ppc_fmadd},
|
||||
{1147, &ppc_fmadddot}, {1148, &ppc_fnmsub}, {1149, &ppc_fnmsubdot},
|
||||
{1150, &ppc_fnmadd}, {1151, &ppc_fnmadddot}, {1166, &ppc_mffs},
|
||||
{1167, &ppc_mffsdot}, {1198, &ppc_fsel}, {1199, &ppc_fseldot},
|
||||
{1202, &ppc_fmult}, {1203, &ppc_fmultdot}, {1208, &ppc_fmsub},
|
||||
{1209, &ppc_fmsubdot}, {1210, &ppc_fmadd}, {1211, &ppc_fmadddot},
|
||||
{1212, &ppc_fnmsub}, {1213, &ppc_fnmsubdot}, {1214, &ppc_fnmadd},
|
||||
{1215, &ppc_fnmadddot}, {1262, &ppc_fsel}, {1263, &ppc_fseldot},
|
||||
{1266, &ppc_fmult}, {1267, &ppc_fmultdot}, {1272, &ppc_fmsub},
|
||||
{1273, &ppc_fmsubdot}, {1274, &ppc_fmadd}, {1275, &ppc_fmadddot},
|
||||
{1276, &ppc_fnmsub}, {1277, &ppc_fnmsubdot}, {1278, &ppc_fnmadd},
|
||||
{1279, &ppc_fnmadddot}, {1326, &ppc_fsel}, {1327, &ppc_fseldot},
|
||||
{1330, &ppc_fmult}, {1331, &ppc_fmultdot}, {1336, &ppc_fmsub},
|
||||
{1337, &ppc_fmsubdot}, {1338, &ppc_fmadd}, {1339, &ppc_fmadddot},
|
||||
{1340, &ppc_fnmsub}, {1341, &ppc_fnmsubdot}, {1342, &ppc_fnmadd},
|
||||
{1343, &ppc_fnmadddot}, {1390, &ppc_fsel}, {1391, &ppc_fseldot},
|
||||
{1394, &ppc_fmult}, {1395, &ppc_fmultdot}, {1400, &ppc_fmsub},
|
||||
{1401, &ppc_fmsubdot}, {1402, &ppc_fmadd}, {1403, &ppc_fmadddot},
|
||||
{1404, &ppc_fnmsub}, {1405, &ppc_fnmsubdot}, {1406, &ppc_fnmadd},
|
||||
{1407, &ppc_fnmadddot}, {1422, &ppc_mtfsf}, {1423, &ppc_mtfsfdot},
|
||||
{1454, &ppc_fsel}, {1455, &ppc_fseldot}, {1458, &ppc_fmult},
|
||||
{1459, &ppc_fmultdot}, {1464, &ppc_fmsub}, {1465, &ppc_fmsubdot},
|
||||
{1466, &ppc_fmadd}, {1467, &ppc_fmadddot}, {1468, &ppc_fnmsub},
|
||||
{1469, &ppc_fnmsubdot}, {1470, &ppc_fnmadd}, {1471, &ppc_fnmadddot},
|
||||
{1518, &ppc_fsel}, {1519, &ppc_fseldot}, {1522, &ppc_fmult},
|
||||
{1523, &ppc_fmultdot}, {1528, &ppc_fmsub}, {1529, &ppc_fmsubdot},
|
||||
{1530, &ppc_fmadd}, {1531, &ppc_fmadddot}, {1532, &ppc_fnmsub},
|
||||
{1533, &ppc_fnmsubdot}, {1534, &ppc_fnmadd}, {1535, &ppc_fnmadddot},
|
||||
{1582, &ppc_fsel}, {1583, &ppc_fseldot}, {1586, &ppc_fmult},
|
||||
{1587, &ppc_fmultdot}, {1592, &ppc_fmsub}, {1593, &ppc_fmsubdot},
|
||||
{1594, &ppc_fmadd}, {1595, &ppc_fmadddot}, {1596, &ppc_fnmsub},
|
||||
{1597, &ppc_fnmsubdot}, {1598, &ppc_fnmadd}, {1599, &ppc_fnmadddot},
|
||||
{1646, &ppc_fsel}, {1647, &ppc_fseldot}, {1650, &ppc_fmult},
|
||||
{1651, &ppc_fmultdot}, {1656, &ppc_fmsub}, {1657, &ppc_fmsubdot},
|
||||
{1658, &ppc_fmadd}, {1659, &ppc_fmadddot}, {1660, &ppc_fnmsub},
|
||||
{1661, &ppc_fnmsubdot}, {1662, &ppc_fnmadd}, {1663, &ppc_fnmadddot},
|
||||
{1710, &ppc_fsel}, {1711, &ppc_fseldot}, {1714, &ppc_fmult},
|
||||
{1715, &ppc_fmultdot}, {1720, &ppc_fmsub}, {1721, &ppc_fmsubdot},
|
||||
{1722, &ppc_fmadd}, {1723, &ppc_fmadddot}, {1724, &ppc_fnmsub},
|
||||
{1725, &ppc_fnmsubdot}, {1726, &ppc_fnmadd}, {1727, &ppc_fnmadddot},
|
||||
{1774, &ppc_fsel}, {1775, &ppc_fseldot}, {1778, &ppc_fmult},
|
||||
{1779, &ppc_fmultdot}, {1784, &ppc_fmsub}, {1785, &ppc_fmsubdot},
|
||||
{1786, &ppc_fmadd}, {1787, &ppc_fmadddot}, {1788, &ppc_fnmsub},
|
||||
{1789, &ppc_fnmsubdot}, {1790, &ppc_fnmadd}, {1791, &ppc_fnmadddot},
|
||||
{1838, &ppc_fsel}, {1839, &ppc_fseldot}, {1842, &ppc_fmult},
|
||||
{1843, &ppc_fmultdot}, {1848, &ppc_fmsub}, {1849, &ppc_fmsubdot},
|
||||
{1850, &ppc_fmadd}, {1851, &ppc_fmadddot}, {1852, &ppc_fnmsub},
|
||||
{1853, &ppc_fnmsubdot}, {1854, &ppc_fnmadd}, {1855, &ppc_fnmadddot},
|
||||
{1902, &ppc_fsel}, {1903, &ppc_fseldot}, {1906, &ppc_fmult},
|
||||
{1907, &ppc_fmultdot}, {1912, &ppc_fmsub}, {1913, &ppc_fmsubdot},
|
||||
{1914, &ppc_fmadd}, {1915, &ppc_fmadddot}, {1916, &ppc_fnmsub},
|
||||
{1917, &ppc_fnmsubdot}, {1918, &ppc_fnmadd}, {1919, &ppc_fnmadddot},
|
||||
{1966, &ppc_fsel}, {1967, &ppc_fseldot}, {1970, &ppc_fmult},
|
||||
{1971, &ppc_fmultdot}, {1976, &ppc_fmsub}, {1977, &ppc_fmsubdot},
|
||||
{1978, &ppc_fmadd}, {1979, &ppc_fmadddot}, {1980, &ppc_fnmsub},
|
||||
{1981, &ppc_fnmsubdot}, {1982, &ppc_fnmadd}, {1983, &ppc_fnmadddot},
|
||||
{2030, &ppc_fsel}, {2031, &ppc_fseldot}, {2034, &ppc_fmult},
|
||||
{2035, &ppc_fmultdot}, {2040, &ppc_fmsub}, {2041, &ppc_fmsubdot},
|
||||
{2042, &ppc_fmadd}, {2043, &ppc_fmadddot}, {2044, &ppc_fnmsub},
|
||||
{2045, &ppc_fnmsubdot}, {2046, &ppc_fnmadd}, {2047, &ppc_fnmadddot}
|
||||
};
|
||||
{0, &ppc_fcmpu}, {24, &ppc_frsp}, {25, &ppc_frspdot}, {28, &ppc_fctiw},
|
||||
{29, &ppc_fctiwdot}, {30, &ppc_fctiwz}, {31, &ppc_fctiwzdot}, {36, &ppc_fdiv},
|
||||
{37, &ppc_fdivdot}, {40, &ppc_fsub}, {41, &ppc_fsubdot}, {42, &ppc_fadd},
|
||||
{43, &ppc_fadddot}, {44, &ppc_fsqrt}, {45, &ppc_fsqrtdot}, {46, &ppc_fsel},
|
||||
{47, &ppc_fseldot}, {50, &ppc_fmult}, {51, &ppc_fmultdot}, {52, &ppc_frsqrte},
|
||||
{53, &ppc_frsqrtedot}, {56, &ppc_fmsub}, {57, &ppc_fmsubdot}, {58, &ppc_fmadd},
|
||||
{59, &ppc_fmadddot}, {60, &ppc_fnmsub}, {61, &ppc_fnmsubdot}, {62, &ppc_fnmadd},
|
||||
{63, &ppc_fnmadddot}, {64, &ppc_fcmpo}, {76, &ppc_mtfsb1}, {77, &ppc_mtfsb1dot},
|
||||
{80, &ppc_fneg}, {81, &ppc_fnegdot}, {110, &ppc_fsel}, {111, &ppc_fseldot},
|
||||
{114, &ppc_fmult}, {115, &ppc_fmultdot}, {120, &ppc_fmsub}, {121, &ppc_fmsubdot},
|
||||
{122, &ppc_fmadd}, {123, &ppc_fmadd}, {124, &ppc_fnmsub}, {125, &ppc_fnmsubdot},
|
||||
{126, &ppc_fnmadd}, {127, &ppc_fnmadddot}, {128, &ppc_mcrfs}, {140, &ppc_mtfsb0},
|
||||
{141, &ppc_mtfsb0dot}, {144, &ppc_fmr}, {174, &ppc_fsel}, {175, &ppc_fseldot},
|
||||
{178, &ppc_fmult}, {179, &ppc_fmultdot}, {184, &ppc_fmsub}, {185, &ppc_fmsubdot},
|
||||
{186, &ppc_fmadd}, {187, &ppc_fmadddot}, {188, &ppc_fnmsub}, {189, &ppc_fnmsubdot},
|
||||
{190, &ppc_fnmadd}, {191, &ppc_fnmadddot}, {238, &ppc_fsel}, {239, &ppc_fseldot},
|
||||
{242, &ppc_fmult}, {243, &ppc_fmultdot}, {248, &ppc_fmsub}, {249, &ppc_fmsubdot},
|
||||
{250, &ppc_fmadd}, {251, &ppc_fmadddot}, {252, &ppc_fnmsub}, {253, &ppc_fnmsubdot},
|
||||
{254, &ppc_fnmadd}, {255, &ppc_fnmadddot}, {268, &ppc_mtfsfi}, {272, &ppc_fnabs},
|
||||
{273, &ppc_fnabsdot}, {302, &ppc_fsel}, {303, &ppc_fseldot}, {306, &ppc_fmult},
|
||||
{307, &ppc_fmultdot}, {312, &ppc_fmsub}, {313, &ppc_fmsubdot}, {314, &ppc_fmadd},
|
||||
{315, &ppc_fmadddot}, {316, &ppc_fnmsub}, {317, &ppc_fnmsubdot}, {318, &ppc_fnmadd},
|
||||
{319, &ppc_fnmadddot}, {366, &ppc_fsel}, {367, &ppc_fseldot}, {370, &ppc_fmult},
|
||||
{371, &ppc_fmultdot}, {376, &ppc_fmsub}, {377, &ppc_fmsubdot}, {378, &ppc_fmadd},
|
||||
{379, &ppc_fmadddot}, {380, &ppc_fnmsub}, {381, &ppc_fnmsubdot}, {382, &ppc_fnmadd},
|
||||
{383, &ppc_fnmadddot}, {430, &ppc_fsel}, {431, &ppc_fseldot}, {434, &ppc_fmult},
|
||||
{435, &ppc_fmultdot}, {440, &ppc_fmsub}, {441, &ppc_fmsubdot}, {442, &ppc_fmadd},
|
||||
{443, &ppc_fmadddot}, {444, &ppc_fnmsub}, {445, &ppc_fnmsubdot}, {446, &ppc_fnmadd},
|
||||
{447, &ppc_fnmadddot}, {494, &ppc_fsel}, {495, &ppc_fseldot}, {498, &ppc_fmult},
|
||||
{499, &ppc_fmultdot}, {504, &ppc_fmsub}, {505, &ppc_fmsubdot}, {506, &ppc_fmadd},
|
||||
{507, &ppc_fmadddot}, {508, &ppc_fnmsub}, {509, &ppc_fnmsubdot}, {510, &ppc_fnmadd},
|
||||
{511, &ppc_fnmadddot}, {528, &ppc_fabs}, {529, &ppc_fabsdot}, {536, &ppc_mtfsfidot},
|
||||
{558, &ppc_fsel}, {559, &ppc_fseldot}, {562, &ppc_fmult}, {563, &ppc_fmultdot},
|
||||
{568, &ppc_fmsub}, {569, &ppc_fmsubdot}, {570, &ppc_fmadd}, {571, &ppc_fmadddot},
|
||||
{572, &ppc_fnmsub}, {573, &ppc_fnmsubdot}, {574, &ppc_fnmadd}, {575, &ppc_fnmadddot},
|
||||
{622, &ppc_fsel}, {623, &ppc_fseldot}, {626, &ppc_fmult}, {627, &ppc_fmultdot},
|
||||
{632, &ppc_fmsub}, {633, &ppc_fmsubdot}, {634, &ppc_fmadd}, {635, &ppc_fmadddot},
|
||||
{636, &ppc_fnmsub}, {637, &ppc_fnmsubdot}, {638, &ppc_fnmadd}, {639, &ppc_fnmadddot},
|
||||
{686, &ppc_fsel}, {687, &ppc_fseldot}, {690, &ppc_fmult}, {691, &ppc_fmultdot},
|
||||
{696, &ppc_fmsub}, {697, &ppc_fmsubdot}, {698, &ppc_fmadd}, {699, &ppc_fmadddot},
|
||||
{700, &ppc_fnmsub}, {701, &ppc_fnmsubdot}, {702, &ppc_fnmadd}, {703, &ppc_fnmadddot},
|
||||
{750, &ppc_fsel}, {751, &ppc_fseldot}, {754, &ppc_fmult}, {755, &ppc_fmultdot},
|
||||
{760, &ppc_fmsub}, {761, &ppc_fmsubdot}, {762, &ppc_fmadd}, {763, &ppc_fmadddot},
|
||||
{764, &ppc_fnmsub}, {765, &ppc_fnmsubdot}, {766, &ppc_fnmadd}, {767, &ppc_fnmadddot},
|
||||
{814, &ppc_fsel}, {815, &ppc_fseldot}, {818, &ppc_fmult}, {819, &ppc_fmultdot},
|
||||
{824, &ppc_fmsub}, {825, &ppc_fmsubdot}, {826, &ppc_fmadd}, {827, &ppc_fmadddot},
|
||||
{828, &ppc_fnmsub}, {829, &ppc_fnmsubdot}, {830, &ppc_fnmadd}, {831, &ppc_fnmadddot},
|
||||
{878, &ppc_fsel}, {879, &ppc_fseldot}, {882, &ppc_fmult}, {883, &ppc_fmultdot},
|
||||
{888, &ppc_fmsub}, {889, &ppc_fmsubdot}, {890, &ppc_fmadd}, {891, &ppc_fmadddot},
|
||||
{892, &ppc_fnmsub}, {893, &ppc_fnmsubdot}, {894, &ppc_fnmadd}, {895, &ppc_fnmadddot},
|
||||
{942, &ppc_fsel}, {943, &ppc_fseldot}, {946, &ppc_fmult}, {947, &ppc_fmultdot},
|
||||
{952, &ppc_fmsub}, {953, &ppc_fmsubdot}, {954, &ppc_fmadd}, {955, &ppc_fmadddot},
|
||||
{957, &ppc_fnmsub}, {958, &ppc_fnmsubdot}, {958, &ppc_fnmadd}, {959, &ppc_fnmadddot},
|
||||
{1006, &ppc_fsel}, {1007, &ppc_fseldot}, {1010, &ppc_fmult}, {1011, &ppc_fmultdot},
|
||||
{1016, &ppc_fmsub}, {1017, &ppc_fmsubdot}, {1018, &ppc_fmadd}, {1019, &ppc_fmadddot},
|
||||
{1020, &ppc_fnmsub}, {1021, &ppc_fnmsubdot}, {1022, &ppc_fnmadd}, {1023, &ppc_fnmadddot},
|
||||
{1070, &ppc_fsel}, {1071, &ppc_fseldot}, {1074, &ppc_fmult}, {1075, &ppc_fmultdot},
|
||||
{1080, &ppc_fmsub}, {1081, &ppc_fmsubdot}, {1082, &ppc_fmadd}, {1083, &ppc_fmadddot},
|
||||
{1084, &ppc_fnmsub}, {1085, &ppc_fnmsubdot}, {1086, &ppc_fnmadd}, {1087, &ppc_fnmadddot},
|
||||
{1134, &ppc_fsel}, {1135, &ppc_fseldot}, {1138, &ppc_fmult}, {1139, &ppc_fmultdot},
|
||||
{1144, &ppc_fmsub}, {1145, &ppc_fmsubdot}, {1146, &ppc_fmadd}, {1147, &ppc_fmadddot},
|
||||
{1148, &ppc_fnmsub}, {1149, &ppc_fnmsubdot}, {1150, &ppc_fnmadd}, {1151, &ppc_fnmadddot},
|
||||
{1166, &ppc_mffs}, {1167, &ppc_mffsdot}, {1198, &ppc_fsel}, {1199, &ppc_fseldot},
|
||||
{1202, &ppc_fmult}, {1203, &ppc_fmultdot}, {1208, &ppc_fmsub}, {1209, &ppc_fmsubdot},
|
||||
{1210, &ppc_fmadd}, {1211, &ppc_fmadddot}, {1212, &ppc_fnmsub}, {1213, &ppc_fnmsubdot},
|
||||
{1214, &ppc_fnmadd}, {1215, &ppc_fnmadddot}, {1262, &ppc_fsel}, {1263, &ppc_fseldot},
|
||||
{1266, &ppc_fmult}, {1267, &ppc_fmultdot}, {1272, &ppc_fmsub}, {1273, &ppc_fmsubdot},
|
||||
{1274, &ppc_fmadd}, {1275, &ppc_fmadddot}, {1276, &ppc_fnmsub}, {1277, &ppc_fnmsubdot},
|
||||
{1278, &ppc_fnmadd}, {1279, &ppc_fnmadddot}, {1326, &ppc_fsel}, {1327, &ppc_fseldot},
|
||||
{1330, &ppc_fmult}, {1331, &ppc_fmultdot}, {1336, &ppc_fmsub}, {1337, &ppc_fmsubdot},
|
||||
{1338, &ppc_fmadd}, {1339, &ppc_fmadddot}, {1340, &ppc_fnmsub}, {1341, &ppc_fnmsubdot},
|
||||
{1342, &ppc_fnmadd}, {1343, &ppc_fnmadddot}, {1390, &ppc_fsel}, {1391, &ppc_fseldot},
|
||||
{1394, &ppc_fmult}, {1395, &ppc_fmultdot}, {1400, &ppc_fmsub}, {1401, &ppc_fmsubdot},
|
||||
{1402, &ppc_fmadd}, {1403, &ppc_fmadddot}, {1404, &ppc_fnmsub}, {1405, &ppc_fnmsubdot},
|
||||
{1406, &ppc_fnmadd}, {1407, &ppc_fnmadddot}, {1422, &ppc_mtfsf}, {1423, &ppc_mtfsfdot},
|
||||
{1454, &ppc_fsel}, {1455, &ppc_fseldot}, {1458, &ppc_fmult}, {1459, &ppc_fmultdot},
|
||||
{1464, &ppc_fmsub}, {1465, &ppc_fmsubdot}, {1466, &ppc_fmadd}, {1467, &ppc_fmadddot},
|
||||
{1468, &ppc_fnmsub}, {1469, &ppc_fnmsubdot}, {1470, &ppc_fnmadd}, {1471, &ppc_fnmadddot},
|
||||
{1518, &ppc_fsel}, {1519, &ppc_fseldot}, {1522, &ppc_fmult}, {1523, &ppc_fmultdot},
|
||||
{1528, &ppc_fmsub}, {1529, &ppc_fmsubdot}, {1530, &ppc_fmadd}, {1531, &ppc_fmadddot},
|
||||
{1532, &ppc_fnmsub}, {1533, &ppc_fnmsubdot}, {1534, &ppc_fnmadd}, {1535, &ppc_fnmadddot},
|
||||
{1582, &ppc_fsel}, {1583, &ppc_fseldot}, {1586, &ppc_fmult}, {1587, &ppc_fmultdot},
|
||||
{1592, &ppc_fmsub}, {1593, &ppc_fmsubdot}, {1594, &ppc_fmadd}, {1595, &ppc_fmadddot},
|
||||
{1596, &ppc_fnmsub}, {1597, &ppc_fnmsubdot}, {1598, &ppc_fnmadd}, {1599, &ppc_fnmadddot},
|
||||
{1646, &ppc_fsel}, {1647, &ppc_fseldot}, {1650, &ppc_fmult}, {1651, &ppc_fmultdot},
|
||||
{1656, &ppc_fmsub}, {1657, &ppc_fmsubdot}, {1658, &ppc_fmadd}, {1659, &ppc_fmadddot},
|
||||
{1660, &ppc_fnmsub}, {1661, &ppc_fnmsubdot}, {1662, &ppc_fnmadd}, {1663, &ppc_fnmadddot},
|
||||
{1710, &ppc_fsel}, {1711, &ppc_fseldot}, {1714, &ppc_fmult}, {1715, &ppc_fmultdot},
|
||||
{1720, &ppc_fmsub}, {1721, &ppc_fmsubdot}, {1722, &ppc_fmadd}, {1723, &ppc_fmadddot},
|
||||
{1724, &ppc_fnmsub}, {1725, &ppc_fnmsubdot}, {1726, &ppc_fnmadd}, {1727, &ppc_fnmadddot},
|
||||
{1774, &ppc_fsel}, {1775, &ppc_fseldot}, {1778, &ppc_fmult}, {1779, &ppc_fmultdot},
|
||||
{1784, &ppc_fmsub}, {1785, &ppc_fmsubdot}, {1786, &ppc_fmadd}, {1787, &ppc_fmadddot},
|
||||
{1788, &ppc_fnmsub}, {1789, &ppc_fnmsubdot}, {1790, &ppc_fnmadd}, {1791, &ppc_fnmadddot},
|
||||
{1838, &ppc_fsel}, {1839, &ppc_fseldot}, {1842, &ppc_fmult}, {1843, &ppc_fmultdot},
|
||||
{1848, &ppc_fmsub}, {1849, &ppc_fmsubdot}, {1850, &ppc_fmadd}, {1851, &ppc_fmadddot},
|
||||
{1852, &ppc_fnmsub}, {1853, &ppc_fnmsubdot}, {1854, &ppc_fnmadd}, {1855, &ppc_fnmadddot},
|
||||
{1902, &ppc_fsel}, {1903, &ppc_fseldot}, {1906, &ppc_fmult}, {1907, &ppc_fmultdot},
|
||||
{1912, &ppc_fmsub}, {1913, &ppc_fmsubdot}, {1914, &ppc_fmadd}, {1915, &ppc_fmadddot},
|
||||
{1916, &ppc_fnmsub}, {1917, &ppc_fnmsubdot}, {1918, &ppc_fnmadd}, {1919, &ppc_fnmadddot},
|
||||
{1966, &ppc_fsel}, {1967, &ppc_fseldot}, {1970, &ppc_fmult}, {1971, &ppc_fmultdot},
|
||||
{1976, &ppc_fmsub}, {1977, &ppc_fmsubdot}, {1978, &ppc_fmadd}, {1979, &ppc_fmadddot},
|
||||
{1980, &ppc_fnmsub}, {1981, &ppc_fnmsubdot}, {1982, &ppc_fnmadd}, {1983, &ppc_fnmadddot},
|
||||
{2030, &ppc_fsel}, {2031, &ppc_fseldot}, {2034, &ppc_fmult}, {2035, &ppc_fmultdot},
|
||||
{2040, &ppc_fmsub}, {2041, &ppc_fmsubdot}, {2042, &ppc_fmadd}, {2043, &ppc_fmadddot},
|
||||
{2044, &ppc_fnmsub}, {2045, &ppc_fnmsubdot}, {2046, &ppc_fnmadd}, {2047, &ppc_fnmadddot}};
|
||||
|
||||
/** Opcode decoding functions. */
|
||||
|
||||
|
@ -445,8 +418,11 @@ void ppc_opcode4() {
|
|||
LOG_F(INFO, "Reading from Opcode 4 table \n");
|
||||
uint8_t subop_grab = ppc_cur_instruction & 3;
|
||||
uint32_t regrab = (uint32_t)subop_grab;
|
||||
LOG_F(ERROR, "Executing subopcode entry %d \n"
|
||||
".. or would if I bothered to implement it. SORRY!", regrab);
|
||||
LOG_F(
|
||||
ERROR,
|
||||
"Executing subopcode entry %d \n"
|
||||
".. or would if I bothered to implement it. SORRY!",
|
||||
regrab);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
@ -465,8 +441,7 @@ void ppc_opcode19() {
|
|||
LOG_F(INFO, "Executing Opcode 19 table subopcode entry \n", regrab);
|
||||
if (SubOpcode19Grabber.count(subop_grab) == 1) {
|
||||
SubOpcode19Grabber[subop_grab]();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(ERROR, "ILLEGAL SUBOPCODE: %d \n", subop_grab);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
|
||||
}
|
||||
|
@ -482,8 +457,7 @@ void ppc_opcode31() {
|
|||
LOG_F(INFO, "Executing Opcode 31 table subopcode entry \n", regrab);
|
||||
if (SubOpcode31Grabber.count(subop_grab) == 1) {
|
||||
SubOpcode31Grabber[subop_grab]();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(ERROR, "ILLEGAL SUBOPCODE: %d \n", subop_grab);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
|
||||
}
|
||||
|
@ -499,8 +473,7 @@ void ppc_opcode59() {
|
|||
LOG_F(INFO, "Executing Opcode 59 table subopcode entry \n", regrab);
|
||||
if (SubOpcode59Grabber.count(subop_grab) == 1) {
|
||||
SubOpcode59Grabber[subop_grab]();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(ERROR, "ILLEGAL SUBOPCODE: %d \n", subop_grab);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
|
||||
}
|
||||
|
@ -516,8 +489,7 @@ void ppc_opcode63() {
|
|||
LOG_F(INFO, "Executing Opcode 63 table subopcode entry \n", regrab);
|
||||
if (SubOpcode63Grabber.count(subop_grab) == 1) {
|
||||
SubOpcode63Grabber[subop_grab]();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(ERROR, "ILLEGAL SUBOPCODE: %d \n", subop_grab);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
|
||||
}
|
||||
|
@ -527,31 +499,28 @@ void ppc_opcode63() {
|
|||
}
|
||||
|
||||
void ppc_main_opcode() {
|
||||
//Grab the main opcode
|
||||
// Grab the main opcode
|
||||
uint8_t ppc_mainop = (ppc_cur_instruction >> 26) & 63;
|
||||
OpcodeGrabber[ppc_mainop]();
|
||||
}
|
||||
|
||||
/** Old time base register (TBR) update code. */
|
||||
void tbr_update()
|
||||
{
|
||||
void tbr_update() {
|
||||
clock_t clock_test_current = clock();
|
||||
uint32_t test_clock = ((uint32_t)(clock_test_current - clock_test_begin)) / CLOCKS_PER_SEC;
|
||||
if (test_clock) {
|
||||
if (ppc_state.tbr[0] != 0xFFFFFFFF) {
|
||||
ppc_state.tbr[0]++;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_state.tbr[0] = 0;
|
||||
if (ppc_state.tbr[1] != 0xFFFFFFFF) {
|
||||
ppc_state.tbr[1]++;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_state.tbr[1] = 0;
|
||||
}
|
||||
}
|
||||
clock_test_begin = clock();
|
||||
//Placeholder Decrementing Code
|
||||
// Placeholder Decrementing Code
|
||||
if (ppc_state.spr[22] > 0) {
|
||||
ppc_state.spr[22]--;
|
||||
}
|
||||
|
@ -584,8 +553,7 @@ void ppc_exec()
|
|||
}
|
||||
}
|
||||
#else
|
||||
void ppc_exec()
|
||||
{
|
||||
void ppc_exec() {
|
||||
uint32_t bb_start_la, page_start;
|
||||
uint8_t* pc_real;
|
||||
|
||||
|
@ -619,15 +587,13 @@ again:
|
|||
if ((ppc_next_instruction_address & 0xFFFFF000) != page_start) {
|
||||
page_start = bb_start_la & 0xFFFFF000;
|
||||
pc_real = quickinstruction_translate(bb_start_la);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
pc_real += (int)bb_start_la - (int)ppc_state.pc;
|
||||
ppc_set_cur_instruction(pc_real);
|
||||
}
|
||||
ppc_state.pc = bb_start_la;
|
||||
bb_kind = BB_end_kind::BB_NONE;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_state.pc += 4;
|
||||
pc_real += 4;
|
||||
ppc_set_cur_instruction(pc_real);
|
||||
|
@ -659,8 +625,7 @@ void ppc_exec_single()
|
|||
}
|
||||
}
|
||||
#else
|
||||
void ppc_exec_single()
|
||||
{
|
||||
void ppc_exec_single() {
|
||||
if (setjmp(exc_env)) {
|
||||
/* reaching here means we got a low-level exception */
|
||||
timebase_counter += 1;
|
||||
|
@ -674,8 +639,7 @@ void ppc_exec_single()
|
|||
if (bb_kind != BB_end_kind::BB_NONE) {
|
||||
ppc_state.pc = ppc_next_instruction_address;
|
||||
bb_kind = BB_end_kind::BB_NONE;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_state.pc += 4;
|
||||
}
|
||||
timebase_counter += 1;
|
||||
|
@ -708,8 +672,7 @@ void ppc_exec_until(uint32_t goal_addr)
|
|||
}
|
||||
}
|
||||
#else
|
||||
void ppc_exec_until(uint32_t goal_addr)
|
||||
{
|
||||
void ppc_exec_until(uint32_t goal_addr) {
|
||||
uint32_t bb_start_la, page_start;
|
||||
uint8_t* pc_real;
|
||||
|
||||
|
@ -743,15 +706,13 @@ again:
|
|||
if ((ppc_next_instruction_address & 0xFFFFF000) != page_start) {
|
||||
page_start = bb_start_la & 0xFFFFF000;
|
||||
pc_real = quickinstruction_translate(bb_start_la);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
pc_real += (int)bb_start_la - (int)ppc_state.pc;
|
||||
ppc_set_cur_instruction(pc_real);
|
||||
}
|
||||
ppc_state.pc = bb_start_la;
|
||||
bb_kind = BB_end_kind::BB_NONE;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_state.pc += 4;
|
||||
pc_real += 4;
|
||||
ppc_set_cur_instruction(pc_real);
|
||||
|
@ -760,8 +721,7 @@ again:
|
|||
}
|
||||
#endif
|
||||
|
||||
void ppc_cpu_init(MemCtrlBase *mem_ctrl, uint32_t proc_version)
|
||||
{
|
||||
void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t proc_version) {
|
||||
int i;
|
||||
|
||||
mem_ctrl_instance = mem_ctrl;
|
||||
|
@ -816,11 +776,9 @@ void ppc_cpu_init(MemCtrlBase *mem_ctrl, uint32_t proc_version)
|
|||
ppc_state.pc = 0xFFF00100;
|
||||
}
|
||||
|
||||
void print_gprs()
|
||||
{
|
||||
void print_gprs() {
|
||||
for (int i = 0; i < 32; i++)
|
||||
cout << "GPR " << dec << i << " : " << uppercase << hex
|
||||
<< ppc_state.gpr[i] << endl;
|
||||
cout << "GPR " << dec << i << " : " << uppercase << hex << ppc_state.gpr[i] << endl;
|
||||
|
||||
cout << "PC: " << uppercase << hex << ppc_state.pc << endl;
|
||||
cout << "LR: " << uppercase << hex << ppc_state.spr[SPR::LR] << endl;
|
||||
|
@ -830,19 +788,15 @@ void print_gprs()
|
|||
cout << "MSR: " << uppercase << hex << ppc_state.msr << endl;
|
||||
}
|
||||
|
||||
void print_fprs()
|
||||
{
|
||||
void print_fprs() {
|
||||
for (int i = 0; i < 32; i++)
|
||||
cout << "FPR " << dec << i << " : " << ppc_state.fpr[i].dbl64_r << endl;
|
||||
}
|
||||
|
||||
static map<string, int> SPRName2Num = {
|
||||
{"XER", SPR::XER}, {"LR", SPR::LR}, {"CTR", SPR::CTR}, {"DEC", SPR::DEC},
|
||||
{"PVR", SPR::PVR}
|
||||
};
|
||||
{"XER", SPR::XER}, {"LR", SPR::LR}, {"CTR", SPR::CTR}, {"DEC", SPR::DEC}, {"PVR", SPR::PVR}};
|
||||
|
||||
uint64_t reg_op(string ®_name, uint64_t val, bool is_write)
|
||||
{
|
||||
uint64_t reg_op(string& reg_name, uint64_t val, bool is_write) {
|
||||
string reg_name_u, reg_num_str;
|
||||
unsigned reg_num;
|
||||
map<string, int>::iterator spr;
|
||||
|
@ -853,9 +807,7 @@ uint64_t reg_op(string ®_name, uint64_t val, bool is_write)
|
|||
reg_name_u = reg_name;
|
||||
|
||||
/* convert reg_name string to uppercase */
|
||||
std::for_each(reg_name_u.begin(), reg_name_u.end(), [](char & c) {
|
||||
c = ::toupper(c);
|
||||
});
|
||||
std::for_each(reg_name_u.begin(), reg_name_u.end(), [](char& c) { c = ::toupper(c); });
|
||||
|
||||
try {
|
||||
if (reg_name_u == "PC") {
|
||||
|
@ -925,20 +877,17 @@ uint64_t reg_op(string ®_name, uint64_t val, bool is_write)
|
|||
ppc_state.spr[spr->second] = val;
|
||||
return ppc_state.spr[spr->second];
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
bail_out:
|
||||
throw std::invalid_argument(string("Unknown register ") + reg_name);
|
||||
}
|
||||
|
||||
uint64_t get_reg(string ®_name)
|
||||
{
|
||||
uint64_t get_reg(string& reg_name) {
|
||||
return reg_op(reg_name, 0, false);
|
||||
}
|
||||
|
||||
void set_reg(string ®_name, uint64_t val)
|
||||
{
|
||||
void set_reg(string& reg_name, uint64_t val) {
|
||||
reg_op(reg_name, val, true);
|
||||
}
|
||||
|
|
|
@ -21,20 +21,20 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
// The opcodes for the processor - ppcopcodes.cpp
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <cinttypes>
|
||||
#include <array>
|
||||
#include <stdio.h>
|
||||
#include <stdexcept>
|
||||
#include "ppcemu.h"
|
||||
#include "ppcmmu.h"
|
||||
#include <array>
|
||||
#include <cfenv>
|
||||
#include <cinttypes>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <unordered_map>
|
||||
|
||||
//Used for FP calcs
|
||||
// Used for FP calcs
|
||||
uint64_t ppc_result64_a;
|
||||
uint64_t ppc_result64_b;
|
||||
uint64_t ppc_result64_c;
|
||||
|
@ -48,7 +48,7 @@ double ppc_dblresult64_d;
|
|||
double snan = std::numeric_limits<double>::signaling_NaN();
|
||||
double qnan = std::numeric_limits<double>::quiet_NaN();
|
||||
|
||||
//Storage and register retrieval functions for the floating point functions.
|
||||
// Storage and register retrieval functions for the floating point functions.
|
||||
|
||||
double fp_return_double(uint32_t reg) {
|
||||
return ppc_state.fpr[reg].dbl64_r;
|
||||
|
@ -62,8 +62,7 @@ void ppc_store_sfpresult(bool int_rep) {
|
|||
if (int_rep) {
|
||||
ppc_state.fpr[reg_d].int64_r = ppc_result64_d;
|
||||
ppc_state.fpr[reg_d].dbl64_r = *(double*)&ppc_result64_d;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_state.fpr[reg_d].dbl64_r = ppc_dblresult64_d;
|
||||
ppc_state.fpr[reg_d].int64_r = *(uint64_t*)&ppc_dblresult64_d;
|
||||
}
|
||||
|
@ -73,8 +72,7 @@ void ppc_store_dfpresult(bool int_rep) {
|
|||
if (int_rep) {
|
||||
ppc_state.fpr[reg_d].int64_r = ppc_result64_d;
|
||||
ppc_state.fpr[reg_d].dbl64_r = *(double*)&ppc_result64_d;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_state.fpr[reg_d].dbl64_r = ppc_dblresult64_d;
|
||||
ppc_state.fpr[reg_d].int64_r = *(uint64_t*)&ppc_dblresult64_d;
|
||||
}
|
||||
|
@ -85,8 +83,7 @@ void ppc_grab_regsfpdb(bool int_rep) {
|
|||
reg_b = (ppc_cur_instruction >> 11) & 31;
|
||||
if (int_rep) {
|
||||
ppc_result64_b = ppc_state.fpr[reg_b].int64_r;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_dblresult64_b = ppc_state.fpr[reg_b].dbl64_r;
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +93,6 @@ void ppc_grab_regsfpdiab(bool int_rep) {
|
|||
reg_a = (ppc_cur_instruction >> 16) & 31;
|
||||
reg_b = (ppc_cur_instruction >> 11) & 31;
|
||||
if (int_rep == true) {
|
||||
|
||||
}
|
||||
ppc_result_a = ppc_state.gpr[reg_a];
|
||||
ppc_result_b = ppc_state.gpr[reg_b];
|
||||
|
@ -132,8 +128,7 @@ void ppc_grab_regsfpsab(bool int_rep) {
|
|||
ppc_result64_d = ppc_state.fpr[reg_s].int64_r;
|
||||
ppc_result64_a = ppc_state.fpr[reg_a].int64_r;
|
||||
ppc_result64_b = ppc_state.fpr[reg_b].int64_r;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_dblresult64_d = fp_return_double(reg_s);
|
||||
ppc_dblresult64_a = fp_return_double(reg_a);
|
||||
ppc_dblresult64_c = fp_return_double(reg_c);
|
||||
|
@ -147,8 +142,7 @@ void ppc_grab_regsfpdab(bool int_rep) {
|
|||
if (int_rep) {
|
||||
ppc_result64_a = fp_return_uint64(reg_a);
|
||||
ppc_result64_b = fp_return_uint64(reg_b);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_dblresult64_a = fp_return_double(reg_a);
|
||||
ppc_dblresult64_b = fp_return_double(reg_b);
|
||||
}
|
||||
|
@ -161,8 +155,7 @@ void ppc_grab_regsfpdac(bool int_rep) {
|
|||
if (int_rep) {
|
||||
ppc_result64_a = fp_return_uint64(reg_a);
|
||||
ppc_result64_c = fp_return_uint64(reg_c);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_dblresult64_a = fp_return_double(reg_a);
|
||||
ppc_dblresult64_c = fp_return_double(reg_c);
|
||||
}
|
||||
|
@ -177,8 +170,7 @@ void ppc_grab_regsfpdabc(bool int_rep) {
|
|||
ppc_result64_a = fp_return_uint64(reg_a);
|
||||
ppc_result64_b = fp_return_uint64(reg_b);
|
||||
ppc_result64_c = fp_return_uint64(reg_c);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_dblresult64_a = fp_return_double(reg_a);
|
||||
ppc_dblresult64_b = fp_return_double(reg_b);
|
||||
ppc_dblresult64_c = fp_return_double(reg_c);
|
||||
|
@ -203,7 +195,6 @@ void fp_save_uint64(uint64_t entry) {
|
|||
void fp_save_uint32(uint32_t entry) {
|
||||
ppc_state.fpr[reg_d].int64_r = entry;
|
||||
ppc_state.fpr[reg_d].dbl64_r = (double)entry;
|
||||
|
||||
}
|
||||
|
||||
void ppc_fp_changecrf1() {
|
||||
|
@ -222,8 +213,7 @@ void ppc_divbyzero(uint64_t input_a, uint64_t input_b, bool is_single) {
|
|||
int64_t round_to_nearest(double f) {
|
||||
if (f >= 0.0) {
|
||||
return (int32_t)(int64_t)(f + 0.5);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return (int32_t)(-(int64_t)(-f + 0.5));
|
||||
}
|
||||
}
|
||||
|
@ -265,8 +255,7 @@ bool ppc_confirm_inf_nan(uint32_t chosen_reg_1, uint32_t chosen_reg_2, bool is_s
|
|||
ppc_state.fpscr |= 0x80400000;
|
||||
ppc_toggle_fpscr_fex();
|
||||
return true;
|
||||
}
|
||||
else if ((input_a == 0) & (input_b == 0)) {
|
||||
} else if ((input_a == 0) & (input_b == 0)) {
|
||||
ppc_state.fpscr |= 0x80200000;
|
||||
ppc_toggle_fpscr_fex();
|
||||
return true;
|
||||
|
@ -297,8 +286,7 @@ bool ppc_confirm_inf_nan(uint32_t chosen_reg_1, uint32_t chosen_reg_2, bool is_s
|
|||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
uint32_t exp_a = (input_a >> 52) & 0x7ff;
|
||||
uint32_t exp_b = (input_b >> 52) & 0x7ff;
|
||||
|
||||
|
@ -310,8 +298,7 @@ bool ppc_confirm_inf_nan(uint32_t chosen_reg_1, uint32_t chosen_reg_2, bool is_s
|
|||
ppc_state.fpscr |= 0x80400000;
|
||||
ppc_toggle_fpscr_fex();
|
||||
return true;
|
||||
}
|
||||
else if ((input_a == 0) & (input_b == 0)) {
|
||||
} else if ((input_a == 0) & (input_b == 0)) {
|
||||
ppc_state.fpscr |= 0x80200000;
|
||||
ppc_toggle_fpscr_fex();
|
||||
return true;
|
||||
|
@ -348,7 +335,6 @@ bool ppc_confirm_inf_nan(uint32_t chosen_reg_1, uint32_t chosen_reg_2, bool is_s
|
|||
}
|
||||
|
||||
void fpresult_update(uint64_t set_result, bool confirm_arc) {
|
||||
|
||||
bool confirm_ov = (bool)std::fetestexcept(FE_OVERFLOW);
|
||||
|
||||
if (confirm_ov) {
|
||||
|
@ -362,15 +348,12 @@ void fpresult_update(uint64_t set_result, bool confirm_arc) {
|
|||
|
||||
if (set_result == 0) {
|
||||
ppc_state.fpscr |= 0x2000;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (set_result < 0) {
|
||||
ppc_state.fpscr |= 0x8000;
|
||||
}
|
||||
else if (set_result > 0) {
|
||||
} else if (set_result > 0) {
|
||||
ppc_state.fpscr |= 0x4000;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_state.fpscr |= 0x1000;
|
||||
}
|
||||
}
|
||||
|
@ -378,9 +361,7 @@ void fpresult_update(uint64_t set_result, bool confirm_arc) {
|
|||
}
|
||||
|
||||
void ppc_frsqrte_result() {
|
||||
|
||||
if (ppc_result64_d & 0x007FF000000000000UL) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -389,7 +370,7 @@ void ppc_changecrf1() {
|
|||
ppc_state.cr |= (ppc_state.fpscr & 0xF0000000) >> 4;
|
||||
}
|
||||
|
||||
//Floating Point Arithmetic
|
||||
// Floating Point Arithmetic
|
||||
void ppc_fadd() {
|
||||
ppc_grab_regsfpdab(false);
|
||||
|
||||
|
@ -638,7 +619,6 @@ void ppc_fmultsdot() {
|
|||
ppc_grab_regsfpdac(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 50)) {
|
||||
|
||||
float intermediate = (float)ppc_dblresult64_a * (float)ppc_dblresult64_b;
|
||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
||||
ppc_store_dfpresult(false);
|
||||
|
@ -682,7 +662,6 @@ void ppc_fmadds() {
|
|||
ppc_store_dfpresult(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ppc_fmaddsdot() {
|
||||
|
@ -717,8 +696,6 @@ void ppc_fmsubs() {
|
|||
ppc_store_dfpresult(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ppc_fmsubsdot() {
|
||||
|
@ -793,7 +770,6 @@ void ppc_fnmsubs() {
|
|||
ppc_store_dfpresult(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ppc_fnmsubsdot() {
|
||||
|
@ -873,8 +849,7 @@ void ppc_fsel() {
|
|||
|
||||
if (ppc_dblresult64_a >= 0.0) {
|
||||
ppc_dblresult64_d = ppc_dblresult64_c;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_dblresult64_d = ppc_dblresult64_b;
|
||||
}
|
||||
|
||||
|
@ -886,8 +861,7 @@ void ppc_fseldot() {
|
|||
|
||||
if (ppc_dblresult64_a >= 0.0) {
|
||||
ppc_dblresult64_d = ppc_dblresult64_c;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_dblresult64_d = ppc_dblresult64_b;
|
||||
}
|
||||
|
||||
|
@ -1001,7 +975,6 @@ void ppc_fctiw() {
|
|||
}
|
||||
|
||||
ppc_store_dfpresult(true);
|
||||
|
||||
}
|
||||
|
||||
void ppc_fctiwdot() {
|
||||
|
@ -1037,7 +1010,7 @@ void ppc_fctiwzdot() {
|
|||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
//Floating Point Store and Load
|
||||
// Floating Point Store and Load
|
||||
|
||||
void ppc_lfs() {
|
||||
ppc_grab_regsfpdia(true);
|
||||
|
@ -1057,8 +1030,7 @@ void ppc_lfsu() {
|
|||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_dfpresult(true);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
}
|
||||
}
|
||||
|
@ -1078,8 +1050,7 @@ void ppc_lfsux() {
|
|||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_dfpresult(true);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
}
|
||||
}
|
||||
|
@ -1101,8 +1072,7 @@ void ppc_lfdu() {
|
|||
ppc_store_dfpresult(true);
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
}
|
||||
}
|
||||
|
@ -1122,8 +1092,7 @@ void ppc_lfdux() {
|
|||
ppc_store_dfpresult(true);
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
}
|
||||
}
|
||||
|
@ -1143,8 +1112,7 @@ void ppc_stfsu() {
|
|||
mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
}
|
||||
}
|
||||
|
@ -1162,8 +1130,7 @@ void ppc_stfsux() {
|
|||
mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
}
|
||||
}
|
||||
|
@ -1183,8 +1150,7 @@ void ppc_stfdu() {
|
|||
mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
}
|
||||
}
|
||||
|
@ -1202,8 +1168,7 @@ void ppc_stfdux() {
|
|||
mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
}
|
||||
}
|
||||
|
@ -1214,7 +1179,7 @@ void ppc_stfiwx() {
|
|||
mem_write_dword(ppc_effective_address, (uint32_t)(ppc_state.fpr[reg_s].int64_r));
|
||||
}
|
||||
|
||||
//Floating Point Register Transfer
|
||||
// Floating Point Register Transfer
|
||||
|
||||
void ppc_fmr() {
|
||||
ppc_grab_regsfpdb(true);
|
||||
|
@ -1275,14 +1240,16 @@ void ppc_mtfsfi() {
|
|||
ppc_result_b = (ppc_cur_instruction >> 11) & 15;
|
||||
crf_d = (ppc_cur_instruction >> 23) & 7;
|
||||
crf_d = crf_d << 2;
|
||||
ppc_state.fpscr = (ppc_state.cr & ~(0xF0000000UL >> crf_d)) | ((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> crf_d);
|
||||
ppc_state.fpscr = (ppc_state.cr & ~(0xF0000000UL >> crf_d)) |
|
||||
((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> crf_d);
|
||||
}
|
||||
|
||||
void ppc_mtfsfidot() {
|
||||
ppc_result_b = (ppc_cur_instruction >> 11) & 15;
|
||||
crf_d = (ppc_cur_instruction >> 23) & 7;
|
||||
crf_d = crf_d << 2;
|
||||
ppc_state.fpscr = (ppc_state.cr & ~(0xF0000000UL >> crf_d)) | ((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> crf_d);
|
||||
ppc_state.fpscr = (ppc_state.cr & ~(0xF0000000UL >> crf_d)) |
|
||||
((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> crf_d);
|
||||
ppc_fp_changecrf1();
|
||||
}
|
||||
|
||||
|
@ -1321,10 +1288,11 @@ void ppc_mcrfs() {
|
|||
crf_d = crf_d << 2;
|
||||
crf_s = (ppc_cur_instruction >> 18) & 7;
|
||||
crf_s = crf_d << 2;
|
||||
ppc_state.cr = ~(ppc_state.cr & ((15 << (28 - crf_d)))) & (ppc_state.fpscr & (15 << (28 - crf_s)));
|
||||
ppc_state.cr = ~(ppc_state.cr & ((15 << (28 - crf_d)))) &
|
||||
(ppc_state.fpscr & (15 << (28 - crf_s)));
|
||||
}
|
||||
|
||||
//Floating Point Comparisons
|
||||
// Floating Point Comparisons
|
||||
|
||||
void ppc_fcmpo() {
|
||||
ppc_grab_regsfpsab(true);
|
||||
|
@ -1339,14 +1307,11 @@ void ppc_fcmpo() {
|
|||
|
||||
if (std::isnan(db_test_a) || std::isnan(db_test_b)) {
|
||||
cmp_c |= 0x01;
|
||||
}
|
||||
else if (db_test_a < db_test_b) {
|
||||
} else if (db_test_a < db_test_b) {
|
||||
cmp_c |= 0x08;
|
||||
}
|
||||
else if (db_test_a > db_test_b) {
|
||||
} else if (db_test_a > db_test_b) {
|
||||
cmp_c |= 0x04;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
cmp_c |= 0x02;
|
||||
}
|
||||
|
||||
|
@ -1358,11 +1323,9 @@ void ppc_fcmpo() {
|
|||
if (ppc_state.fpscr & 0x80) {
|
||||
ppc_state.fpscr |= 0x80000;
|
||||
}
|
||||
}
|
||||
else if ((db_test_a == qnan) || (db_test_b == qnan)) {
|
||||
} else if ((db_test_a == qnan) || (db_test_b == qnan)) {
|
||||
ppc_state.fpscr |= 0x80000;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ppc_fcmpu() {
|
||||
|
@ -1378,14 +1341,11 @@ void ppc_fcmpu() {
|
|||
|
||||
if (std::isnan(db_test_a) || std::isnan(db_test_b)) {
|
||||
cmp_c |= 0x01;
|
||||
}
|
||||
else if (db_test_a < db_test_b) {
|
||||
} else if (db_test_a < db_test_b) {
|
||||
cmp_c |= 0x08;
|
||||
}
|
||||
else if (db_test_a > db_test_b) {
|
||||
} else if (db_test_a > db_test_b) {
|
||||
cmp_c |= 0x04;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
cmp_c |= 0x02;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,26 +21,26 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
// The uniquely Gekko opcodes for the processor - ppcgekkoopcodes.cpp
|
||||
|
||||
#include "ppcemu.h"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include "ppcemu.h"
|
||||
|
||||
void ppc_psq_l(){
|
||||
void ppc_psq_l() {
|
||||
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void ppc_psq_lu(){
|
||||
void ppc_psq_lu() {
|
||||
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void ppc_psq_st(){
|
||||
void ppc_psq_st() {
|
||||
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void ppc_psq_stu(){
|
||||
void ppc_psq_stu() {
|
||||
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
@ -28,36 +28,36 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
- clarify what to do in the case of unaligned memory accesses
|
||||
*/
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <array>
|
||||
#include "memreadwrite.h"
|
||||
#include "ppcemu.h"
|
||||
#include "ppcmmu.h"
|
||||
#include "devices/memctrlbase.h"
|
||||
#include "memreadwrite.h"
|
||||
#include "ppcemu.h"
|
||||
#include <array>
|
||||
#include <cinttypes>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
/* pointer to exception handler to be called when a MMU exception is occured. */
|
||||
void (*mmu_exception_handler)(Except_Type exception_type, uint32_t srr1_bits);
|
||||
|
||||
/** PowerPC-style MMU BAT arrays (NULL initialization isn't prescribed). */
|
||||
PPC_BAT_entry ibat_array[4] = { {0} };
|
||||
PPC_BAT_entry dbat_array[4] = { {0} };
|
||||
PPC_BAT_entry ibat_array[4] = {{0}};
|
||||
PPC_BAT_entry dbat_array[4] = {{0}};
|
||||
|
||||
/** remember recently used physical memory regions for quicker translation. */
|
||||
AddressMapEntry last_read_area = { 0 };
|
||||
AddressMapEntry last_write_area = { 0 };
|
||||
AddressMapEntry last_exec_area = { 0 };
|
||||
AddressMapEntry last_ptab_area = { 0 };
|
||||
AddressMapEntry last_dma_area = { 0 };
|
||||
AddressMapEntry last_read_area = {0};
|
||||
AddressMapEntry last_write_area = {0};
|
||||
AddressMapEntry last_exec_area = {0};
|
||||
AddressMapEntry last_ptab_area = {0};
|
||||
AddressMapEntry last_dma_area = {0};
|
||||
|
||||
|
||||
/* macro for generating code reading from physical memory */
|
||||
#define READ_PHYS_MEM(ENTRY, ADDR, OP, SIZE, UNVAL) \
|
||||
{ \
|
||||
{ \
|
||||
if ((ADDR) >= (ENTRY).start && ((ADDR) + (SIZE)) <= (ENTRY).end) { \
|
||||
ret = OP((ENTRY).mem_ptr + ((ADDR) - (ENTRY).start)); \
|
||||
} else { \
|
||||
|
@ -68,26 +68,22 @@ AddressMapEntry last_dma_area = { 0 };
|
|||
(ENTRY).end = entry->end; \
|
||||
(ENTRY).mem_ptr = entry->mem_ptr; \
|
||||
ret = OP((ENTRY).mem_ptr + ((ADDR) - (ENTRY).start)); \
|
||||
} \
|
||||
else if (entry->type & RT_MMIO) { \
|
||||
ret = entry->devobj->read(entry->start, (ADDR) - entry->start, \
|
||||
(SIZE)); \
|
||||
} \
|
||||
else { \
|
||||
} else if (entry->type & RT_MMIO) { \
|
||||
ret = entry->devobj->read(entry->start, (ADDR)-entry->start, (SIZE)); \
|
||||
} else { \
|
||||
LOG_F(ERROR, "Please check your address map! \n"); \
|
||||
ret = (UNVAL); \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
} else { \
|
||||
LOG_F(WARNING, "Read from unmapped memory at 0x%08X!\n", (ADDR)); \
|
||||
ret = (UNVAL); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
}
|
||||
|
||||
/* macro for generating code writing to physical memory */
|
||||
#define WRITE_PHYS_MEM(ENTRY, ADDR, OP, VAL, SIZE) \
|
||||
{ \
|
||||
{ \
|
||||
if ((ADDR) >= (ENTRY).start && ((ADDR) + (SIZE)) <= (ENTRY).end) { \
|
||||
OP((ENTRY).mem_ptr + ((ADDR) - (ENTRY).start), (VAL)); \
|
||||
} else { \
|
||||
|
@ -98,48 +94,39 @@ AddressMapEntry last_dma_area = { 0 };
|
|||
(ENTRY).end = entry->end; \
|
||||
(ENTRY).mem_ptr = entry->mem_ptr; \
|
||||
OP((ENTRY).mem_ptr + ((ADDR) - (ENTRY).start), (VAL)); \
|
||||
} \
|
||||
else if (entry->type & RT_MMIO) { \
|
||||
entry->devobj->write(entry->start, (ADDR) - entry->start, \
|
||||
(VAL), (SIZE)); \
|
||||
} \
|
||||
else { \
|
||||
} else if (entry->type & RT_MMIO) { \
|
||||
entry->devobj->write(entry->start, (ADDR)-entry->start, (VAL), (SIZE)); \
|
||||
} else { \
|
||||
LOG_F(ERROR, "Please check your address map!\n"); \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
} else { \
|
||||
LOG_F(WARNING, "Write to unmapped memory at 0x%08X!\n", (ADDR)); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *mmu_get_dma_mem(uint32_t addr, uint32_t size)
|
||||
{
|
||||
uint8_t* mmu_get_dma_mem(uint32_t addr, uint32_t size) {
|
||||
if (addr >= last_dma_area.start && (addr + size) <= last_dma_area.end) {
|
||||
return last_dma_area.mem_ptr + (addr - last_dma_area.start);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
AddressMapEntry* entry = mem_ctrl_instance->find_range(addr);
|
||||
if (entry && entry->type & (RT_ROM | RT_RAM)) {
|
||||
last_dma_area.start = entry->start;
|
||||
last_dma_area.end = entry->end;
|
||||
last_dma_area.mem_ptr = entry->mem_ptr;
|
||||
return last_dma_area.mem_ptr + (addr - last_dma_area.start);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(ERROR, "SOS: DMA access to unmapped memory %08X!\n", addr);
|
||||
exit(-1); // FIXME: ugly error handling, must be the proper exception!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_set_cur_instruction(const uint8_t* ptr)
|
||||
{
|
||||
void ppc_set_cur_instruction(const uint8_t* ptr) {
|
||||
ppc_cur_instruction = READ_DWORD_BE_A(ptr);
|
||||
}
|
||||
|
||||
void ibat_update(uint32_t bat_reg)
|
||||
{
|
||||
void ibat_update(uint32_t bat_reg) {
|
||||
int upper_reg_num;
|
||||
uint32_t bl, lo_mask;
|
||||
PPC_BAT_entry* bat_entry;
|
||||
|
@ -159,8 +146,7 @@ void ibat_update(uint32_t bat_reg)
|
|||
}
|
||||
}
|
||||
|
||||
void dbat_update(uint32_t bat_reg)
|
||||
{
|
||||
void dbat_update(uint32_t bat_reg) {
|
||||
int upper_reg_num;
|
||||
uint32_t bl, lo_mask;
|
||||
PPC_BAT_entry* bat_entry;
|
||||
|
@ -180,41 +166,35 @@ void dbat_update(uint32_t bat_reg)
|
|||
}
|
||||
}
|
||||
|
||||
static inline uint8_t* calc_pteg_addr(uint32_t hash)
|
||||
{
|
||||
static inline uint8_t* calc_pteg_addr(uint32_t hash) {
|
||||
uint32_t sdr1_val, pteg_addr;
|
||||
|
||||
sdr1_val = ppc_state.spr[SPR::SDR1];
|
||||
|
||||
pteg_addr = sdr1_val & 0xFE000000;
|
||||
pteg_addr |= (sdr1_val & 0x01FF0000) |
|
||||
(((sdr1_val & 0x1FF) << 16) & ((hash & 0x7FC00) << 6));
|
||||
pteg_addr |= (sdr1_val & 0x01FF0000) | (((sdr1_val & 0x1FF) << 16) & ((hash & 0x7FC00) << 6));
|
||||
pteg_addr |= (hash & 0x3FF) << 6;
|
||||
|
||||
if (pteg_addr >= last_ptab_area.start && pteg_addr <= last_ptab_area.end) {
|
||||
return last_ptab_area.mem_ptr + (pteg_addr - last_ptab_area.start);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
AddressMapEntry* entry = mem_ctrl_instance->find_range(pteg_addr);
|
||||
if (entry && entry->type & (RT_ROM | RT_RAM)) {
|
||||
last_ptab_area.start = entry->start;
|
||||
last_ptab_area.end = entry->end;
|
||||
last_ptab_area.mem_ptr = entry->mem_ptr;
|
||||
return last_ptab_area.mem_ptr + (pteg_addr - last_ptab_area.start);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(ERROR, "SOS: no page table region was found at %08X!\n", pteg_addr);
|
||||
exit(-1); // FIXME: ugly error handling, must be the proper exception!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool search_pteg(uint8_t* pteg_addr, uint8_t** ret_pte_addr,
|
||||
uint32_t vsid, uint16_t page_index, uint8_t pteg_num)
|
||||
{
|
||||
static bool search_pteg(
|
||||
uint8_t* pteg_addr, uint8_t** ret_pte_addr, uint32_t vsid, uint16_t page_index, uint8_t pteg_num) {
|
||||
/* construct PTE matching word */
|
||||
uint32_t pte_check = 0x80000000 | (vsid << 7) | (pteg_num << 6) |
|
||||
(page_index >> 10);
|
||||
uint32_t pte_check = 0x80000000 | (vsid << 7) | (pteg_num << 6) | (page_index >> 10);
|
||||
|
||||
#ifdef MMU_INTEGRITY_CHECKS
|
||||
/* PTEG integrity check that ensures that all matching PTEs have
|
||||
|
@ -229,8 +209,7 @@ static bool search_pteg(uint8_t* pteg_addr, uint8_t** ret_pte_addr,
|
|||
LOG_F(ERROR, "Multiple PTEs with different RPN/WIMG/PP found!\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* isolate RPN, WIMG and PP fields */
|
||||
pte_word2_check = READ_DWORD_BE_A(pteg_addr) & 0xFFFFF07B;
|
||||
*ret_pte_addr = pteg_addr;
|
||||
|
@ -249,9 +228,7 @@ static bool search_pteg(uint8_t* pteg_addr, uint8_t** ret_pte_addr,
|
|||
return false;
|
||||
}
|
||||
|
||||
static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
|
||||
unsigned msr_pr, int is_write)
|
||||
{
|
||||
static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch, unsigned msr_pr, int is_write) {
|
||||
uint32_t sr_val, page_index, pteg_hash1, vsid, pte_word2;
|
||||
unsigned key, pp;
|
||||
uint8_t* pte_addr;
|
||||
|
@ -275,8 +252,7 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
|
|||
if (!search_pteg(calc_pteg_addr(~pteg_hash1), &pte_addr, vsid, page_index, 1)) {
|
||||
if (is_instr_fetch) {
|
||||
mmu_exception_handler(Except_Type::EXC_ISI, 0x40000000);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_state.spr[SPR::DSISR] = 0x40000000 | (is_write << 25);
|
||||
ppc_state.spr[SPR::DAR] = la;
|
||||
mmu_exception_handler(Except_Type::EXC_DSI, 0);
|
||||
|
@ -286,7 +262,7 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
|
|||
|
||||
pte_word2 = READ_DWORD_BE_A(pte_addr + 4);
|
||||
|
||||
key = (((sr_val >> 29) & 1)& msr_pr) | (((sr_val >> 30) & 1)& (msr_pr ^ 1));
|
||||
key = (((sr_val >> 29) & 1) & msr_pr) | (((sr_val >> 30) & 1) & (msr_pr ^ 1));
|
||||
|
||||
/* check page access */
|
||||
pp = pte_word2 & 3;
|
||||
|
@ -298,8 +274,7 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
|
|||
if ((key && (!pp || (pp == 1 && is_write))) || (pp == 3 && is_write)) {
|
||||
if (is_instr_fetch) {
|
||||
mmu_exception_handler(Except_Type::EXC_ISI, 0x08000000);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_state.spr[SPR::DSISR] = 0x08000000 | (is_write << 25);
|
||||
ppc_state.spr[SPR::DAR] = la;
|
||||
mmu_exception_handler(Except_Type::EXC_DSI, 0);
|
||||
|
@ -318,8 +293,7 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
|
|||
}
|
||||
|
||||
/** PowerPC-style MMU instruction address translation. */
|
||||
static uint32_t ppc_mmu_instr_translate(uint32_t la)
|
||||
{
|
||||
static uint32_t ppc_mmu_instr_translate(uint32_t la) {
|
||||
uint32_t pa; /* translated physical address */
|
||||
|
||||
bool bat_hit = false;
|
||||
|
@ -333,8 +307,7 @@ static uint32_t ppc_mmu_instr_translate(uint32_t la)
|
|||
for (int bat_index = 0; bat_index < 4; bat_index++) {
|
||||
PPC_BAT_entry* bat_entry = &ibat_array[bat_index];
|
||||
|
||||
if ((bat_entry->access & access_bits) &&
|
||||
((la & ~bat_entry->lo_mask) == bat_entry->bepi)) {
|
||||
if ((bat_entry->access & access_bits) && ((la & ~bat_entry->lo_mask) == bat_entry->bepi)) {
|
||||
bat_hit = true;
|
||||
|
||||
if (!bat_entry->prot) {
|
||||
|
@ -356,8 +329,7 @@ static uint32_t ppc_mmu_instr_translate(uint32_t la)
|
|||
}
|
||||
|
||||
/** PowerPC-style MMU data address translation. */
|
||||
static uint32_t ppc_mmu_addr_translate(uint32_t la, int is_write)
|
||||
{
|
||||
static uint32_t ppc_mmu_addr_translate(uint32_t la, int is_write) {
|
||||
#ifdef PROFILER
|
||||
mmu_translations_num++;
|
||||
#endif
|
||||
|
@ -375,8 +347,7 @@ static uint32_t ppc_mmu_addr_translate(uint32_t la, int is_write)
|
|||
for (int bat_index = 0; bat_index < 4; bat_index++) {
|
||||
PPC_BAT_entry* bat_entry = &dbat_array[bat_index];
|
||||
|
||||
if ((bat_entry->access & access_bits) &&
|
||||
((la & ~bat_entry->lo_mask) == bat_entry->bepi)) {
|
||||
if ((bat_entry->access & access_bits) && ((la & ~bat_entry->lo_mask) == bat_entry->bepi)) {
|
||||
bat_hit = true;
|
||||
|
||||
if (!bat_entry->prot || ((bat_entry->prot & 1) && is_write)) {
|
||||
|
@ -399,13 +370,12 @@ static uint32_t ppc_mmu_addr_translate(uint32_t la, int is_write)
|
|||
return pa;
|
||||
}
|
||||
|
||||
static void mem_write_unaligned(uint32_t addr, uint32_t value, uint32_t size)
|
||||
{
|
||||
static void mem_write_unaligned(uint32_t addr, uint32_t value, uint32_t size) {
|
||||
LOG_F(WARNING, "Attempt to write unaligned %d bytes to 0x%08X\n", size, addr);
|
||||
|
||||
if (((addr & 0xFFF) + size) > 0x1000) {
|
||||
LOG_F(ERROR, "SOS! Cross-page unaligned write, addr=%08X, size=%d\n", addr, size);
|
||||
exit(-1); //FIXME!
|
||||
exit(-1); // FIXME!
|
||||
} else {
|
||||
/* data address translation if enabled */
|
||||
if (ppc_state.msr & 0x10) {
|
||||
|
@ -420,20 +390,18 @@ static void mem_write_unaligned(uint32_t addr, uint32_t value, uint32_t size)
|
|||
}
|
||||
}
|
||||
|
||||
void mem_write_byte(uint32_t addr, uint8_t value)
|
||||
{
|
||||
void mem_write_byte(uint32_t addr, uint8_t value) {
|
||||
/* data address translation if enabled */
|
||||
if (ppc_state.msr & 0x10) {
|
||||
addr = ppc_mmu_addr_translate(addr, 1);
|
||||
}
|
||||
|
||||
#define WRITE_BYTE(addr, val) (*(addr) = val)
|
||||
#define WRITE_BYTE(addr, val) (*(addr) = val)
|
||||
|
||||
WRITE_PHYS_MEM(last_write_area, addr, WRITE_BYTE, value, 1);
|
||||
}
|
||||
|
||||
void mem_write_word(uint32_t addr, uint16_t value)
|
||||
{
|
||||
void mem_write_word(uint32_t addr, uint16_t value) {
|
||||
if (addr & 1) {
|
||||
mem_write_unaligned(addr, value, 2);
|
||||
}
|
||||
|
@ -446,8 +414,7 @@ void mem_write_word(uint32_t addr, uint16_t value)
|
|||
WRITE_PHYS_MEM(last_write_area, addr, WRITE_WORD_BE_A, value, 2);
|
||||
}
|
||||
|
||||
void mem_write_dword(uint32_t addr, uint32_t value)
|
||||
{
|
||||
void mem_write_dword(uint32_t addr, uint32_t value) {
|
||||
if (addr & 3) {
|
||||
mem_write_unaligned(addr, value, 4);
|
||||
}
|
||||
|
@ -460,11 +427,10 @@ void mem_write_dword(uint32_t addr, uint32_t value)
|
|||
WRITE_PHYS_MEM(last_write_area, addr, WRITE_DWORD_BE_A, value, 4);
|
||||
}
|
||||
|
||||
void mem_write_qword(uint32_t addr, uint64_t value)
|
||||
{
|
||||
void mem_write_qword(uint32_t addr, uint64_t value) {
|
||||
if (addr & 7) {
|
||||
LOG_F(ERROR, "SOS! Attempt to write unaligned QWORD to 0x%08X\n", addr);
|
||||
exit(-1); //FIXME!
|
||||
exit(-1); // FIXME!
|
||||
}
|
||||
|
||||
/* data address translation if enabled */
|
||||
|
@ -475,15 +441,14 @@ void mem_write_qword(uint32_t addr, uint64_t value)
|
|||
WRITE_PHYS_MEM(last_write_area, addr, WRITE_QWORD_BE_A, value, 8);
|
||||
}
|
||||
|
||||
static uint32_t mem_grab_unaligned(uint32_t addr, uint32_t size)
|
||||
{
|
||||
static uint32_t mem_grab_unaligned(uint32_t addr, uint32_t size) {
|
||||
uint32_t ret = 0;
|
||||
|
||||
LOG_F(WARNING, "Attempt to read unaligned %d bytes from 0x%08X\n", size, addr);
|
||||
|
||||
if (((addr & 0xFFF) + size) > 0x1000) {
|
||||
LOG_F(ERROR, "SOS! Cross-page unaligned read, addr=%08X, size=%d\n", addr, size);
|
||||
exit(-1); //FIXME!
|
||||
exit(-1); // FIXME!
|
||||
} else {
|
||||
/* data address translation if enabled */
|
||||
if (ppc_state.msr & 0x10) {
|
||||
|
@ -501,8 +466,7 @@ static uint32_t mem_grab_unaligned(uint32_t addr, uint32_t size)
|
|||
}
|
||||
|
||||
/** Grab a value from memory into a register */
|
||||
uint8_t mem_grab_byte(uint32_t addr)
|
||||
{
|
||||
uint8_t mem_grab_byte(uint32_t addr) {
|
||||
uint8_t ret;
|
||||
|
||||
/* data address translation if enabled */
|
||||
|
@ -514,8 +478,7 @@ uint8_t mem_grab_byte(uint32_t addr)
|
|||
return ret;
|
||||
}
|
||||
|
||||
uint16_t mem_grab_word(uint32_t addr)
|
||||
{
|
||||
uint16_t mem_grab_word(uint32_t addr) {
|
||||
uint16_t ret;
|
||||
|
||||
if (addr & 1) {
|
||||
|
@ -531,8 +494,7 @@ uint16_t mem_grab_word(uint32_t addr)
|
|||
return ret;
|
||||
}
|
||||
|
||||
uint32_t mem_grab_dword(uint32_t addr)
|
||||
{
|
||||
uint32_t mem_grab_dword(uint32_t addr) {
|
||||
uint32_t ret;
|
||||
|
||||
if (addr & 3) {
|
||||
|
@ -548,13 +510,12 @@ uint32_t mem_grab_dword(uint32_t addr)
|
|||
return ret;
|
||||
}
|
||||
|
||||
uint64_t mem_grab_qword(uint32_t addr)
|
||||
{
|
||||
uint64_t mem_grab_qword(uint32_t addr) {
|
||||
uint64_t ret;
|
||||
|
||||
if (addr & 7) {
|
||||
LOG_F(ERROR, "SOS! Attempt to read unaligned QWORD at 0x%08X\n", addr);
|
||||
exit(-1); //FIXME!
|
||||
exit(-1); // FIXME!
|
||||
}
|
||||
|
||||
/* data address translation if enabled */
|
||||
|
@ -566,8 +527,7 @@ uint64_t mem_grab_qword(uint32_t addr)
|
|||
return ret;
|
||||
}
|
||||
|
||||
uint8_t* quickinstruction_translate(uint32_t addr)
|
||||
{
|
||||
uint8_t* quickinstruction_translate(uint32_t addr) {
|
||||
uint8_t* real_addr;
|
||||
|
||||
/* perform instruction address translation if enabled */
|
||||
|
@ -578,8 +538,7 @@ uint8_t* quickinstruction_translate(uint32_t addr)
|
|||
if (addr >= last_exec_area.start && addr <= last_exec_area.end) {
|
||||
real_addr = last_exec_area.mem_ptr + (addr - last_exec_area.start);
|
||||
ppc_set_cur_instruction(real_addr);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
AddressMapEntry* entry = mem_ctrl_instance->find_range(addr);
|
||||
if (entry && entry->type & (RT_ROM | RT_RAM)) {
|
||||
last_exec_area.start = entry->start;
|
||||
|
@ -587,8 +546,7 @@ uint8_t* quickinstruction_translate(uint32_t addr)
|
|||
last_exec_area.mem_ptr = entry->mem_ptr;
|
||||
real_addr = last_exec_area.mem_ptr + (addr - last_exec_area.start);
|
||||
ppc_set_cur_instruction(real_addr);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(WARNING, "attempt to execute code at %08X!\n", addr);
|
||||
exit(-1); // FIXME: ugly error handling, must be the proper exception!
|
||||
}
|
||||
|
@ -597,8 +555,7 @@ uint8_t* quickinstruction_translate(uint32_t addr)
|
|||
return real_addr;
|
||||
}
|
||||
|
||||
uint64_t mem_read_dbg(uint32_t virt_addr, uint32_t size)
|
||||
{
|
||||
uint64_t mem_read_dbg(uint32_t virt_addr, uint32_t size) {
|
||||
uint32_t save_dsisr, save_dar;
|
||||
uint64_t ret_val;
|
||||
|
||||
|
@ -608,7 +565,7 @@ uint64_t mem_read_dbg(uint32_t virt_addr, uint32_t size)
|
|||
mmu_exception_handler = dbg_exception_handler;
|
||||
|
||||
try {
|
||||
switch(size) {
|
||||
switch (size) {
|
||||
case 1:
|
||||
ret_val = mem_grab_byte(virt_addr);
|
||||
break;
|
||||
|
@ -624,8 +581,7 @@ uint64_t mem_read_dbg(uint32_t virt_addr, uint32_t size)
|
|||
default:
|
||||
ret_val = mem_grab_byte(virt_addr);
|
||||
}
|
||||
}
|
||||
catch (std::invalid_argument& exc) {
|
||||
} catch (std::invalid_argument& exc) {
|
||||
/* restore MMU-related CPU state */
|
||||
mmu_exception_handler = ppc_exception_handler;
|
||||
ppc_state.spr[SPR::DSISR] = save_dsisr;
|
||||
|
@ -643,7 +599,6 @@ uint64_t mem_read_dbg(uint32_t virt_addr, uint32_t size)
|
|||
return ret_val;
|
||||
}
|
||||
|
||||
void ppc_mmu_init()
|
||||
{
|
||||
void ppc_mmu_init() {
|
||||
mmu_exception_handler = ppc_exception_handler;
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef PPCMEMORY_H
|
||||
#define PPCMEMORY_H
|
||||
|
||||
#include <array>
|
||||
#include <cinttypes>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
/* Uncomment this to exhaustive MMU integrity checks. */
|
||||
//#define MMU_INTEGRITY_CHECKS
|
||||
|
@ -44,7 +44,7 @@ typedef struct PPC_BAT_entry {
|
|||
extern void ibat_update(uint32_t bat_reg);
|
||||
extern void dbat_update(uint32_t bat_reg);
|
||||
|
||||
extern uint8_t *mmu_get_dma_mem(uint32_t addr, uint32_t size);
|
||||
extern uint8_t* mmu_get_dma_mem(uint32_t addr, uint32_t size);
|
||||
|
||||
extern void ppc_set_cur_instruction(const uint8_t* ptr);
|
||||
extern void mem_write_byte(uint32_t addr, uint8_t value);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,34 +1,31 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "../ppcemu.h"
|
||||
#include "../ppcdisasm.h"
|
||||
#include "../ppcemu.h"
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int ntested; /* number of tested instructions */
|
||||
int nfailed; /* number of failed instructions */
|
||||
|
||||
void xer_ov_test(string mnem, uint32_t opcode)
|
||||
{
|
||||
void xer_ov_test(string mnem, uint32_t opcode) {
|
||||
ppc_state.gpr[3] = 2;
|
||||
ppc_state.gpr[4] = 2;
|
||||
ppc_state.spr[SPR::XER] = 0xFFFFFFFF;
|
||||
ppc_cur_instruction = opcode;
|
||||
ppc_main_opcode();
|
||||
if (ppc_state.spr[SPR::XER] & 0x40000000UL) {
|
||||
cout << "Invalid " << mnem << " emulation! XER[OV] should not be set."
|
||||
<< endl;
|
||||
cout << "Invalid " << mnem << " emulation! XER[OV] should not be set." << endl;
|
||||
nfailed++;
|
||||
}
|
||||
ntested++;
|
||||
}
|
||||
|
||||
void xer_update_test()
|
||||
{
|
||||
void xer_update_test() {
|
||||
xer_ov_test("ADDCO", 0x7C632414);
|
||||
xer_ov_test("ADDCO.", 0x7C632415);
|
||||
xer_ov_test("ADDO", 0x7C632614);
|
||||
|
@ -60,8 +57,7 @@ void xer_update_test()
|
|||
}
|
||||
|
||||
/** testing vehicle */
|
||||
static void read_test_data()
|
||||
{
|
||||
static void read_test_data() {
|
||||
string line, token;
|
||||
int i, lineno;
|
||||
uint32_t opcode, dest, src1, src2, check_xer, check_cr;
|
||||
|
@ -74,7 +70,7 @@ static void read_test_data()
|
|||
|
||||
lineno = 0;
|
||||
|
||||
while(getline(tfstream, line)) {
|
||||
while (getline(tfstream, line)) {
|
||||
lineno++;
|
||||
|
||||
if (line.empty() || !line.rfind("#", 0))
|
||||
|
@ -84,7 +80,7 @@ static void read_test_data()
|
|||
|
||||
vector<string> tokens;
|
||||
|
||||
while(getline(lnstream, token, ',' )) {
|
||||
while (getline(lnstream, token, ',')) {
|
||||
tokens.push_back(token);
|
||||
}
|
||||
|
||||
|
@ -113,8 +109,8 @@ static void read_test_data()
|
|||
} else if (tokens[i].rfind("CR=", 0) == 0) {
|
||||
check_cr = stoul(tokens[i].substr(3), NULL, 16);
|
||||
} else {
|
||||
cout << "Unknown parameter " << tokens[i] << " in line " << lineno <<
|
||||
". Exiting..." << endl;
|
||||
cout << "Unknown parameter " << tokens[i] << " in line " << lineno << ". Exiting..."
|
||||
<< endl;
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
@ -131,15 +127,13 @@ static void read_test_data()
|
|||
ntested++;
|
||||
|
||||
if ((tokens[0].rfind("CMP") && (ppc_state.gpr[3] != dest)) ||
|
||||
(ppc_state.spr[SPR::XER] != check_xer) ||
|
||||
(ppc_state.cr != check_cr)) {
|
||||
cout << "Mismatch: instr=" << tokens[0] << ", src1=0x" << hex << src1
|
||||
<< ", src2=0x" << hex << src2 << endl;
|
||||
cout << "expected: dest=0x" << hex << dest << ", XER=0x" << hex
|
||||
<< check_xer << ", CR=0x" << hex << check_cr << endl;
|
||||
cout << "got: dest=0x" << hex << ppc_state.gpr[3] << ", XER=0x"
|
||||
<< hex << ppc_state.spr[SPR::XER] << ", CR=0x" << hex
|
||||
<< ppc_state.cr << endl;
|
||||
(ppc_state.spr[SPR::XER] != check_xer) || (ppc_state.cr != check_cr)) {
|
||||
cout << "Mismatch: instr=" << tokens[0] << ", src1=0x" << hex << src1 << ", src2=0x"
|
||||
<< hex << src2 << endl;
|
||||
cout << "expected: dest=0x" << hex << dest << ", XER=0x" << hex << check_xer
|
||||
<< ", CR=0x" << hex << check_cr << endl;
|
||||
cout << "got: dest=0x" << hex << ppc_state.gpr[3] << ", XER=0x" << hex
|
||||
<< ppc_state.spr[SPR::XER] << ", CR=0x" << hex << ppc_state.cr << endl;
|
||||
cout << "Test file line #: " << dec << lineno << endl << endl;
|
||||
|
||||
nfailed++;
|
||||
|
@ -147,9 +141,7 @@ static void read_test_data()
|
|||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
int main() {
|
||||
cout << "Running DingusPPC emulator tests..." << endl << endl;
|
||||
|
||||
ntested = 0;
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "../ppcdisasm.h"
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/** testing vehicle */
|
||||
static vector<PPCDisasmContext> read_test_data()
|
||||
{
|
||||
static vector<PPCDisasmContext> read_test_data() {
|
||||
string line, token;
|
||||
int i, lineno;
|
||||
PPCDisasmContext ctx;
|
||||
|
@ -24,7 +23,7 @@ static vector<PPCDisasmContext> read_test_data()
|
|||
|
||||
lineno = 0;
|
||||
|
||||
while(getline(tfstream, line)) {
|
||||
while (getline(tfstream, line)) {
|
||||
lineno++;
|
||||
|
||||
if (line.empty() || !line.rfind("#", 0))
|
||||
|
@ -34,8 +33,8 @@ static vector<PPCDisasmContext> read_test_data()
|
|||
|
||||
vector<string> tokens;
|
||||
|
||||
while(getline(lnstream, token, ',' )) {
|
||||
//cout << "Token: " << token << endl;
|
||||
while (getline(lnstream, token, ',')) {
|
||||
// cout << "Token: " << token << endl;
|
||||
tokens.push_back(token);
|
||||
}
|
||||
|
||||
|
@ -64,7 +63,7 @@ static vector<PPCDisasmContext> read_test_data()
|
|||
|
||||
ctx.instr_str = idisasm.str();
|
||||
|
||||
//cout << idisasm.str() << endl;
|
||||
// cout << idisasm.str() << endl;
|
||||
|
||||
tstvec.push_back(ctx);
|
||||
}
|
||||
|
@ -72,8 +71,7 @@ static vector<PPCDisasmContext> read_test_data()
|
|||
return tstvec;
|
||||
}
|
||||
|
||||
int test_ppc_disasm()
|
||||
{
|
||||
int test_ppc_disasm() {
|
||||
int i, nfailed;
|
||||
PPCDisasmContext ctx;
|
||||
|
||||
|
@ -92,14 +90,13 @@ int test_ppc_disasm()
|
|||
std::string disas = disassemble_single(&ctx);
|
||||
|
||||
if (disas != testdata[i].instr_str) {
|
||||
cout << "Mismatch found, expected={" << testdata[i].instr_str <<
|
||||
"}, got={" << disas << "}" << endl;
|
||||
cout << "Mismatch found, expected={" << testdata[i].instr_str << "}, got={" << disas
|
||||
<< "}" << endl;
|
||||
nfailed++;
|
||||
}
|
||||
}
|
||||
|
||||
cout << "Tested " << testdata.size() << " instructions. Failed: " <<
|
||||
nfailed << "." << endl;
|
||||
cout << "Tested " << testdata.size() << " instructions. Failed: " << nfailed << "." << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -19,43 +19,38 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include "../cpu/ppc/ppcdisasm.h"
|
||||
#include "../cpu/ppc/ppcemu.h"
|
||||
#include "../cpu/ppc/ppcmmu.h"
|
||||
#include "../cpu/ppc/ppcdisasm.h"
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
static uint32_t str2addr(string& addr_str)
|
||||
{
|
||||
static uint32_t str2addr(string& addr_str) {
|
||||
try {
|
||||
return stoul(addr_str, NULL, 0);
|
||||
}
|
||||
catch (invalid_argument& exc) {
|
||||
} catch (invalid_argument& exc) {
|
||||
throw invalid_argument(string("Cannot convert ") + addr_str);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t str2num(string& num_str)
|
||||
{
|
||||
static uint32_t str2num(string& num_str) {
|
||||
try {
|
||||
return stol(num_str, NULL, 0);
|
||||
}
|
||||
catch (invalid_argument & exc) {
|
||||
} catch (invalid_argument& exc) {
|
||||
throw invalid_argument(string("Cannot convert ") + num_str);
|
||||
}
|
||||
}
|
||||
|
||||
static void show_help()
|
||||
{
|
||||
static void show_help() {
|
||||
cout << "Debugger commands:" << endl;
|
||||
cout << " step -- execute single instruction" << endl;
|
||||
cout << " si -- shortcut for step" << endl;
|
||||
|
@ -80,8 +75,7 @@ static void show_help()
|
|||
cout << "Pressing ENTER will repeat last command." << endl;
|
||||
}
|
||||
|
||||
static void disasm(uint32_t count, uint32_t address)
|
||||
{
|
||||
static void disasm(uint32_t count, uint32_t address) {
|
||||
PPCDisasmContext ctx;
|
||||
|
||||
ctx.instr_addr = address;
|
||||
|
@ -94,8 +88,7 @@ static void disasm(uint32_t count, uint32_t address)
|
|||
}
|
||||
}
|
||||
|
||||
static void dump_mem(string& params)
|
||||
{
|
||||
static void dump_mem(string& params) {
|
||||
int cell_size, chars_per_line;
|
||||
bool is_char;
|
||||
uint32_t count, addr;
|
||||
|
@ -114,7 +107,7 @@ static void dump_mem(string& params)
|
|||
|
||||
is_char = false;
|
||||
|
||||
switch(num_type_str.back()) {
|
||||
switch (num_type_str.back()) {
|
||||
case 'b':
|
||||
case 'B':
|
||||
cell_size = 1;
|
||||
|
@ -144,21 +137,18 @@ static void dump_mem(string& params)
|
|||
try {
|
||||
num_type_str = num_type_str.substr(0, num_type_str.length() - 1);
|
||||
count = str2addr(num_type_str);
|
||||
}
|
||||
catch (invalid_argument& exc) {
|
||||
} catch (invalid_argument& exc) {
|
||||
cout << exc.what() << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
addr = str2addr(addr_str);
|
||||
}
|
||||
catch (invalid_argument& exc) {
|
||||
} catch (invalid_argument& exc) {
|
||||
try {
|
||||
/* number conversion failed, trying reg name */
|
||||
addr = get_reg(addr_str);
|
||||
}
|
||||
catch (invalid_argument& exc) {
|
||||
} catch (invalid_argument& exc) {
|
||||
cout << exc.what() << endl;
|
||||
return;
|
||||
}
|
||||
|
@ -179,13 +169,11 @@ static void dump_mem(string& params)
|
|||
cout << (char)val;
|
||||
chars_per_line += cell_size;
|
||||
} else {
|
||||
cout << setw(cell_size * 2) << setfill('0') << uppercase <<
|
||||
hex << val << " ";
|
||||
cout << setw(cell_size * 2) << setfill('0') << uppercase << hex << val << " ";
|
||||
chars_per_line += cell_size * 2 + 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (invalid_argument& exc) {
|
||||
} catch (invalid_argument& exc) {
|
||||
cout << exc.what() << endl;
|
||||
return;
|
||||
}
|
||||
|
@ -193,10 +181,8 @@ static void dump_mem(string& params)
|
|||
cout << endl << endl;
|
||||
}
|
||||
|
||||
void enter_debugger()
|
||||
{
|
||||
string inp, cmd, addr_str, expr_str, reg_expr, last_cmd, reg_value_str,
|
||||
inst_string, inst_num_str;
|
||||
void enter_debugger() {
|
||||
string inp, cmd, addr_str, expr_str, reg_expr, last_cmd, reg_value_str, inst_string, inst_num_str;
|
||||
uint32_t addr, inst_grab;
|
||||
std::stringstream ss;
|
||||
int log_level;
|
||||
|
@ -223,8 +209,7 @@ void enter_debugger()
|
|||
}
|
||||
if (cmd == "help") {
|
||||
show_help();
|
||||
}
|
||||
else if (cmd == "quit") {
|
||||
} else if (cmd == "quit") {
|
||||
break;
|
||||
}
|
||||
#ifdef PROFILER
|
||||
|
@ -236,8 +221,7 @@ void enter_debugger()
|
|||
#endif
|
||||
else if (cmd == "regs") {
|
||||
print_gprs();
|
||||
}
|
||||
else if (cmd == "set") {
|
||||
} else if (cmd == "set") {
|
||||
ss >> expr_str;
|
||||
|
||||
separator_pos = expr_str.find_first_of("=");
|
||||
|
@ -256,35 +240,28 @@ void enter_debugger()
|
|||
continue;
|
||||
}
|
||||
loguru::g_stderr_verbosity = log_level;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
addr = str2addr(addr_str);
|
||||
set_reg(reg_expr, addr);
|
||||
}
|
||||
}
|
||||
catch (invalid_argument& exc) {
|
||||
} catch (invalid_argument& exc) {
|
||||
cout << exc.what() << endl;
|
||||
}
|
||||
}
|
||||
else if (cmd == "step" || cmd == "si") {
|
||||
} else if (cmd == "step" || cmd == "si") {
|
||||
ppc_exec_single();
|
||||
}
|
||||
else if (cmd == "next" || cmd == "ni") {
|
||||
} else if (cmd == "next" || cmd == "ni") {
|
||||
addr_str = "PC";
|
||||
addr = get_reg(addr_str) + 4;
|
||||
ppc_exec_until(addr);
|
||||
}
|
||||
else if (cmd == "until") {
|
||||
} else if (cmd == "until") {
|
||||
ss >> addr_str;
|
||||
try {
|
||||
addr = str2addr(addr_str);
|
||||
ppc_exec_until(addr);
|
||||
}
|
||||
catch (invalid_argument& exc) {
|
||||
} catch (invalid_argument& exc) {
|
||||
cout << exc.what() << endl;
|
||||
}
|
||||
}
|
||||
else if (cmd == "disas") {
|
||||
} else if (cmd == "disas") {
|
||||
expr_str = "";
|
||||
ss >> expr_str;
|
||||
if (expr_str.length() > 0) {
|
||||
|
@ -298,37 +275,31 @@ void enter_debugger()
|
|||
addr_str = expr_str.substr(expr_str.find_first_of(",") + 1);
|
||||
try {
|
||||
addr = str2addr(addr_str);
|
||||
}
|
||||
catch (invalid_argument& exc) {
|
||||
} catch (invalid_argument& exc) {
|
||||
try {
|
||||
/* number conversion failed, trying reg name */
|
||||
addr = get_reg(addr_str);
|
||||
}
|
||||
catch (invalid_argument& exc) {
|
||||
} catch (invalid_argument& exc) {
|
||||
cout << exc.what() << endl;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
try {
|
||||
disasm(inst_grab, addr);
|
||||
}
|
||||
catch (invalid_argument& exc) {
|
||||
} catch (invalid_argument& exc) {
|
||||
cout << exc.what() << endl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* disas without arguments defaults to disas 1,pc */
|
||||
addr_str = "PC";
|
||||
addr = get_reg(addr_str);
|
||||
disasm(1, addr);
|
||||
}
|
||||
}
|
||||
else if (cmd == "dump") {
|
||||
} else if (cmd == "dump") {
|
||||
expr_str = "";
|
||||
ss >> expr_str;
|
||||
dump_mem(expr_str);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
cout << "Unknown command: " << cmd << endl;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -25,9 +25,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
*/
|
||||
|
||||
#include "devices/adb.h"
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include "devices/adb.h"
|
||||
|
||||
#include <thirdparty/SDL2/include/SDL.h>
|
||||
#include <thirdparty/SDL2/include/SDL_events.h>
|
||||
|
@ -40,7 +40,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
using namespace std;
|
||||
|
||||
ADB_Bus::ADB_Bus() {
|
||||
//set data streams as clear
|
||||
// set data streams as clear
|
||||
this->adb_mouse_register0 = 0x8080;
|
||||
|
||||
input_stream_len = 0;
|
||||
|
@ -53,50 +53,43 @@ ADB_Bus::ADB_Bus() {
|
|||
mouse_access_no = adb_relative;
|
||||
}
|
||||
|
||||
ADB_Bus::~ADB_Bus() {
|
||||
|
||||
}
|
||||
ADB_Bus::~ADB_Bus() {}
|
||||
|
||||
bool ADB_Bus::listen(int device, int reg) {
|
||||
if (device == keyboard_access_no) {
|
||||
if (adb_keybd_listen(reg)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (device == mouse_access_no) {
|
||||
} else if (device == mouse_access_no) {
|
||||
if (adb_mouse_listen(reg)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ADB_Bus::talk(int device, int reg, uint16_t value) {
|
||||
//temp code
|
||||
// temp code
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ADB_Bus::bus_reset() {
|
||||
//temp code
|
||||
// temp code
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ADB_Bus::set_addr(int dev_addr, int new_addr) {
|
||||
//temp code
|
||||
// temp code
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ADB_Bus::flush(int dev_addr) {
|
||||
//temp code
|
||||
// temp code
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -108,7 +101,7 @@ bool ADB_Bus::adb_keybd_listen(int reg) {
|
|||
}
|
||||
|
||||
while (SDL_PollEvent(&adb_keybd_evt)) {
|
||||
//Poll our SDL key event for any keystrokes.
|
||||
// Poll our SDL key event for any keystrokes.
|
||||
switch (adb_keybd_evt.type) {
|
||||
case SDL_KEYDOWN:
|
||||
switch (adb_keybd_evt.key.keysym.sym) {
|
||||
|
@ -323,34 +316,34 @@ bool ADB_Bus::adb_keybd_listen(int reg) {
|
|||
ask_key_pressed = 0x5C;
|
||||
break;
|
||||
case SDLK_BACKSPACE:
|
||||
//ask_key_pressed = 0x33;
|
||||
// ask_key_pressed = 0x33;
|
||||
confirm_ask_reg_2 = true;
|
||||
mod_key_pressed = 0x40;
|
||||
break;
|
||||
case SDLK_CAPSLOCK:
|
||||
//ask_key_pressed = 0x39;
|
||||
// ask_key_pressed = 0x39;
|
||||
confirm_ask_reg_2 = true;
|
||||
mod_key_pressed = 0x20;
|
||||
break;
|
||||
case SDLK_RALT:
|
||||
case SDLK_RCTRL: //Temp key for Control key
|
||||
//ask_key_pressed = 0x36;
|
||||
case SDLK_RCTRL: // Temp key for Control key
|
||||
// ask_key_pressed = 0x36;
|
||||
confirm_ask_reg_2 = true;
|
||||
mod_key_pressed = 0x8;
|
||||
break;
|
||||
case SDLK_LSHIFT:
|
||||
case SDLK_RSHIFT:
|
||||
//ask_key_pressed = 0x38;
|
||||
// ask_key_pressed = 0x38;
|
||||
confirm_ask_reg_2 = true;
|
||||
mod_key_pressed = 0x4;
|
||||
break;
|
||||
case SDLK_LALT:
|
||||
//ask_key_pressed = 0x3A;
|
||||
// ask_key_pressed = 0x3A;
|
||||
confirm_ask_reg_2 = true;
|
||||
mod_key_pressed = 0x2;
|
||||
break;
|
||||
case SDLK_LCTRL: //Temp key for the Command/Apple key
|
||||
//ask_key_pressed = 0x37;
|
||||
case SDLK_LCTRL: // Temp key for the Command/Apple key
|
||||
// ask_key_pressed = 0x37;
|
||||
confirm_ask_reg_2 = true;
|
||||
mod_key_pressed = 0x1;
|
||||
break;
|
||||
|
@ -363,15 +356,14 @@ bool ADB_Bus::adb_keybd_listen(int reg) {
|
|||
adb_keybd_register0 &= (ask_key_pressed << 8);
|
||||
output_data_stream[0] = (adb_keybd_register0 >> 8);
|
||||
output_data_stream[1] = (adb_keybd_register0 & 0xff);
|
||||
}
|
||||
else if (adb_keybd_register0 & 0x80) {
|
||||
} else if (adb_keybd_register0 & 0x80) {
|
||||
adb_keybd_register0 &= 0xFF7F;
|
||||
adb_keybd_register0 &= (ask_key_pressed);
|
||||
output_data_stream[0] = (adb_keybd_register0 >> 8);
|
||||
output_data_stream[1] = (adb_keybd_register0 & 0xff);
|
||||
}
|
||||
|
||||
//check if mod keys are being pressed
|
||||
// check if mod keys are being pressed
|
||||
|
||||
if (confirm_ask_reg_2) {
|
||||
adb_keybd_register0 |= (mod_key_pressed << 8);
|
||||
|
@ -386,8 +378,7 @@ bool ADB_Bus::adb_keybd_listen(int reg) {
|
|||
adb_keybd_register0 |= 0x8000;
|
||||
output_data_stream[0] = (adb_keybd_register0 >> 8);
|
||||
output_data_stream[1] = (adb_keybd_register0 & 0xff);
|
||||
}
|
||||
else if (adb_keybd_register0 & 0x80)
|
||||
} else if (adb_keybd_register0 & 0x80)
|
||||
adb_keybd_register0 |= 0x0080;
|
||||
output_data_stream[0] = (adb_keybd_register0 >> 8);
|
||||
output_data_stream[1] = (adb_keybd_register0 & 0xff);
|
||||
|
@ -403,8 +394,7 @@ bool ADB_Bus::adb_keybd_listen(int reg) {
|
|||
|
||||
if ((reg != 1)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -421,11 +411,9 @@ bool ADB_Bus::adb_mouse_listen(int reg) {
|
|||
if (adb_mouse_evt.motion.xrel < 0) {
|
||||
if (adb_mouse_evt.motion.xrel <= -64) {
|
||||
this->adb_mouse_register0 |= 0x7F;
|
||||
}
|
||||
else if (adb_mouse_evt.motion.xrel >= 63) {
|
||||
} else if (adb_mouse_evt.motion.xrel >= 63) {
|
||||
this->adb_mouse_register0 |= 0x3F;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this->adb_mouse_register0 |= adb_mouse_evt.motion.xrel;
|
||||
}
|
||||
}
|
||||
|
@ -436,15 +424,12 @@ bool ADB_Bus::adb_mouse_listen(int reg) {
|
|||
if (adb_mouse_evt.motion.yrel < 0) {
|
||||
if (adb_mouse_evt.motion.yrel <= -64) {
|
||||
this->adb_mouse_register0 |= 0x7F00;
|
||||
}
|
||||
else if (adb_mouse_evt.motion.yrel >= 63) {
|
||||
} else if (adb_mouse_evt.motion.yrel >= 63) {
|
||||
this->adb_mouse_register0 |= 0x3F00;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this->adb_mouse_register0 |= (adb_mouse_evt.motion.yrel << 8);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
switch (adb_mouse_evt.type) {
|
||||
|
@ -458,13 +443,11 @@ bool ADB_Bus::adb_mouse_listen(int reg) {
|
|||
if (reg == 0) {
|
||||
output_data_stream[0] = (adb_mouse_register0 >> 8);
|
||||
output_data_stream[1] = (adb_mouse_register0 & 0xff);
|
||||
}
|
||||
else if (reg == 3) {
|
||||
} else if (reg == 3) {
|
||||
output_data_stream[0] = (adb_mouse_register3 >> 8);
|
||||
output_data_stream[1] = (adb_mouse_register3 & 0xff);
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -27,14 +27,25 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#include <thirdparty/SDL2/include/SDL_events.h>
|
||||
|
||||
enum adb_default_values {
|
||||
adb_reserved0, adb_reserved1, adb_encoded, adb_relative,
|
||||
adb_absolute, adb_reserved5, adb_reserved6, adb_reserved7,
|
||||
adb_other8, adb_other9, adb_other10, adb_other11,
|
||||
adb_other12, adb_other13, adb_other14, adb_other15
|
||||
adb_reserved0,
|
||||
adb_reserved1,
|
||||
adb_encoded,
|
||||
adb_relative,
|
||||
adb_absolute,
|
||||
adb_reserved5,
|
||||
adb_reserved6,
|
||||
adb_reserved7,
|
||||
adb_other8,
|
||||
adb_other9,
|
||||
adb_other10,
|
||||
adb_other11,
|
||||
adb_other12,
|
||||
adb_other13,
|
||||
adb_other14,
|
||||
adb_other15
|
||||
};
|
||||
|
||||
class ADB_Bus
|
||||
{
|
||||
class ADB_Bus {
|
||||
public:
|
||||
ADB_Bus();
|
||||
~ADB_Bus();
|
||||
|
@ -58,7 +69,7 @@ private:
|
|||
int keyboard_access_no;
|
||||
int mouse_access_no;
|
||||
|
||||
//Keyboard Variables
|
||||
// Keyboard Variables
|
||||
|
||||
uint16_t adb_keybd_register0;
|
||||
uint16_t adb_keybd_register2;
|
||||
|
@ -71,15 +82,15 @@ private:
|
|||
|
||||
bool confirm_ask_reg_2;
|
||||
|
||||
//Mouse Variables
|
||||
// Mouse Variables
|
||||
SDL_Event adb_mouse_evt;
|
||||
|
||||
uint16_t adb_mouse_register0;
|
||||
uint16_t adb_mouse_register3;
|
||||
|
||||
uint8_t input_data_stream[16]; //temp buffer
|
||||
uint8_t input_data_stream[16]; // temp buffer
|
||||
int input_stream_len;
|
||||
uint8_t output_data_stream[16]; //temp buffer
|
||||
uint8_t output_data_stream[16]; // temp buffer
|
||||
int output_stream_len;
|
||||
};
|
||||
|
||||
|
|
|
@ -19,17 +19,16 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <atirage.h>
|
||||
#include <cstdint>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include "displayid.h"
|
||||
#include "endianswap.h"
|
||||
#include "memreadwrite.h"
|
||||
#include "pcidevice.h"
|
||||
#include "displayid.h"
|
||||
#include <atirage.h>
|
||||
#include <cstdint>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
|
||||
ATIRage::ATIRage(uint16_t dev_id) : PCIDevice("ati-rage")
|
||||
{
|
||||
ATIRage::ATIRage(uint16_t dev_id) : PCIDevice("ati-rage") {
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[0], (dev_id << 16) | ATI_PCI_VENDOR_ID);
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[8], 0x0300005C);
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[0x3C], 0x00080100);
|
||||
|
@ -37,13 +36,11 @@ ATIRage::ATIRage(uint16_t dev_id) : PCIDevice("ati-rage")
|
|||
this->disp_id = new DisplayID();
|
||||
}
|
||||
|
||||
ATIRage::~ATIRage()
|
||||
{
|
||||
ATIRage::~ATIRage() {
|
||||
delete (this->disp_id);
|
||||
}
|
||||
|
||||
uint32_t ATIRage::size_dep_read(uint8_t *buf, uint32_t size)
|
||||
{
|
||||
uint32_t ATIRage::size_dep_read(uint8_t* buf, uint32_t size) {
|
||||
switch (size) {
|
||||
case 4:
|
||||
return READ_DWORD_LE_A(buf);
|
||||
|
@ -60,8 +57,7 @@ uint32_t ATIRage::size_dep_read(uint8_t *buf, uint32_t size)
|
|||
}
|
||||
}
|
||||
|
||||
void ATIRage::size_dep_write(uint8_t *buf, uint32_t value, uint32_t size)
|
||||
{
|
||||
void ATIRage::size_dep_write(uint8_t* buf, uint32_t value, uint32_t size) {
|
||||
switch (size) {
|
||||
case 4:
|
||||
WRITE_DWORD_BE_A(buf, value);
|
||||
|
@ -74,8 +70,7 @@ void ATIRage::size_dep_write(uint8_t *buf, uint32_t value, uint32_t size)
|
|||
}
|
||||
}
|
||||
|
||||
const char* ATIRage::get_reg_name(uint32_t reg_offset)
|
||||
{
|
||||
const char* ATIRage::get_reg_name(uint32_t reg_offset) {
|
||||
const char* reg_name;
|
||||
|
||||
switch (reg_offset & ~3) {
|
||||
|
@ -152,16 +147,19 @@ const char* ATIRage::get_reg_name(uint32_t reg_offset)
|
|||
return reg_name;
|
||||
}
|
||||
|
||||
uint32_t ATIRage::read_reg(uint32_t offset, uint32_t size)
|
||||
{
|
||||
uint32_t ATIRage::read_reg(uint32_t offset, uint32_t size) {
|
||||
uint32_t res;
|
||||
|
||||
switch (offset & ~3) {
|
||||
case ATI_GP_IO:
|
||||
break;
|
||||
default:
|
||||
LOG_F(INFO, "ATI Rage: read I/O reg %s at 0x%X, size=%d, val=0x%X",
|
||||
get_reg_name(offset), offset, size,
|
||||
LOG_F(
|
||||
INFO,
|
||||
"ATI Rage: read I/O reg %s at 0x%X, size=%d, val=0x%X",
|
||||
get_reg_name(offset),
|
||||
offset,
|
||||
size,
|
||||
size_dep_read(&this->block_io_regs[offset], size));
|
||||
}
|
||||
|
||||
|
@ -170,8 +168,7 @@ uint32_t ATIRage::read_reg(uint32_t offset, uint32_t size)
|
|||
return res;
|
||||
}
|
||||
|
||||
void ATIRage::write_reg(uint32_t offset, uint32_t value, uint32_t size)
|
||||
{
|
||||
void ATIRage::write_reg(uint32_t offset, uint32_t value, uint32_t size) {
|
||||
uint32_t gpio_val;
|
||||
uint16_t gpio_dir;
|
||||
|
||||
|
@ -183,20 +180,23 @@ void ATIRage::write_reg(uint32_t offset, uint32_t value, uint32_t size)
|
|||
if (offset < (ATI_GP_IO + 2)) {
|
||||
gpio_val = READ_DWORD_LE_A(&this->block_io_regs[ATI_GP_IO]);
|
||||
gpio_dir = (gpio_val >> 16) & 0x3FFF;
|
||||
WRITE_WORD_LE_A(&this->block_io_regs[ATI_GP_IO],
|
||||
WRITE_WORD_LE_A(
|
||||
&this->block_io_regs[ATI_GP_IO],
|
||||
this->disp_id->read_monitor_sense(gpio_val, gpio_dir));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_F(INFO, "ATI Rage: %s register at 0x%X set to 0x%X",
|
||||
get_reg_name(offset), offset & ~3,
|
||||
LOG_F(
|
||||
INFO,
|
||||
"ATI Rage: %s register at 0x%X set to 0x%X",
|
||||
get_reg_name(offset),
|
||||
offset & ~3,
|
||||
READ_DWORD_LE_A(&this->block_io_regs[offset & ~3]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size)
|
||||
{
|
||||
uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size) {
|
||||
uint32_t res = 0;
|
||||
|
||||
LOG_F(INFO, "Reading ATI Rage config space, offset = 0x%X, size=%d", reg_offs, size);
|
||||
|
@ -207,32 +207,32 @@ uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size)
|
|||
return res;
|
||||
}
|
||||
|
||||
void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
|
||||
{
|
||||
LOG_F(INFO, "Writing into ATI Rage PCI config space, offset = 0x%X, val=0x%X size=%d",
|
||||
reg_offs, BYTESWAP_32(value), size);
|
||||
void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) {
|
||||
LOG_F(
|
||||
INFO,
|
||||
"Writing into ATI Rage PCI config space, offset = 0x%X, val=0x%X size=%d",
|
||||
reg_offs,
|
||||
BYTESWAP_32(value),
|
||||
size);
|
||||
|
||||
switch (reg_offs) {
|
||||
case 0x10: /* BAR 0 */
|
||||
if (value == 0xFFFFFFFFUL) {
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR0], 0xFF000008);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR0], value);
|
||||
}
|
||||
break;
|
||||
case 0x14: /* BAR 1: I/O space base, 256 bytes wide */
|
||||
if (value == 0xFFFFFFFFUL) {
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR1], 0x0000FFF1);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR1], value);
|
||||
}
|
||||
case 0x18: /* BAR 2 */
|
||||
if (value == 0xFFFFFFFFUL) {
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR2], 0xFFFFF000);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR2], value);
|
||||
}
|
||||
break;
|
||||
|
@ -248,8 +248,7 @@ void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
|
|||
}
|
||||
|
||||
|
||||
bool ATIRage::io_access_allowed(uint32_t offset, uint32_t *p_io_base)
|
||||
{
|
||||
bool ATIRage::io_access_allowed(uint32_t offset, uint32_t* p_io_base) {
|
||||
if (!(this->pci_cfg[CFG_REG_CMD] & 1)) {
|
||||
LOG_F(WARNING, "ATI I/O space disabled in the command reg");
|
||||
return false;
|
||||
|
@ -268,8 +267,7 @@ bool ATIRage::io_access_allowed(uint32_t offset, uint32_t *p_io_base)
|
|||
}
|
||||
|
||||
|
||||
bool ATIRage::pci_io_read(uint32_t offset, uint32_t size, uint32_t *res)
|
||||
{
|
||||
bool ATIRage::pci_io_read(uint32_t offset, uint32_t size, uint32_t* res) {
|
||||
uint32_t io_base;
|
||||
|
||||
if (!this->io_access_allowed(offset, &io_base)) {
|
||||
|
@ -281,8 +279,7 @@ bool ATIRage::pci_io_read(uint32_t offset, uint32_t size, uint32_t *res)
|
|||
}
|
||||
|
||||
|
||||
bool ATIRage::pci_io_write(uint32_t offset, uint32_t value, uint32_t size)
|
||||
{
|
||||
bool ATIRage::pci_io_write(uint32_t offset, uint32_t value, uint32_t size) {
|
||||
uint32_t io_base;
|
||||
|
||||
if (!this->io_access_allowed(offset, &io_base)) {
|
||||
|
@ -294,13 +291,11 @@ bool ATIRage::pci_io_write(uint32_t offset, uint32_t value, uint32_t size)
|
|||
}
|
||||
|
||||
|
||||
uint32_t ATIRage::read(uint32_t reg_start, uint32_t offset, int size)
|
||||
{
|
||||
uint32_t ATIRage::read(uint32_t reg_start, uint32_t offset, int size) {
|
||||
LOG_F(INFO, "Reading reg=%X, size %d", offset, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ATIRage::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
|
||||
{
|
||||
void ATIRage::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) {
|
||||
LOG_F(INFO, "Writing reg=%X, value=%X, size %d", offset, value, size);
|
||||
}
|
||||
|
|
|
@ -22,9 +22,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef ATI_RAGE_H
|
||||
#define ATI_RAGE_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include "pcidevice.h"
|
||||
#include "displayid.h"
|
||||
#include "pcidevice.h"
|
||||
#include <cinttypes>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -102,8 +102,7 @@ enum {
|
|||
ATI_TVO_CNTL = 0x0500,
|
||||
};
|
||||
|
||||
class ATIRage : public PCIDevice
|
||||
{
|
||||
class ATIRage : public PCIDevice {
|
||||
public:
|
||||
ATIRage(uint16_t dev_id);
|
||||
~ATIRage();
|
||||
|
@ -112,17 +111,21 @@ public:
|
|||
uint32_t read(uint32_t reg_start, uint32_t offset, int size);
|
||||
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size);
|
||||
|
||||
bool supports_type(HWCompType type) { return type == HWCompType::MMIO_DEV; };
|
||||
bool supports_type(HWCompType type) {
|
||||
return type == HWCompType::MMIO_DEV;
|
||||
};
|
||||
|
||||
/* PCI device methods */
|
||||
bool supports_io_space(void) { return true; };
|
||||
bool supports_io_space(void) {
|
||||
return true;
|
||||
};
|
||||
|
||||
uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size);
|
||||
void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size);
|
||||
|
||||
/* I/O space access methods */
|
||||
bool pci_io_read(uint32_t offset, uint32_t size, uint32_t *res);
|
||||
bool pci_io_write(uint32_t offset, uint32_t value, uint32_t size) ;
|
||||
bool pci_io_read(uint32_t offset, uint32_t size, uint32_t* res);
|
||||
bool pci_io_write(uint32_t offset, uint32_t value, uint32_t size);
|
||||
|
||||
protected:
|
||||
uint32_t size_dep_read(uint8_t* buf, uint32_t size);
|
||||
|
@ -133,14 +136,14 @@ protected:
|
|||
void write_reg(uint32_t offset, uint32_t value, uint32_t size);
|
||||
|
||||
private:
|
||||
//uint32_t atirage_membuf_regs[9]; /* ATI Rage Memory Buffer Registers */
|
||||
//uint32_t atirage_scratch_regs[4]; /* ATI Rage Scratch Registers */
|
||||
//uint32_t atirage_cmdfifo_regs[3]; /* ATI Rage Command FIFO Registers */
|
||||
//uint32_t atirage_datapath_regs[12]; /* ATI Rage Data Path Registers*/
|
||||
// uint32_t atirage_membuf_regs[9]; /* ATI Rage Memory Buffer Registers */
|
||||
// uint32_t atirage_scratch_regs[4]; /* ATI Rage Scratch Registers */
|
||||
// uint32_t atirage_cmdfifo_regs[3]; /* ATI Rage Command FIFO Registers */
|
||||
// uint32_t atirage_datapath_regs[12]; /* ATI Rage Data Path Registers*/
|
||||
|
||||
uint8_t block_io_regs[256] = { 0 };
|
||||
uint8_t block_io_regs[256] = {0};
|
||||
|
||||
uint8_t pci_cfg[256] = { 0 }; /* PCI configuration space */
|
||||
uint8_t pci_cfg[256] = {0}; /* PCI configuration space */
|
||||
|
||||
DisplayID* disp_id;
|
||||
};
|
||||
|
|
|
@ -24,26 +24,24 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
Author: Max Poliakovski 2019-20
|
||||
*/
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include "endianswap.h"
|
||||
#include "awacs.h"
|
||||
#include "dbdma.h"
|
||||
#include "endianswap.h"
|
||||
#include "machines/machinebase.h"
|
||||
#include <thirdparty/SDL2/include/SDL.h>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
static int awac_freqs[8] = {44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350};
|
||||
|
||||
AWACDevice::AWACDevice()
|
||||
{
|
||||
AWACDevice::AWACDevice() {
|
||||
this->audio_proc = new AudioProcessor();
|
||||
|
||||
/* register audio processor chip with the I2C bus */
|
||||
I2CBus *i2c_bus = dynamic_cast<I2CBus *>(gMachineObj->get_comp_by_type(HWCompType::I2C_HOST));
|
||||
I2CBus* i2c_bus = dynamic_cast<I2CBus*>(gMachineObj->get_comp_by_type(HWCompType::I2C_HOST));
|
||||
i2c_bus->register_device(0x45, this->audio_proc);
|
||||
}
|
||||
|
||||
AWACDevice::~AWACDevice()
|
||||
{
|
||||
AWACDevice::~AWACDevice() {
|
||||
delete this->audio_proc;
|
||||
|
||||
if (this->snd_buf)
|
||||
|
@ -53,21 +51,18 @@ AWACDevice::~AWACDevice()
|
|||
SDL_CloseAudioDevice(snd_out_dev);
|
||||
}
|
||||
|
||||
void AWACDevice::set_dma_out(DMAChannel *dma_out_ch)
|
||||
{
|
||||
void AWACDevice::set_dma_out(DMAChannel* dma_out_ch) {
|
||||
this->dma_out_ch = dma_out_ch;
|
||||
}
|
||||
|
||||
uint32_t AWACDevice::snd_ctrl_read(uint32_t offset, int size)
|
||||
{
|
||||
switch(offset) {
|
||||
uint32_t AWACDevice::snd_ctrl_read(uint32_t offset, int size) {
|
||||
switch (offset) {
|
||||
case AWAC_SOUND_CTRL_REG:
|
||||
return this->snd_ctrl_reg;
|
||||
case AWAC_CODEC_CTRL_REG:
|
||||
return this->is_busy;
|
||||
case AWAC_CODEC_STATUS_REG:
|
||||
return (AWAC_AVAILABLE << 8) | (AWAC_MAKER_CRYSTAL << 16) |
|
||||
(AWAC_REV_SCREAMER << 20);
|
||||
return (AWAC_AVAILABLE << 8) | (AWAC_MAKER_CRYSTAL << 16) | (AWAC_REV_SCREAMER << 20);
|
||||
break;
|
||||
default:
|
||||
LOG_F(ERROR, "AWAC: unsupported register at offset 0x%X", offset);
|
||||
|
@ -76,12 +71,11 @@ uint32_t AWACDevice::snd_ctrl_read(uint32_t offset, int size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void AWACDevice::snd_ctrl_write(uint32_t offset, uint32_t value, int size)
|
||||
{
|
||||
void AWACDevice::snd_ctrl_write(uint32_t offset, uint32_t value, int size) {
|
||||
int subframe, reg_num;
|
||||
uint16_t data;
|
||||
|
||||
switch(offset) {
|
||||
switch (offset) {
|
||||
case AWAC_SOUND_CTRL_REG:
|
||||
this->snd_ctrl_reg = BYTESWAP_32(value);
|
||||
LOG_F(INFO, "New sound control value = 0x%X", this->snd_ctrl_reg);
|
||||
|
@ -99,48 +93,45 @@ void AWACDevice::snd_ctrl_write(uint32_t offset, uint32_t value, int size)
|
|||
}
|
||||
}
|
||||
|
||||
static void convert_data(const uint8_t *in, uint8_t *out, uint32_t len)
|
||||
{
|
||||
static void convert_data(const uint8_t* in, uint8_t* out, uint32_t len) {
|
||||
uint16_t *p_in, *p_out;
|
||||
|
||||
if (len & 7) {
|
||||
LOG_F(WARNING, "AWAC sound buffer len not a multiply of 8, %d", len);
|
||||
}
|
||||
|
||||
p_in = (uint16_t *)in;
|
||||
p_out = (uint16_t *)out;
|
||||
p_in = (uint16_t*)in;
|
||||
p_out = (uint16_t*)out;
|
||||
len >>= 1;
|
||||
|
||||
/* AWAC data comes as LLRR -> convert it to LRLR */
|
||||
for (int i = 0; i < len; i += 8) {
|
||||
p_out[i] = p_in[i];
|
||||
p_out[i+1] = p_in[i+2];
|
||||
p_out[i+2] = p_in[i+1];
|
||||
p_out[i+3] = p_in[i+3];
|
||||
p_out[i + 1] = p_in[i + 2];
|
||||
p_out[i + 2] = p_in[i + 1];
|
||||
p_out[i + 3] = p_in[i + 3];
|
||||
}
|
||||
}
|
||||
|
||||
static void audio_out_callback(void *user_data, uint8_t *buf, int buf_len)
|
||||
{
|
||||
uint8_t *p_in;
|
||||
static void audio_out_callback(void* user_data, uint8_t* buf, int buf_len) {
|
||||
uint8_t* p_in;
|
||||
uint32_t rem_len, got_len;
|
||||
|
||||
DMAChannel *dma_ch = (DMAChannel *)user_data; /* C API baby! */
|
||||
DMAChannel* dma_ch = (DMAChannel*)user_data; /* C API baby! */
|
||||
|
||||
for (rem_len = buf_len; rem_len > 0; rem_len -= got_len, buf += got_len) {
|
||||
if (!dma_ch->get_data(rem_len, &got_len, &p_in)) {
|
||||
convert_data(p_in, buf, got_len);
|
||||
//LOG_F(9, "Converted sound data, len = %d", got_len);
|
||||
// LOG_F(9, "Converted sound data, len = %d", got_len);
|
||||
} else { /* no more data */
|
||||
memset(buf, 0, rem_len); /* fill the buffer with silence */
|
||||
//LOG_F(9, "Inserted silence, len = %d", rem_len);
|
||||
// LOG_F(9, "Inserted silence, len = %d", rem_len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t AWACDevice::convert_data(const uint8_t *data, int len)
|
||||
{
|
||||
uint32_t AWACDevice::convert_data(const uint8_t* data, int len) {
|
||||
int i;
|
||||
uint16_t *p_in, *p_out;
|
||||
|
||||
|
@ -151,21 +142,20 @@ uint32_t AWACDevice::convert_data(const uint8_t *data, int len)
|
|||
this->buf_len = len;
|
||||
}
|
||||
|
||||
p_in = (uint16_t *)data;
|
||||
p_out = (uint16_t *)this->snd_buf;
|
||||
p_in = (uint16_t*)data;
|
||||
p_out = (uint16_t*)this->snd_buf;
|
||||
|
||||
for (i = 0; i < len; i += 8) {
|
||||
p_out[i] = p_in[i];
|
||||
p_out[i+1] = p_in[i+2];
|
||||
p_out[i+2] = p_in[i+1];
|
||||
p_out[i+3] = p_in[i+3];
|
||||
p_out[i + 1] = p_in[i + 2];
|
||||
p_out[i + 2] = p_in[i + 1];
|
||||
p_out[i + 3] = p_in[i + 3];
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void AWACDevice::dma_start()
|
||||
{
|
||||
void AWACDevice::dma_start() {
|
||||
SDL_AudioSpec snd_spec, snd_settings;
|
||||
|
||||
SDL_zero(snd_spec);
|
||||
|
@ -174,7 +164,7 @@ void AWACDevice::dma_start()
|
|||
snd_spec.channels = 2;
|
||||
snd_spec.samples = 4096; /* buffer size, chosen empirically */
|
||||
snd_spec.callback = audio_out_callback;
|
||||
snd_spec.userdata = (void *)this->dma_out_ch;
|
||||
snd_spec.userdata = (void*)this->dma_out_ch;
|
||||
|
||||
|
||||
this->snd_out_dev = SDL_OpenAudioDevice(NULL, 0, &snd_spec, &snd_settings, 0);
|
||||
|
@ -188,16 +178,14 @@ void AWACDevice::dma_start()
|
|||
SDL_PauseAudioDevice(this->snd_out_dev, 0); /* start audio playing */
|
||||
}
|
||||
|
||||
void AWACDevice::dma_end()
|
||||
{
|
||||
void AWACDevice::dma_end() {
|
||||
if (this->snd_out_dev) {
|
||||
SDL_CloseAudioDevice(this->snd_out_dev);
|
||||
this->snd_out_dev = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void AWACDevice::dma_push(uint8_t *buf, int size)
|
||||
{
|
||||
void AWACDevice::dma_push(uint8_t* buf, int size) {
|
||||
uint32_t dst_len;
|
||||
|
||||
dst_len = this->convert_data(buf, size);
|
||||
|
@ -213,6 +201,4 @@ void AWACDevice::dma_push(uint8_t *buf, int size)
|
|||
}
|
||||
}
|
||||
|
||||
void AWACDevice::dma_pull(uint8_t *buf, int size)
|
||||
{
|
||||
}
|
||||
void AWACDevice::dma_pull(uint8_t* buf, int size) {}
|
||||
|
|
|
@ -28,9 +28,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef AWAC_H
|
||||
#define AWAC_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include "i2c.h"
|
||||
#include "dbdma.h"
|
||||
#include "i2c.h"
|
||||
#include <cinttypes>
|
||||
#include <thirdparty/SDL2/include/SDL.h>
|
||||
|
||||
/** AWAC registers offsets. */
|
||||
|
@ -57,7 +57,9 @@ public:
|
|||
AudioProcessor() = default;
|
||||
~AudioProcessor() = default;
|
||||
|
||||
void start_transaction() { this->pos = 0; };
|
||||
void start_transaction() {
|
||||
this->pos = 0;
|
||||
};
|
||||
|
||||
bool send_subaddress(uint8_t sub_addr) {
|
||||
if ((sub_addr & 0xF) > 6)
|
||||
|
@ -65,8 +67,7 @@ public:
|
|||
|
||||
this->sub_addr = sub_addr & 0xF;
|
||||
this->auto_inc = !!(sub_addr & 0x10);
|
||||
LOG_F(INFO, "TDA7433 subaddress = 0x%X, auto increment = %d",
|
||||
this->sub_addr, this->auto_inc);
|
||||
LOG_F(INFO, "TDA7433 subaddress = 0x%X, auto increment = %d", this->sub_addr, this->auto_inc);
|
||||
this->pos++;
|
||||
return true;
|
||||
};
|
||||
|
@ -86,7 +87,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
bool receive_byte(uint8_t *p_data) {
|
||||
bool receive_byte(uint8_t* p_data) {
|
||||
*p_data = this->regs[this->sub_addr];
|
||||
LOG_F(INFO, "TDA7433 byte 0x%X sent", *p_data);
|
||||
return true;
|
||||
|
@ -105,7 +106,7 @@ public:
|
|||
AWACDevice();
|
||||
~AWACDevice();
|
||||
|
||||
void set_dma_out(DMAChannel *dma_out_ch);
|
||||
void set_dma_out(DMAChannel* dma_out_ch);
|
||||
|
||||
uint32_t snd_ctrl_read(uint32_t offset, int size);
|
||||
void snd_ctrl_write(uint32_t offset, uint32_t value, int size);
|
||||
|
@ -113,22 +114,22 @@ public:
|
|||
/* DMACallback methods */
|
||||
void dma_start();
|
||||
void dma_end();
|
||||
void dma_push(uint8_t *buf, int size);
|
||||
void dma_pull(uint8_t *buf, int size);
|
||||
void dma_push(uint8_t* buf, int size);
|
||||
void dma_pull(uint8_t* buf, int size);
|
||||
|
||||
protected:
|
||||
uint32_t convert_data(const uint8_t *data, int len);
|
||||
uint32_t convert_data(const uint8_t* data, int len);
|
||||
|
||||
private:
|
||||
uint32_t snd_ctrl_reg = {0};
|
||||
uint16_t control_regs[8] = {0}; /* control registers, each 12-bits wide */
|
||||
uint8_t is_busy = 0;
|
||||
AudioProcessor *audio_proc;
|
||||
AudioProcessor* audio_proc;
|
||||
|
||||
SDL_AudioDeviceID snd_out_dev = 0;
|
||||
bool wake_up = false;
|
||||
|
||||
DMAChannel *dma_out_ch;
|
||||
DMAChannel* dma_out_ch;
|
||||
|
||||
uint8_t* snd_buf = 0;
|
||||
uint32_t buf_len = 0;
|
||||
|
|
|
@ -21,27 +21,25 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
/** @file Descriptor-based direct memory access emulation. */
|
||||
|
||||
#include "dbdma.h"
|
||||
#include "cpu/ppc/ppcmmu.h"
|
||||
#include "endianswap.h"
|
||||
#include <cinttypes>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include "dbdma.h"
|
||||
#include "endianswap.h"
|
||||
#include "cpu/ppc/ppcmmu.h"
|
||||
|
||||
void DMAChannel::get_next_cmd(uint32_t cmd_addr, DMACmd *p_cmd)
|
||||
{
|
||||
void DMAChannel::get_next_cmd(uint32_t cmd_addr, DMACmd* p_cmd) {
|
||||
/* load DMACmd from physical memory */
|
||||
memcpy((uint8_t *)p_cmd, mmu_get_dma_mem(cmd_addr, 16), 16);
|
||||
memcpy((uint8_t*)p_cmd, mmu_get_dma_mem(cmd_addr, 16), 16);
|
||||
}
|
||||
|
||||
uint8_t DMAChannel::interpret_cmd()
|
||||
{
|
||||
uint8_t DMAChannel::interpret_cmd() {
|
||||
DMACmd cmd_struct;
|
||||
|
||||
get_next_cmd(this->cmd_ptr, &cmd_struct);
|
||||
|
||||
this->ch_stat &= ~CH_STAT_WAKE; /* clear wake bit (DMA spec, 5.5.3.4) */
|
||||
|
||||
switch(cmd_struct.cmd_key >> 4) {
|
||||
switch (cmd_struct.cmd_key >> 4) {
|
||||
case 0:
|
||||
LOG_F(9, "Executing DMA Command OUTPUT_MORE");
|
||||
if (cmd_struct.cmd_key & 7) {
|
||||
|
@ -52,7 +50,7 @@ uint8_t DMAChannel::interpret_cmd()
|
|||
LOG_F(ERROR, "non-zero i/b/w not implemented");
|
||||
break;
|
||||
}
|
||||
//this->dma_cb->dma_push(
|
||||
// this->dma_cb->dma_push(
|
||||
// mmu_get_dma_mem(cmd_struct.address, cmd_struct.req_count),
|
||||
// cmd_struct.req_count);
|
||||
this->queue_data = mmu_get_dma_mem(cmd_struct.address, cmd_struct.req_count);
|
||||
|
@ -69,7 +67,7 @@ uint8_t DMAChannel::interpret_cmd()
|
|||
LOG_F(ERROR, "non-zero i/b/w not implemented");
|
||||
break;
|
||||
}
|
||||
//this->dma_cb->dma_push(
|
||||
// this->dma_cb->dma_push(
|
||||
// mmu_get_dma_mem(cmd_struct.address, cmd_struct.req_count),
|
||||
// cmd_struct.req_count);
|
||||
this->queue_data = mmu_get_dma_mem(cmd_struct.address, cmd_struct.req_count);
|
||||
|
@ -105,8 +103,7 @@ uint8_t DMAChannel::interpret_cmd()
|
|||
}
|
||||
|
||||
|
||||
uint32_t DMAChannel::reg_read(uint32_t offset, int size)
|
||||
{
|
||||
uint32_t DMAChannel::reg_read(uint32_t offset, int size) {
|
||||
uint32_t res = 0;
|
||||
|
||||
if (size != 4) {
|
||||
|
@ -114,7 +111,7 @@ uint32_t DMAChannel::reg_read(uint32_t offset, int size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
switch(offset) {
|
||||
switch (offset) {
|
||||
case DMAReg::CH_CTRL:
|
||||
res = 0; /* ChannelControl reads as 0 (DBDMA spec 5.5.1, table 74) */
|
||||
break;
|
||||
|
@ -128,8 +125,7 @@ uint32_t DMAChannel::reg_read(uint32_t offset, int size)
|
|||
return res;
|
||||
}
|
||||
|
||||
void DMAChannel::reg_write(uint32_t offset, uint32_t value, int size)
|
||||
{
|
||||
void DMAChannel::reg_write(uint32_t offset, uint32_t value, int size) {
|
||||
uint16_t mask, old_stat, new_stat;
|
||||
|
||||
if (size != 4) {
|
||||
|
@ -140,7 +136,7 @@ void DMAChannel::reg_write(uint32_t offset, uint32_t value, int size)
|
|||
value = BYTESWAP_32(value);
|
||||
old_stat = this->ch_stat;
|
||||
|
||||
switch(offset) {
|
||||
switch (offset) {
|
||||
case DMAReg::CH_CTRL:
|
||||
mask = value >> 16;
|
||||
new_stat = (value & mask & 0xF0FFU) | (old_stat & ~mask);
|
||||
|
@ -187,8 +183,7 @@ void DMAChannel::reg_write(uint32_t offset, uint32_t value, int size)
|
|||
}
|
||||
}
|
||||
|
||||
int DMAChannel::get_data(uint32_t req_len, uint32_t *avail_len, uint8_t **p_data)
|
||||
{
|
||||
int DMAChannel::get_data(uint32_t req_len, uint32_t* avail_len, uint8_t** p_data) {
|
||||
if (this->ch_stat & CH_STAT_DEAD || !(this->ch_stat & CH_STAT_ACTIVE)) {
|
||||
LOG_F(WARNING, "Dead/idle channel -> no more data");
|
||||
*avail_len = 0;
|
||||
|
@ -220,8 +215,7 @@ int DMAChannel::get_data(uint32_t req_len, uint32_t *avail_len, uint8_t **p_data
|
|||
return -1; /* tell the caller there is no more data */
|
||||
}
|
||||
|
||||
void DMAChannel::start()
|
||||
{
|
||||
void DMAChannel::start() {
|
||||
if (this->ch_stat & CH_STAT_PAUSE) {
|
||||
LOG_F(WARNING, "Cannot start DMA channel, PAUSE bit is set");
|
||||
return;
|
||||
|
@ -233,12 +227,11 @@ void DMAChannel::start()
|
|||
|
||||
this->dma_cb->dma_start();
|
||||
|
||||
//while (this->interpret_cmd() != 7) {
|
||||
// while (this->interpret_cmd() != 7) {
|
||||
//}
|
||||
}
|
||||
|
||||
void DMAChannel::resume()
|
||||
{
|
||||
void DMAChannel::resume() {
|
||||
if (this->ch_stat & CH_STAT_PAUSE) {
|
||||
LOG_F(WARNING, "Cannot resume DMA channel, PAUSE bit is set");
|
||||
return;
|
||||
|
@ -247,13 +240,11 @@ void DMAChannel::resume()
|
|||
LOG_F(INFO, "Resuming DMA channel");
|
||||
}
|
||||
|
||||
void DMAChannel::abort()
|
||||
{
|
||||
void DMAChannel::abort() {
|
||||
LOG_F(INFO, "Aborting DMA channel");
|
||||
}
|
||||
|
||||
void DMAChannel::pause()
|
||||
{
|
||||
void DMAChannel::pause() {
|
||||
LOG_F(INFO, "Pausing DMA channel");
|
||||
this->dma_cb->dma_end();
|
||||
}
|
||||
|
|
|
@ -63,22 +63,24 @@ class DMACallback {
|
|||
public:
|
||||
virtual void dma_start(void) = 0;
|
||||
virtual void dma_end(void) = 0;
|
||||
virtual void dma_push(uint8_t *buf, int size) = 0;
|
||||
virtual void dma_pull(uint8_t *buf, int size) = 0;
|
||||
virtual void dma_push(uint8_t* buf, int size) = 0;
|
||||
virtual void dma_pull(uint8_t* buf, int size) = 0;
|
||||
};
|
||||
|
||||
class DMAChannel {
|
||||
public:
|
||||
DMAChannel(DMACallback *cb) { this->dma_cb = cb; };
|
||||
DMAChannel(DMACallback* cb) {
|
||||
this->dma_cb = cb;
|
||||
};
|
||||
~DMAChannel() = default;
|
||||
|
||||
uint32_t reg_read(uint32_t offset, int size);
|
||||
void reg_write(uint32_t offset, uint32_t value, int size);
|
||||
|
||||
int get_data(uint32_t req_len, uint32_t *avail_len, uint8_t **p_data);
|
||||
int get_data(uint32_t req_len, uint32_t* avail_len, uint8_t** p_data);
|
||||
|
||||
protected:
|
||||
void get_next_cmd(uint32_t cmd_addr, DMACmd *p_cmd);
|
||||
void get_next_cmd(uint32_t cmd_addr, DMACmd* p_cmd);
|
||||
uint8_t interpret_cmd(void);
|
||||
|
||||
void start(void);
|
||||
|
@ -87,7 +89,7 @@ protected:
|
|||
void pause(void);
|
||||
|
||||
private:
|
||||
DMACallback *dma_cb = 0;
|
||||
DMACallback* dma_cb = 0;
|
||||
uint16_t ch_stat = 0;
|
||||
uint32_t cmd_ptr = 0;
|
||||
|
||||
|
|
|
@ -19,11 +19,10 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include "displayid.h"
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
DisplayID::DisplayID()
|
||||
{
|
||||
DisplayID::DisplayID() {
|
||||
/* Initialize Apple monitor codes */
|
||||
this->std_sense_code = 6;
|
||||
this->ext_sense_code = 0x2B;
|
||||
|
@ -41,22 +40,19 @@ DisplayID::DisplayID()
|
|||
}
|
||||
|
||||
|
||||
uint16_t DisplayID::set_result(uint8_t sda, uint8_t scl)
|
||||
{
|
||||
uint16_t DisplayID::set_result(uint8_t sda, uint8_t scl) {
|
||||
this->last_sda = sda;
|
||||
this->last_scl = scl;
|
||||
|
||||
if (scl) {
|
||||
this->data_out |= 0x1000;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this->data_out &= ~0x1000U;
|
||||
}
|
||||
|
||||
if (sda) {
|
||||
this->data_out |= 0x2000;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this->data_out &= ~0x2000U;
|
||||
}
|
||||
|
||||
|
@ -64,8 +60,7 @@ uint16_t DisplayID::set_result(uint8_t sda, uint8_t scl)
|
|||
}
|
||||
|
||||
|
||||
uint16_t DisplayID::read_monitor_sense(uint16_t data, uint16_t dirs)
|
||||
{
|
||||
uint16_t DisplayID::read_monitor_sense(uint16_t data, uint16_t dirs) {
|
||||
uint8_t scl, sda;
|
||||
uint16_t result;
|
||||
|
||||
|
@ -81,24 +76,19 @@ uint16_t DisplayID::read_monitor_sense(uint16_t data, uint16_t dirs)
|
|||
sda = (dirs & 0x2000) ? !!(data & 0x2000) : 1;
|
||||
|
||||
return update_ddc_i2c(sda, scl);
|
||||
}
|
||||
else { /* Apple legacy monitor codes (see Technical Note HW30) */
|
||||
} else { /* Apple legacy monitor codes (see Technical Note HW30) */
|
||||
switch (dirs & 0x3100) {
|
||||
case 0:
|
||||
result = ((this->std_sense_code & 6) << 11) |
|
||||
((this->std_sense_code & 1) << 8);
|
||||
result = ((this->std_sense_code & 6) << 11) | ((this->std_sense_code & 1) << 8);
|
||||
break;
|
||||
case 0x2000: /* Sense line 2 is low */
|
||||
result = ((this->ext_sense_code & 0x20) << 7) |
|
||||
((this->ext_sense_code & 0x10) << 4);
|
||||
result = ((this->ext_sense_code & 0x20) << 7) | ((this->ext_sense_code & 0x10) << 4);
|
||||
break;
|
||||
case 0x1000: /* Sense line 1 is low */
|
||||
result = ((this->ext_sense_code & 8) << 10) |
|
||||
((this->ext_sense_code & 4) << 6);
|
||||
result = ((this->ext_sense_code & 8) << 10) | ((this->ext_sense_code & 4) << 6);
|
||||
break;
|
||||
case 0x100: /* Sense line 0 is low */
|
||||
result = ((this->ext_sense_code & 2) << 12) |
|
||||
((this->ext_sense_code & 1) << 12);
|
||||
result = ((this->ext_sense_code & 2) << 12) | ((this->ext_sense_code & 1) << 12);
|
||||
break;
|
||||
default:
|
||||
result = 0x3100U;
|
||||
|
@ -109,7 +99,7 @@ uint16_t DisplayID::read_monitor_sense(uint16_t data, uint16_t dirs)
|
|||
}
|
||||
|
||||
|
||||
uint16_t DisplayID::update_ddc_i2c(uint8_t sda, uint8_t scl)//(uint16_t data, uint16_t dirs)
|
||||
uint16_t DisplayID::update_ddc_i2c(uint8_t sda, uint8_t scl) //(uint16_t data, uint16_t dirs)
|
||||
{
|
||||
bool clk_gone_high = false;
|
||||
|
||||
|
@ -128,8 +118,7 @@ uint16_t DisplayID::update_ddc_i2c(uint8_t sda, uint8_t scl)//(uint16_t data, ui
|
|||
LOG_F(9, "DDC-I2C: START condition detected!");
|
||||
this->next_state = I2CState::DEV_ADDR;
|
||||
this->bit_count = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(9, "DDC-I2C: STOP condition detected!");
|
||||
this->next_state = I2CState::STOP;
|
||||
}
|
||||
|
@ -152,8 +141,7 @@ uint16_t DisplayID::update_ddc_i2c(uint8_t sda, uint8_t scl)//(uint16_t data, ui
|
|||
case I2CState::DEV_ADDR:
|
||||
if ((dev_addr & 0xFE) == 0xA0) {
|
||||
sda = 0; /* send ACK */
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(ERROR, "DDC-I2C: unknown device address 0x%X", this->dev_addr);
|
||||
sda = 1; /* send NACK */
|
||||
}
|
||||
|
@ -161,8 +149,7 @@ uint16_t DisplayID::update_ddc_i2c(uint8_t sda, uint8_t scl)//(uint16_t data, ui
|
|||
this->next_state = I2CState::DATA;
|
||||
this->data_ptr = this->edid;
|
||||
this->byte = *(this->data_ptr++);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this->next_state = I2CState::REG_ADDR;
|
||||
}
|
||||
break;
|
||||
|
@ -170,8 +157,7 @@ uint16_t DisplayID::update_ddc_i2c(uint8_t sda, uint8_t scl)//(uint16_t data, ui
|
|||
this->next_state = I2CState::DATA;
|
||||
if (!this->reg_addr) {
|
||||
sda = 0; /* send ACK */
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(ERROR, "DDC-I2C: unknown register address 0x%X", this->reg_addr);
|
||||
sda = 1; /* send NACK */
|
||||
}
|
||||
|
@ -182,12 +168,10 @@ uint16_t DisplayID::update_ddc_i2c(uint8_t sda, uint8_t scl)//(uint16_t data, ui
|
|||
if (!sda) {
|
||||
/* load next data byte */
|
||||
this->byte = *(this->data_ptr++);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(ERROR, "DDC-I2C: Oops! NACK received");
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
sda = 0; /* send ACK */
|
||||
}
|
||||
break;
|
||||
|
@ -204,8 +188,7 @@ uint16_t DisplayID::update_ddc_i2c(uint8_t sda, uint8_t scl)//(uint16_t data, ui
|
|||
if (this->prev_state == I2CState::DEV_ADDR) {
|
||||
LOG_F(9, "DDC-I2C: device address received, addr=0x%X", this->byte);
|
||||
this->dev_addr = this->byte;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(9, "DDC-I2C: register address received, addr=0x%X", this->byte);
|
||||
this->reg_addr = this->byte;
|
||||
}
|
||||
|
|
|
@ -74,26 +74,18 @@ private:
|
|||
uint8_t byte; /* byte value being currently transferred */
|
||||
uint8_t dev_addr; /* current device address */
|
||||
uint8_t reg_addr; /* current register address */
|
||||
uint8_t *data_ptr; /* ptr to data byte to be transferred next */
|
||||
uint8_t* data_ptr; /* ptr to data byte to be transferred next */
|
||||
|
||||
uint8_t edid[128] = {
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
|
||||
0x06, 0x10, 0x02, 0x9d, 0x01, 0x01, 0x01, 0x01,
|
||||
0x08, 0x09, 0x01, 0x01, 0x68, 0x20, 0x18, 0x28,
|
||||
0xe8, 0x04, 0x89, 0xa0, 0x57, 0x4a, 0x9b, 0x26,
|
||||
0x12, 0x48, 0x4c, 0x31, 0x2b, 0x80, 0x31, 0x59,
|
||||
0x45, 0x59, 0x61, 0x59, 0xa9, 0x40, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x60, 0x16,
|
||||
0x40, 0x40, 0x31, 0x70, 0x2b, 0x20, 0x20, 0x40,
|
||||
0x23, 0x00, 0x38, 0xea, 0x10, 0x00, 0x00, 0x18,
|
||||
0x48, 0x3f, 0x40, 0x32, 0x62, 0xb0, 0x32, 0x40,
|
||||
0x40, 0xc2, 0x13, 0x00, 0x38, 0xea, 0x10, 0x00,
|
||||
0x00, 0x18, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x30,
|
||||
0xa0, 0x1e, 0x55, 0x10, 0x00, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
|
||||
0x00, 0x53, 0x74, 0x75, 0x64, 0x69, 0x6f, 0x44,
|
||||
0x73, 0x70, 0x6c, 0x79, 0x31, 0x37, 0x00, 0x19
|
||||
};
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x06, 0x10, 0x02, 0x9d, 0x01, 0x01, 0x01,
|
||||
0x01, 0x08, 0x09, 0x01, 0x01, 0x68, 0x20, 0x18, 0x28, 0xe8, 0x04, 0x89, 0xa0, 0x57, 0x4a,
|
||||
0x9b, 0x26, 0x12, 0x48, 0x4c, 0x31, 0x2b, 0x80, 0x31, 0x59, 0x45, 0x59, 0x61, 0x59, 0xa9,
|
||||
0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x60, 0x16, 0x40, 0x40, 0x31, 0x70,
|
||||
0x2b, 0x20, 0x20, 0x40, 0x23, 0x00, 0x38, 0xea, 0x10, 0x00, 0x00, 0x18, 0x48, 0x3f, 0x40,
|
||||
0x32, 0x62, 0xb0, 0x32, 0x40, 0x40, 0xc2, 0x13, 0x00, 0x38, 0xea, 0x10, 0x00, 0x00, 0x18,
|
||||
0x00, 0x00, 0x00, 0xfd, 0x00, 0x30, 0xa0, 0x1e, 0x55, 0x10, 0x00, 0x0a, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x53, 0x74, 0x75, 0x64, 0x69, 0x6f, 0x44,
|
||||
0x73, 0x70, 0x6c, 0x79, 0x31, 0x37, 0x00, 0x19};
|
||||
|
||||
/* More EDID:
|
||||
00ff ffff ffff ff00 5a63 5151 0341 0000
|
||||
|
|
|
@ -19,14 +19,14 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include <cinttypes>
|
||||
#include <iostream>
|
||||
#include "macio.h"
|
||||
#include "viacuda.h"
|
||||
#include "awacs.h"
|
||||
#include "dbdma.h"
|
||||
#include "machines/machinebase.h"
|
||||
#include "macio.h"
|
||||
#include "viacuda.h"
|
||||
#include <cinttypes>
|
||||
#include <iostream>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
/** Heathrow Mac I/O device emulation.
|
||||
|
||||
|
@ -35,8 +35,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
using namespace std;
|
||||
|
||||
HeathrowIC::HeathrowIC() : PCIDevice("mac-io/heathrow")
|
||||
{
|
||||
HeathrowIC::HeathrowIC() : PCIDevice("mac-io/heathrow") {
|
||||
this->nvram = new NVram();
|
||||
|
||||
this->viacuda = new ViaCuda();
|
||||
|
@ -47,37 +46,34 @@ HeathrowIC::HeathrowIC() : PCIDevice("mac-io/heathrow")
|
|||
this->screamer->set_dma_out(this->snd_out_dma);
|
||||
}
|
||||
|
||||
HeathrowIC::~HeathrowIC()
|
||||
{
|
||||
HeathrowIC::~HeathrowIC() {
|
||||
if (this->nvram)
|
||||
delete(this->nvram);
|
||||
delete (this->nvram);
|
||||
|
||||
if (this->viacuda)
|
||||
delete(this->viacuda);
|
||||
delete (this->viacuda);
|
||||
}
|
||||
|
||||
|
||||
uint32_t HeathrowIC::pci_cfg_read(uint32_t reg_offs, uint32_t size)
|
||||
{
|
||||
uint32_t HeathrowIC::pci_cfg_read(uint32_t reg_offs, uint32_t size) {
|
||||
return this->pci_cfg_hdr[reg_offs & 0xFF];
|
||||
}
|
||||
|
||||
void HeathrowIC::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
|
||||
{
|
||||
void HeathrowIC::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) {
|
||||
switch (reg_offs) {
|
||||
case CFG_REG_BAR0: // base address register
|
||||
value = LE2BE(value);
|
||||
if (value == 0xFFFFFFFF) {
|
||||
LOG_F(ERROR, "%s err: BAR0 block size determination not \
|
||||
implemented yet \n", this->name.c_str());
|
||||
}
|
||||
else if (value & 1) {
|
||||
LOG_F(
|
||||
ERROR,
|
||||
"%s err: BAR0 block size determination not \
|
||||
implemented yet \n",
|
||||
this->name.c_str());
|
||||
} else if (value & 1) {
|
||||
LOG_F(ERROR, "%s err: BAR0 I/O space not supported! \n", this->name.c_str());
|
||||
}
|
||||
else if (value & 0x06) {
|
||||
} else if (value & 0x06) {
|
||||
LOG_F(ERROR, "%s err: BAR0 64-bit I/O space not supported! \n", this->name.c_str());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this->base_addr = value & 0xFFF80000;
|
||||
this->host_instance->pci_register_mmio_region(this->base_addr, 0x80000, this);
|
||||
LOG_F(INFO, "%s base address set to %x \n", this->name.c_str(), this->base_addr);
|
||||
|
@ -86,11 +82,10 @@ void HeathrowIC::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t HeathrowIC::dma_read(uint32_t offset, int size)
|
||||
{
|
||||
uint32_t HeathrowIC::dma_read(uint32_t offset, int size) {
|
||||
uint32_t res = 0;
|
||||
|
||||
switch(offset >> 8) {
|
||||
switch (offset >> 8) {
|
||||
case 8:
|
||||
res = this->snd_out_dma->reg_read(offset & 0xFF, size);
|
||||
break;
|
||||
|
@ -101,9 +96,8 @@ uint32_t HeathrowIC::dma_read(uint32_t offset, int size)
|
|||
return res;
|
||||
}
|
||||
|
||||
void HeathrowIC::dma_write(uint32_t offset, uint32_t value, int size)
|
||||
{
|
||||
switch(offset >> 8) {
|
||||
void HeathrowIC::dma_write(uint32_t offset, uint32_t value, int size) {
|
||||
switch (offset >> 8) {
|
||||
case 8:
|
||||
this->snd_out_dma->reg_write(offset & 0xFF, value, size);
|
||||
break;
|
||||
|
@ -113,8 +107,7 @@ void HeathrowIC::dma_write(uint32_t offset, uint32_t value, int size)
|
|||
}
|
||||
|
||||
|
||||
uint32_t HeathrowIC::read(uint32_t reg_start, uint32_t offset, int size)
|
||||
{
|
||||
uint32_t HeathrowIC::read(uint32_t reg_start, uint32_t offset, int size) {
|
||||
uint32_t res = 0;
|
||||
|
||||
LOG_F(9, "%s: reading from offset %x \n", this->name.c_str(), offset);
|
||||
|
@ -138,8 +131,7 @@ uint32_t HeathrowIC::read(uint32_t reg_start, uint32_t offset, int size)
|
|||
default:
|
||||
if (sub_addr >= 0x60) {
|
||||
res = this->nvram->read_byte((offset - 0x60000) >> 4);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(WARNING, "Attempting to read unmapped I/O space: %x \n", offset);
|
||||
}
|
||||
}
|
||||
|
@ -147,8 +139,7 @@ uint32_t HeathrowIC::read(uint32_t reg_start, uint32_t offset, int size)
|
|||
return res;
|
||||
}
|
||||
|
||||
void HeathrowIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
|
||||
{
|
||||
void HeathrowIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) {
|
||||
LOG_F(9, "%s: writing to offset %x \n", this->name.c_str(), offset);
|
||||
|
||||
unsigned sub_addr = (offset >> 12) & 0x7F;
|
||||
|
@ -170,15 +161,13 @@ void HeathrowIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int
|
|||
default:
|
||||
if (sub_addr >= 0x60) {
|
||||
this->nvram->write_byte((offset - 0x60000) >> 4, value);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(WARNING, "Attempting to write to unmapped I/O space: %x \n", offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t HeathrowIC::mio_ctrl_read(uint32_t offset, int size)
|
||||
{
|
||||
uint32_t HeathrowIC::mio_ctrl_read(uint32_t offset, int size) {
|
||||
uint32_t res = 0;
|
||||
|
||||
switch (offset & 0xFF) {
|
||||
|
@ -221,8 +210,7 @@ uint32_t HeathrowIC::mio_ctrl_read(uint32_t offset, int size)
|
|||
return res;
|
||||
}
|
||||
|
||||
void HeathrowIC::mio_ctrl_write(uint32_t offset, uint32_t value, int size)
|
||||
{
|
||||
void HeathrowIC::mio_ctrl_write(uint32_t offset, uint32_t value, int size) {
|
||||
switch (offset & 0xFF) {
|
||||
case 0x14:
|
||||
LOG_F(9, "read from MIO:Int_Mask2 register \n");
|
||||
|
|
|
@ -45,8 +45,12 @@ class HWComponent {
|
|||
public:
|
||||
virtual ~HWComponent() = default;
|
||||
|
||||
virtual std::string get_name(void) { return this->name; };
|
||||
virtual void set_name(std::string name) { this->name = name; };
|
||||
virtual std::string get_name(void) {
|
||||
return this->name;
|
||||
};
|
||||
virtual void set_name(std::string name) {
|
||||
this->name = name;
|
||||
};
|
||||
|
||||
virtual bool supports_type(HWCompType type) = 0;
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef I2C_H
|
||||
#define I2C_H
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
/** Base class for I2C devices */
|
||||
class I2CDevice {
|
||||
|
@ -37,16 +37,20 @@ public:
|
|||
virtual void start_transaction() = 0;
|
||||
virtual bool send_subaddress(uint8_t sub_addr) = 0;
|
||||
virtual bool send_byte(uint8_t data) = 0;
|
||||
virtual bool receive_byte(uint8_t *p_data) = 0;
|
||||
virtual bool receive_byte(uint8_t* p_data) = 0;
|
||||
};
|
||||
|
||||
/** Base class for I2C hosts */
|
||||
class I2CBus {
|
||||
public:
|
||||
I2CBus() { std::memset(this->dev_list, 0, sizeof(this->dev_list)); };
|
||||
~I2CBus() { std::memset(this->dev_list, 0, sizeof(this->dev_list)); };
|
||||
I2CBus() {
|
||||
std::memset(this->dev_list, 0, sizeof(this->dev_list));
|
||||
};
|
||||
~I2CBus() {
|
||||
std::memset(this->dev_list, 0, sizeof(this->dev_list));
|
||||
};
|
||||
|
||||
virtual void register_device(uint8_t dev_addr, I2CDevice *dev_obj) {
|
||||
virtual void register_device(uint8_t dev_addr, I2CDevice* dev_obj) {
|
||||
if (this->dev_list[dev_addr]) {
|
||||
throw std::invalid_argument(std::string("I2C address already taken!"));
|
||||
}
|
||||
|
@ -77,7 +81,7 @@ public:
|
|||
return this->dev_list[dev_addr]->send_byte(data);
|
||||
};
|
||||
|
||||
virtual bool receive_byte(uint8_t dev_addr, uint8_t *p_data) {
|
||||
virtual bool receive_byte(uint8_t dev_addr, uint8_t* p_data) {
|
||||
if (!this->dev_list[dev_addr]) {
|
||||
return false; /* no device -> no acknowledge */
|
||||
}
|
||||
|
@ -85,7 +89,7 @@ public:
|
|||
};
|
||||
|
||||
protected:
|
||||
I2CDevice *dev_list[128]; /* list of registered I2C devices */
|
||||
I2CDevice* dev_list[128]; /* list of registered I2C devices */
|
||||
};
|
||||
|
||||
#endif /* I2C_H */
|
||||
|
|
|
@ -22,9 +22,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef MACHINE_ID_H
|
||||
#define MACHINE_ID_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include "hwcomponent.h"
|
||||
#include "mmiodevice.h"
|
||||
#include <cinttypes>
|
||||
|
||||
/**
|
||||
@file Contains definitions for PowerMacintosh machine ID registers.
|
||||
|
@ -44,7 +44,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
*/
|
||||
class GossamerID : public MMIODevice {
|
||||
public:
|
||||
GossamerID(const uint16_t id) { this->id = id, this->name = "Machine-id"; };
|
||||
GossamerID(const uint16_t id) {
|
||||
this->id = id, this->name = "Machine-id";
|
||||
};
|
||||
~GossamerID() = default;
|
||||
|
||||
bool supports_type(HWCompType type) {
|
||||
|
@ -52,10 +54,10 @@ public:
|
|||
};
|
||||
|
||||
uint32_t read(uint32_t reg_start, uint32_t offset, int size) {
|
||||
return ((!offset && size == 2) ? this->id : 0); };
|
||||
return ((!offset && size == 2) ? this->id : 0);
|
||||
};
|
||||
|
||||
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
|
||||
{}; /* not writable */
|
||||
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size){}; /* not writable */
|
||||
|
||||
private:
|
||||
uint16_t id;
|
||||
|
|
|
@ -51,16 +51,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef MACIO_H
|
||||
#define MACIO_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include "hwcomponent.h"
|
||||
#include "pcidevice.h"
|
||||
#include "memctrlbase.h"
|
||||
#include "mmiodevice.h"
|
||||
#include "pcihost.h"
|
||||
#include "viacuda.h"
|
||||
#include "nvram.h"
|
||||
#include "awacs.h"
|
||||
#include "dbdma.h"
|
||||
#include "hwcomponent.h"
|
||||
#include "memctrlbase.h"
|
||||
#include "mmiodevice.h"
|
||||
#include "nvram.h"
|
||||
#include "pcidevice.h"
|
||||
#include "pcihost.h"
|
||||
#include "viacuda.h"
|
||||
#include <cinttypes>
|
||||
|
||||
/**
|
||||
Heathrow ASIC emulation
|
||||
|
@ -86,16 +86,19 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
VIA-CUDA register space: 0x00016000, size: 0x00002000
|
||||
*/
|
||||
|
||||
class HeathrowIC : public PCIDevice
|
||||
{
|
||||
class HeathrowIC : public PCIDevice {
|
||||
public:
|
||||
HeathrowIC();
|
||||
~HeathrowIC();
|
||||
|
||||
bool supports_type(HWCompType type) { return type == HWCompType::MMIO_DEV; };
|
||||
bool supports_type(HWCompType type) {
|
||||
return type == HWCompType::MMIO_DEV;
|
||||
};
|
||||
|
||||
/* PCI device methods */
|
||||
bool supports_io_space(void) { return false; };
|
||||
bool supports_io_space(void) {
|
||||
return false;
|
||||
};
|
||||
|
||||
uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size);
|
||||
void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size);
|
||||
|
@ -113,17 +116,23 @@ protected:
|
|||
|
||||
private:
|
||||
uint8_t pci_cfg_hdr[256] = {
|
||||
0x6B, 0x10, // vendor ID: Apple Computer Inc.
|
||||
0x10, 0x00, // device ID: Heathrow Mac I/O
|
||||
0x00, 0x00, // PCI command (set to 0 at power-up?)
|
||||
0x00, 0x00, // PCI status (set to 0 at power-up?)
|
||||
0x6B,
|
||||
0x10, // vendor ID: Apple Computer Inc.
|
||||
0x10,
|
||||
0x00, // device ID: Heathrow Mac I/O
|
||||
0x00,
|
||||
0x00, // PCI command (set to 0 at power-up?)
|
||||
0x00,
|
||||
0x00, // PCI status (set to 0 at power-up?)
|
||||
0x01, // revision ID
|
||||
// class code is reported in OF property "class-code" as 0xff0000
|
||||
0x00, // standard programming
|
||||
0x00, // subclass code
|
||||
0xFF, // class code: unassigned
|
||||
0x00, 0x00, // unknown defaults
|
||||
0x00, 0x00 // unknown defaults
|
||||
0x00,
|
||||
0x00, // unknown defaults
|
||||
0x00,
|
||||
0x00 // unknown defaults
|
||||
};
|
||||
|
||||
uint32_t int_mask2;
|
||||
|
@ -135,11 +144,11 @@ private:
|
|||
uint32_t feat_ctrl; // features control register
|
||||
|
||||
/* device cells */
|
||||
ViaCuda *viacuda; /* VIA cell with Cuda MCU attached to it */
|
||||
NVram *nvram; /* NVRAM cell */
|
||||
AWACDevice *screamer; /* Screamer audio codec instance */
|
||||
ViaCuda* viacuda; /* VIA cell with Cuda MCU attached to it */
|
||||
NVram* nvram; /* NVRAM cell */
|
||||
AWACDevice* screamer; /* Screamer audio codec instance */
|
||||
|
||||
DMAChannel *snd_out_dma;
|
||||
DMAChannel* snd_out_dma;
|
||||
};
|
||||
|
||||
#endif /* MACIO_H */
|
||||
|
|
|
@ -19,28 +19,26 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <algorithm> // to shut up MSVC errors (:
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "memctrlbase.h"
|
||||
|
||||
|
||||
MemCtrlBase::~MemCtrlBase()
|
||||
{
|
||||
for (auto ® : mem_regions) {
|
||||
MemCtrlBase::~MemCtrlBase() {
|
||||
for (auto& reg : mem_regions) {
|
||||
if (reg)
|
||||
delete(reg);
|
||||
delete (reg);
|
||||
}
|
||||
this->mem_regions.clear();
|
||||
this->address_map.clear();
|
||||
}
|
||||
|
||||
|
||||
AddressMapEntry *MemCtrlBase::find_range(uint32_t addr)
|
||||
{
|
||||
for (auto &entry : address_map) {
|
||||
AddressMapEntry* MemCtrlBase::find_range(uint32_t addr) {
|
||||
for (auto& entry : address_map) {
|
||||
if (addr >= entry.start && addr <= entry.end)
|
||||
return &entry;
|
||||
}
|
||||
|
@ -49,16 +47,15 @@ AddressMapEntry *MemCtrlBase::find_range(uint32_t addr)
|
|||
}
|
||||
|
||||
|
||||
bool MemCtrlBase::add_mem_region(uint32_t start_addr, uint32_t size,
|
||||
uint32_t dest_addr, uint32_t type, uint8_t init_val = 0)
|
||||
{
|
||||
bool MemCtrlBase::add_mem_region(
|
||||
uint32_t start_addr, uint32_t size, uint32_t dest_addr, uint32_t type, uint8_t init_val = 0) {
|
||||
AddressMapEntry entry;
|
||||
|
||||
/* error if a memory region for the given range already exists */
|
||||
if (find_range(start_addr) || find_range(start_addr + size))
|
||||
return false;
|
||||
|
||||
uint8_t *reg_content = new uint8_t[size];
|
||||
uint8_t* reg_content = new uint8_t[size];
|
||||
|
||||
this->mem_regions.push_back(reg_content);
|
||||
|
||||
|
@ -75,20 +72,17 @@ bool MemCtrlBase::add_mem_region(uint32_t start_addr, uint32_t size,
|
|||
}
|
||||
|
||||
|
||||
bool MemCtrlBase::add_rom_region(uint32_t start_addr, uint32_t size)
|
||||
{
|
||||
bool MemCtrlBase::add_rom_region(uint32_t start_addr, uint32_t size) {
|
||||
return add_mem_region(start_addr, size, 0, RT_ROM);
|
||||
}
|
||||
|
||||
|
||||
bool MemCtrlBase::add_ram_region(uint32_t start_addr, uint32_t size)
|
||||
{
|
||||
bool MemCtrlBase::add_ram_region(uint32_t start_addr, uint32_t size) {
|
||||
return add_mem_region(start_addr, size, 0, RT_RAM);
|
||||
}
|
||||
|
||||
|
||||
bool MemCtrlBase::add_mem_mirror(uint32_t start_addr, uint32_t dest_addr)
|
||||
{
|
||||
bool MemCtrlBase::add_mem_mirror(uint32_t start_addr, uint32_t dest_addr) {
|
||||
AddressMapEntry entry, *ref_entry;
|
||||
|
||||
ref_entry = find_range(dest_addr);
|
||||
|
@ -108,9 +102,8 @@ bool MemCtrlBase::add_mem_mirror(uint32_t start_addr, uint32_t dest_addr)
|
|||
}
|
||||
|
||||
|
||||
bool MemCtrlBase::set_data(uint32_t reg_addr, const uint8_t *data, uint32_t size)
|
||||
{
|
||||
AddressMapEntry *ref_entry;
|
||||
bool MemCtrlBase::set_data(uint32_t reg_addr, const uint8_t* data, uint32_t size) {
|
||||
AddressMapEntry* ref_entry;
|
||||
uint32_t cpy_size;
|
||||
|
||||
ref_entry = find_range(reg_addr);
|
||||
|
@ -124,9 +117,7 @@ bool MemCtrlBase::set_data(uint32_t reg_addr, const uint8_t *data, uint32_t size
|
|||
}
|
||||
|
||||
|
||||
bool MemCtrlBase::add_mmio_region(uint32_t start_addr, uint32_t size,
|
||||
MMIODevice *dev_instance)
|
||||
{
|
||||
bool MemCtrlBase::add_mmio_region(uint32_t start_addr, uint32_t size, MMIODevice* dev_instance) {
|
||||
AddressMapEntry entry;
|
||||
|
||||
/* error if another region for the given range already exists */
|
||||
|
|
|
@ -22,10 +22,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef MEMORY_CONTROLLER_BASE_H
|
||||
#define MEMORY_CONTROLLER_BASE_H
|
||||
|
||||
#include "mmiodevice.h"
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "mmiodevice.h"
|
||||
|
||||
enum RangeType {
|
||||
RT_ROM = 1, /* read-only memory */
|
||||
|
@ -55,18 +55,18 @@ public:
|
|||
virtual bool add_ram_region(uint32_t start_addr, uint32_t size);
|
||||
virtual bool add_mem_mirror(uint32_t start_addr, uint32_t dest_addr);
|
||||
|
||||
virtual bool add_mmio_region(uint32_t start_addr, uint32_t size, MMIODevice *dev_instance);
|
||||
virtual bool add_mmio_region(uint32_t start_addr, uint32_t size, MMIODevice* dev_instance);
|
||||
|
||||
virtual bool set_data(uint32_t reg_addr, const uint8_t *data, uint32_t size);
|
||||
virtual bool set_data(uint32_t reg_addr, const uint8_t* data, uint32_t size);
|
||||
|
||||
AddressMapEntry *find_range(uint32_t addr);
|
||||
AddressMapEntry* find_range(uint32_t addr);
|
||||
|
||||
protected:
|
||||
bool add_mem_region(uint32_t start_addr, uint32_t size, uint32_t dest_addr,
|
||||
uint32_t type, uint8_t init_val);
|
||||
bool add_mem_region(
|
||||
uint32_t start_addr, uint32_t size, uint32_t dest_addr, uint32_t type, uint8_t init_val);
|
||||
|
||||
private:
|
||||
std::vector<uint8_t *> mem_regions;
|
||||
std::vector<uint8_t*> mem_regions;
|
||||
std::vector<AddressMapEntry> address_map;
|
||||
};
|
||||
|
||||
|
|
|
@ -22,9 +22,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef MMIO_DEVICE_H
|
||||
#define MMIO_DEVICE_H
|
||||
|
||||
#include "hwcomponent.h"
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
#include "hwcomponent.h"
|
||||
|
||||
/** Abstract class representing a simple, memory-mapped I/O device */
|
||||
class MMIODevice : public HWComponent {
|
||||
|
|
|
@ -24,20 +24,19 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
Author: Max Poliakovski
|
||||
*/
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
#include "memreadwrite.h"
|
||||
#include "memctrlbase.h"
|
||||
#include "mmiodevice.h"
|
||||
#include "hwcomponent.h"
|
||||
#include "memctrlbase.h"
|
||||
#include "memreadwrite.h"
|
||||
#include "mmiodevice.h"
|
||||
#include "mpc106.h"
|
||||
|
||||
|
||||
MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle PCI host bridge")
|
||||
{
|
||||
MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle PCI host bridge") {
|
||||
this->name = "Grackle";
|
||||
|
||||
/* add PCI/ISA I/O space, 64K for now */
|
||||
|
@ -50,13 +49,11 @@ MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle PCI host bridge")
|
|||
this->io_space_devs.clear();
|
||||
}
|
||||
|
||||
MPC106::~MPC106()
|
||||
{
|
||||
MPC106::~MPC106() {
|
||||
this->pci_0_bus.clear();
|
||||
}
|
||||
|
||||
bool MPC106::supports_type(HWCompType type)
|
||||
{
|
||||
bool MPC106::supports_type(HWCompType type) {
|
||||
if (type == HWCompType::MEM_CTRL || type == HWCompType::MMIO_DEV ||
|
||||
type == HWCompType::PCI_HOST || type == HWCompType::PCI_DEV) {
|
||||
return true;
|
||||
|
@ -65,8 +62,7 @@ bool MPC106::supports_type(HWCompType type)
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t MPC106::read(uint32_t reg_start, uint32_t offset, int size)
|
||||
{
|
||||
uint32_t MPC106::read(uint32_t reg_start, uint32_t offset, int size) {
|
||||
uint32_t result;
|
||||
|
||||
if (reg_start == 0xFE000000) {
|
||||
|
@ -78,8 +74,7 @@ uint32_t MPC106::read(uint32_t reg_start, uint32_t offset, int size)
|
|||
}
|
||||
}
|
||||
LOG_F(ERROR, "Attempt to read from unmapped PCI I/O space, offset=0x%X", offset);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (offset >= 0x200000) {
|
||||
if (this->config_addr & 0x80) // process only if bit E (enable) is set
|
||||
return pci_read(size);
|
||||
|
@ -91,8 +86,7 @@ uint32_t MPC106::read(uint32_t reg_start, uint32_t offset, int size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void MPC106::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
|
||||
{
|
||||
void MPC106::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) {
|
||||
if (reg_start == 0xFE000000) {
|
||||
/* broadcast I/O request to devices that support I/O space
|
||||
until a device returns true that means "request accepted" */
|
||||
|
@ -102,26 +96,26 @@ void MPC106::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size
|
|||
}
|
||||
}
|
||||
LOG_F(ERROR, "Attempt to write to unmapped PCI I/O space, offset=0x%X", offset);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (offset < 0x200000) {
|
||||
this->config_addr = value;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (this->config_addr & 0x80) // process only if bit E (enable) is set
|
||||
return pci_write(value, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t MPC106::pci_read(uint32_t size)
|
||||
{
|
||||
uint32_t MPC106::pci_read(uint32_t size) {
|
||||
int bus_num, dev_num, fun_num, reg_offs;
|
||||
|
||||
bus_num = (this->config_addr >> 8) & 0xFF;
|
||||
if (bus_num) {
|
||||
LOG_F(ERROR, "%s err: read attempt from non-local PCI bus, config_addr = %x \n", \
|
||||
this->name.c_str(), this->config_addr);
|
||||
LOG_F(
|
||||
ERROR,
|
||||
"%s err: read attempt from non-local PCI bus, config_addr = %x \n",
|
||||
this->name.c_str(),
|
||||
this->config_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -135,7 +129,11 @@ uint32_t MPC106::pci_read(uint32_t size)
|
|||
if (this->pci_0_bus.count(dev_num)) {
|
||||
return this->pci_0_bus[dev_num]->pci_cfg_read(reg_offs, size);
|
||||
} else {
|
||||
LOG_F(ERROR, "%s err: read attempt from non-existing PCI device %d \n", this->name.c_str(), dev_num);
|
||||
LOG_F(
|
||||
ERROR,
|
||||
"%s err: read attempt from non-existing PCI device %d \n",
|
||||
this->name.c_str(),
|
||||
dev_num);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -143,14 +141,16 @@ uint32_t MPC106::pci_read(uint32_t size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void MPC106::pci_write(uint32_t value, uint32_t size)
|
||||
{
|
||||
void MPC106::pci_write(uint32_t value, uint32_t size) {
|
||||
int bus_num, dev_num, fun_num, reg_offs;
|
||||
|
||||
bus_num = (this->config_addr >> 8) & 0xFF;
|
||||
if (bus_num) {
|
||||
LOG_F(ERROR, "%s err: write attempt to non-local PCI bus, config_addr = %x \n",
|
||||
this->name.c_str(), this->config_addr);
|
||||
LOG_F(
|
||||
ERROR,
|
||||
"%s err: write attempt to non-local PCI bus, config_addr = %x \n",
|
||||
this->name.c_str(),
|
||||
this->config_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -164,19 +164,21 @@ void MPC106::pci_write(uint32_t value, uint32_t size)
|
|||
if (this->pci_0_bus.count(dev_num)) {
|
||||
this->pci_0_bus[dev_num]->pci_cfg_write(reg_offs, value, size);
|
||||
} else {
|
||||
LOG_F(ERROR, "%s err: write attempt to non-existing PCI device %d \n", \
|
||||
this->name.c_str(), dev_num);
|
||||
LOG_F(
|
||||
ERROR,
|
||||
"%s err: write attempt to non-existing PCI device %d \n",
|
||||
this->name.c_str(),
|
||||
dev_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t MPC106::pci_cfg_read(uint32_t reg_offs, uint32_t size)
|
||||
{
|
||||
uint32_t MPC106::pci_cfg_read(uint32_t reg_offs, uint32_t size) {
|
||||
#ifdef MPC106_DEBUG
|
||||
LOG_F(9, "read from Grackle register %08X\n", reg_offs);
|
||||
#endif
|
||||
|
||||
switch(size) {
|
||||
switch (size) {
|
||||
case 1:
|
||||
return this->my_pci_cfg_hdr[reg_offs];
|
||||
break;
|
||||
|
@ -193,26 +195,25 @@ uint32_t MPC106::pci_cfg_read(uint32_t reg_offs, uint32_t size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void MPC106::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
|
||||
{
|
||||
void MPC106::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) {
|
||||
#ifdef MPC106_DEBUG
|
||||
LOG_F(9, "write %08X to Grackle register %08X\n", value, reg_offs);
|
||||
#endif
|
||||
|
||||
// FIXME: implement write-protection for read-only registers
|
||||
switch(size) {
|
||||
switch (size) {
|
||||
case 1:
|
||||
this->my_pci_cfg_hdr[reg_offs] = value & 0xFF;
|
||||
break;
|
||||
case 2:
|
||||
this->my_pci_cfg_hdr[reg_offs] = (value >> 8) & 0xFF;
|
||||
this->my_pci_cfg_hdr[reg_offs+1] = value & 0xFF;
|
||||
this->my_pci_cfg_hdr[reg_offs + 1] = value & 0xFF;
|
||||
break;
|
||||
case 4:
|
||||
this->my_pci_cfg_hdr[reg_offs] = (value >> 24) & 0xFF;
|
||||
this->my_pci_cfg_hdr[reg_offs+1] = (value >> 16) & 0xFF;
|
||||
this->my_pci_cfg_hdr[reg_offs+2] = (value >> 8) & 0xFF;
|
||||
this->my_pci_cfg_hdr[reg_offs+3] = value & 0xFF;
|
||||
this->my_pci_cfg_hdr[reg_offs + 1] = (value >> 16) & 0xFF;
|
||||
this->my_pci_cfg_hdr[reg_offs + 2] = (value >> 8) & 0xFF;
|
||||
this->my_pci_cfg_hdr[reg_offs + 3] = value & 0xFF;
|
||||
break;
|
||||
default:
|
||||
LOG_F(ERROR, "MPC106 read error: invalid size parameter %d \n", size);
|
||||
|
@ -226,8 +227,7 @@ void MPC106::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
|
|||
}
|
||||
}
|
||||
|
||||
bool MPC106::pci_register_device(int dev_num, PCIDevice *dev_instance)
|
||||
{
|
||||
bool MPC106::pci_register_device(int dev_num, PCIDevice* dev_instance) {
|
||||
if (this->pci_0_bus.count(dev_num)) // is dev_num already registered?
|
||||
return false;
|
||||
|
||||
|
@ -242,14 +242,12 @@ bool MPC106::pci_register_device(int dev_num, PCIDevice *dev_instance)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MPC106::pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice *obj)
|
||||
{
|
||||
bool MPC106::pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice* obj) {
|
||||
// FIXME: add sanity checks!
|
||||
return this->add_mmio_region(start_addr, size, obj);
|
||||
}
|
||||
|
||||
void MPC106::setup_ram()
|
||||
{
|
||||
void MPC106::setup_ram() {
|
||||
uint32_t mem_start, mem_end, ext_mem_start, ext_mem_end, bank_start, bank_end;
|
||||
uint32_t ram_size = 0;
|
||||
|
||||
|
|
127
devices/mpc106.h
127
devices/mpc106.h
|
@ -35,17 +35,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef MPC106_H_
|
||||
#define MPC106_H_
|
||||
|
||||
#include <cinttypes>
|
||||
#include <unordered_map>
|
||||
#include "hwcomponent.h"
|
||||
#include "memctrlbase.h"
|
||||
#include "mmiodevice.h"
|
||||
#include "pcidevice.h"
|
||||
#include "pcihost.h"
|
||||
#include <cinttypes>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
class MPC106 : public MemCtrlBase, public PCIDevice, public PCIHost
|
||||
{
|
||||
class MPC106 : public MemCtrlBase, public PCIDevice, public PCIHost {
|
||||
public:
|
||||
MPC106();
|
||||
~MPC106();
|
||||
|
@ -56,7 +55,7 @@ public:
|
|||
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size);
|
||||
|
||||
/* PCI host bridge API */
|
||||
bool pci_register_device(int dev_num, PCIDevice *dev_instance);
|
||||
bool pci_register_device(int dev_num, PCIDevice* dev_instance);
|
||||
|
||||
protected:
|
||||
/* PCI access */
|
||||
|
@ -67,9 +66,11 @@ protected:
|
|||
uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size);
|
||||
void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size);
|
||||
|
||||
bool supports_io_space(void) { return true; };
|
||||
bool supports_io_space(void) {
|
||||
return true;
|
||||
};
|
||||
|
||||
bool pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice *obj);
|
||||
bool pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice* obj);
|
||||
|
||||
void setup_ram(void);
|
||||
|
||||
|
@ -87,90 +88,80 @@ private:
|
|||
0x00, // latency timer
|
||||
0x00, // header type
|
||||
0x00, // BIST Control
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, //Interrupt line
|
||||
0x00, //Interrupt pin
|
||||
0x00, //MIN GNT
|
||||
0x00, //MAX LAT
|
||||
0x00, //Bus number
|
||||
0x00, //Subordinate bus number
|
||||
0x00, //Discount counter
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, //Performance monitor command
|
||||
0x00, 0x00, //Performance monitor mode control
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, // Interrupt line
|
||||
0x00, // Interrupt pin
|
||||
0x00, // MIN GNT
|
||||
0x00, // MAX LAT
|
||||
0x00, // Bus number
|
||||
0x00, // Subordinate bus number
|
||||
0x00, // Discount counter
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // Performance monitor command
|
||||
0x00, 0x00, // Performance monitor mode control
|
||||
0xFF, 0xFF,
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, //Performance monitor counter 0
|
||||
0x00, 0x00, 0x00, 0x00, //Performance monitor counter 1
|
||||
0x00, 0x00, 0x00, 0x00, //Performance monitor counter 2
|
||||
0x00, 0x00, 0x00, 0x00, //Performance monitor counter 3
|
||||
0x00, 0x00, 0x00, 0x00, // Performance monitor counter 0
|
||||
0x00, 0x00, 0x00, 0x00, // Performance monitor counter 1
|
||||
0x00, 0x00, 0x00, 0x00, // Performance monitor counter 2
|
||||
0x00, 0x00, 0x00, 0x00, // Performance monitor counter 3
|
||||
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF,
|
||||
|
||||
0x00, 0x00, //Power mgt config 1
|
||||
0x00, //Power mgt config 2
|
||||
0xCD, //default value for ODCR
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //Memory Starting Address
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //Extended Memory Starting Address
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //Memory Ending Address
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //Extended Memory Ending Address
|
||||
0x00, 0x00, // Power mgt config 1
|
||||
0x00, // Power mgt config 2
|
||||
0xCD, // default value for ODCR
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, // Memory Starting Address
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Extended Memory Starting Address
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Memory Ending Address
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Extended Memory Ending Address
|
||||
|
||||
0x00, //Memory bank enable
|
||||
0x00, // Memory bank enable
|
||||
0xFF, 0xFF,
|
||||
0x00, //Memory page mode
|
||||
0x00, // Memory page mode
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
0x10, 0x00, 0x00, 0xFF, // PICR1
|
||||
0x0C, 0x06, 0x0C, 0x00, // PICR2
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, //ECC single-bit error counter
|
||||
0x00, //ECC single-bit error trigger
|
||||
0x04, //Alternate OS visible paramaters 1
|
||||
0x01, //Alternate OS visible paramaters 2
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, // ECC single-bit error counter
|
||||
0x00, // ECC single-bit error trigger
|
||||
0x04, // Alternate OS visible paramaters 1
|
||||
0x01, // Alternate OS visible paramaters 2
|
||||
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
0x01, //Error enabling 1
|
||||
0x00, //Error detection 1
|
||||
0x01, // Error enabling 1
|
||||
0x00, // Error detection 1
|
||||
0xFF,
|
||||
0x00, //60x bus error status
|
||||
0x00, //Error enabling 2
|
||||
0x00, //Error detection 2
|
||||
0x00, // 60x bus error status
|
||||
0x00, // Error enabling 2
|
||||
0x00, // Error detection 2
|
||||
0xFF,
|
||||
0x00, //PCI bus error status
|
||||
0x00, 0x00, 0x00, 0x00, //60x/PCI ERROR address
|
||||
0x00, // PCI bus error status
|
||||
0x00, 0x00, 0x00, 0x00, // 60x/PCI ERROR address
|
||||
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF,
|
||||
|
||||
0x42, 0x00, 0xFF, 0x0F, //Emulation support config 1
|
||||
0x00, 0x00, 0x00, 0x00, //Modified memory status (no clear)
|
||||
0x20, 0x00, 0x00, 0x00, //Emulation support config 2
|
||||
0x00, 0x00, 0x00, 0x00, //Modified memory status (clear)
|
||||
0x42, 0x00, 0xFF, 0x0F, // Emulation support config 1
|
||||
0x00, 0x00, 0x00, 0x00, // Modified memory status (no clear)
|
||||
0x20, 0x00, 0x00, 0x00, // Emulation support config 2
|
||||
0x00, 0x00, 0x00, 0x00, // Modified memory status (clear)
|
||||
|
||||
0x00, 0x00, 0x02, 0xFF, //Memory ctrl config 1
|
||||
0x03, 0x00, 0x00, 0x00, //Memory ctrl config 2
|
||||
0x00, 0x00, 0x00, 0x00, //Memory ctrl config 3
|
||||
0x00, 0x00, 0x10, 0x00 //Memory ctrl config 4
|
||||
0x00, 0x00, 0x02, 0xFF, // Memory ctrl config 1
|
||||
0x03, 0x00, 0x00, 0x00, // Memory ctrl config 2
|
||||
0x00, 0x00, 0x00, 0x00, // Memory ctrl config 3
|
||||
0x00, 0x00, 0x10, 0x00 // Memory ctrl config 4
|
||||
};
|
||||
|
||||
uint32_t config_addr;
|
||||
//uint32_t config_data;
|
||||
// uint32_t config_data;
|
||||
|
||||
std::unordered_map<int, PCIDevice*> pci_0_bus;
|
||||
std::vector<PCIDevice*> io_space_devs;
|
||||
|
|
|
@ -19,12 +19,12 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <cinttypes>
|
||||
#include "nvram.h"
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
/** @file Non-volatile RAM implementation.
|
||||
*/
|
||||
|
@ -34,8 +34,7 @@ using namespace std;
|
|||
/** the signature for NVRAM backing file identification. */
|
||||
static char NVRAM_FILE_ID[] = "DINGUSPPCNVRAM";
|
||||
|
||||
NVram::NVram(std::string file_name, uint32_t ram_size)
|
||||
{
|
||||
NVram::NVram(std::string file_name, uint32_t ram_size) {
|
||||
this->file_name = file_name;
|
||||
this->ram_size = ram_size;
|
||||
|
||||
|
@ -44,20 +43,17 @@ NVram::NVram(std::string file_name, uint32_t ram_size)
|
|||
this->init();
|
||||
}
|
||||
|
||||
NVram::~NVram()
|
||||
{
|
||||
NVram::~NVram() {
|
||||
this->save();
|
||||
if (this->storage)
|
||||
delete this->storage;
|
||||
}
|
||||
|
||||
uint8_t NVram::read_byte(uint32_t offset)
|
||||
{
|
||||
uint8_t NVram::read_byte(uint32_t offset) {
|
||||
return (this->storage[offset]);
|
||||
}
|
||||
|
||||
void NVram::write_byte(uint32_t offset, uint8_t val)
|
||||
{
|
||||
void NVram::write_byte(uint32_t offset, uint8_t val) {
|
||||
this->storage[offset] = val;
|
||||
}
|
||||
|
||||
|
@ -67,12 +63,10 @@ void NVram::init() {
|
|||
|
||||
ifstream f(this->file_name, ios::in | ios::binary);
|
||||
|
||||
if (f.fail() || !f.read(sig, sizeof(NVRAM_FILE_ID)) || \
|
||||
!f.read((char *)&data_size, sizeof(data_size)) || \
|
||||
memcmp(sig, NVRAM_FILE_ID, sizeof(NVRAM_FILE_ID)) || \
|
||||
data_size != this->ram_size || \
|
||||
!f.read((char *)this->storage, this->ram_size))
|
||||
{
|
||||
if (f.fail() || !f.read(sig, sizeof(NVRAM_FILE_ID)) ||
|
||||
!f.read((char*)&data_size, sizeof(data_size)) ||
|
||||
memcmp(sig, NVRAM_FILE_ID, sizeof(NVRAM_FILE_ID)) || data_size != this->ram_size ||
|
||||
!f.read((char*)this->storage, this->ram_size)) {
|
||||
LOG_F(WARNING, "Could not restore NVRAM content from the given file. \n");
|
||||
memset(this->storage, 0, sizeof(this->ram_size));
|
||||
}
|
||||
|
@ -80,16 +74,15 @@ void NVram::init() {
|
|||
f.close();
|
||||
}
|
||||
|
||||
void NVram::save()
|
||||
{
|
||||
void NVram::save() {
|
||||
ofstream f(this->file_name, ios::out | ios::binary);
|
||||
|
||||
/* write file identification */
|
||||
f.write(NVRAM_FILE_ID, sizeof(NVRAM_FILE_ID));
|
||||
f.write((char *)&this->ram_size, sizeof(this->ram_size));
|
||||
f.write((char*)&this->ram_size, sizeof(this->ram_size));
|
||||
|
||||
/* write NVRAM content */
|
||||
f.write((char *)this->storage, this->ram_size);
|
||||
f.write((char*)this->storage, this->ram_size);
|
||||
|
||||
f.close();
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef NVRAM_H
|
||||
#define NVRAM_H
|
||||
|
||||
#include <string>
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
|
||||
/** @file Non-volatile RAM emulation.
|
||||
|
||||
|
@ -31,8 +31,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
automatically saved to and restored from the dedicated file.
|
||||
*/
|
||||
|
||||
class NVram
|
||||
{
|
||||
class NVram {
|
||||
public:
|
||||
NVram(std::string file_name = "nvram.bin", uint32_t ram_size = 8192);
|
||||
~NVram();
|
||||
|
|
|
@ -22,10 +22,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef PCI_DEVICE_H
|
||||
#define PCI_DEVICE_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
#include "mmiodevice.h"
|
||||
#include "pcihost.h"
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
|
||||
/* convert little-endian DWORD to big-endian DWORD */
|
||||
#define LE2BE(x) (x >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | (x << 24)
|
||||
|
@ -45,27 +45,33 @@ enum {
|
|||
|
||||
class PCIDevice : public MMIODevice {
|
||||
public:
|
||||
PCIDevice(std::string name) { this->pci_name = name; };
|
||||
PCIDevice(std::string name) {
|
||||
this->pci_name = name;
|
||||
};
|
||||
virtual ~PCIDevice() = default;
|
||||
|
||||
virtual bool supports_io_space(void) = 0;
|
||||
|
||||
/* I/O space access methods */
|
||||
virtual bool pci_io_read(uint32_t offset, uint32_t size, uint32_t* res)
|
||||
{ return false; };
|
||||
virtual bool pci_io_read(uint32_t offset, uint32_t size, uint32_t* res) {
|
||||
return false;
|
||||
};
|
||||
|
||||
virtual bool pci_io_write(uint32_t offset, uint32_t value, uint32_t size)
|
||||
{ return false; };
|
||||
virtual bool pci_io_write(uint32_t offset, uint32_t value, uint32_t size) {
|
||||
return false;
|
||||
};
|
||||
|
||||
/* configuration space access methods */
|
||||
virtual uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size) = 0;
|
||||
virtual void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) = 0;
|
||||
|
||||
virtual void set_host(PCIHost* host_instance) { this->host_instance = host_instance; };
|
||||
virtual void set_host(PCIHost* host_instance) {
|
||||
this->host_instance = host_instance;
|
||||
};
|
||||
|
||||
protected:
|
||||
std::string pci_name; // human-readable device name
|
||||
PCIHost *host_instance; // host bridge instance to call back
|
||||
PCIHost* host_instance; // host bridge instance to call back
|
||||
uint32_t base_addr; // base address register 0
|
||||
};
|
||||
|
||||
|
|
|
@ -7,9 +7,8 @@ class PCIDevice; // forward declaration to prevent errors
|
|||
|
||||
class PCIHost {
|
||||
public:
|
||||
virtual bool pci_register_device(int dev_num, PCIDevice *dev_instance) = 0;
|
||||
virtual bool pci_register_mmio_region(uint32_t start_addr, uint32_t size,
|
||||
PCIDevice *obj) = 0;
|
||||
virtual bool pci_register_device(int dev_num, PCIDevice* dev_instance) = 0;
|
||||
virtual bool pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice* obj) = 0;
|
||||
};
|
||||
|
||||
#endif /* PCI_HOST_H */
|
||||
|
|
|
@ -47,16 +47,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef SPD_EEPROM_H
|
||||
#define SPD_EEPROM_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include "i2c.h"
|
||||
#include "hwcomponent.h"
|
||||
#include "i2c.h"
|
||||
#include <cinttypes>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
enum RAMType : int {
|
||||
SDRAM = 4
|
||||
};
|
||||
enum RAMType : int { SDRAM = 4 };
|
||||
|
||||
|
||||
class SpdSdram168 : public HWComponent, public I2CDevice {
|
||||
|
@ -68,10 +66,12 @@ public:
|
|||
|
||||
~SpdSdram168() = default;
|
||||
|
||||
bool supports_type(HWCompType type) { return type == HWCompType::RAM; };
|
||||
bool supports_type(HWCompType type) {
|
||||
return type == HWCompType::RAM;
|
||||
};
|
||||
|
||||
void set_capacity(int capacity_megs) {
|
||||
switch(capacity_megs) {
|
||||
switch (capacity_megs) {
|
||||
case 32:
|
||||
this->eeprom_data[3] = 0xC; /* 12 rows */
|
||||
this->eeprom_data[4] = 0x8; /* 8 columns */
|
||||
|
@ -95,11 +95,12 @@ public:
|
|||
default:
|
||||
throw std::invalid_argument(std::string("Unsupported capacity!"));
|
||||
}
|
||||
LOG_F(INFO, "SDRAM capacity set to %dMB, I2C addr = 0x%X",
|
||||
capacity_megs, this->dev_addr);
|
||||
LOG_F(INFO, "SDRAM capacity set to %dMB, I2C addr = 0x%X", capacity_megs, this->dev_addr);
|
||||
};
|
||||
|
||||
void start_transaction() { this->pos = 0; };
|
||||
void start_transaction() {
|
||||
this->pos = 0;
|
||||
};
|
||||
|
||||
bool send_subaddress(uint8_t sub_addr) {
|
||||
this->pos = sub_addr;
|
||||
|
@ -112,7 +113,7 @@ public:
|
|||
return true;
|
||||
};
|
||||
|
||||
bool receive_byte(uint8_t *p_data) {
|
||||
bool receive_byte(uint8_t* p_data) {
|
||||
if (this->pos >= this->eeprom_data[0]) {
|
||||
this->pos = 0; /* attempt to read past SPD data should wrap around */
|
||||
}
|
||||
|
|
|
@ -24,15 +24,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
Author: Max Poliakovski 2019
|
||||
*/
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include <cinttypes>
|
||||
#include "viacuda.h"
|
||||
#include "adb.h"
|
||||
#include <cinttypes>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
ViaCuda::ViaCuda()
|
||||
{
|
||||
ViaCuda::ViaCuda() {
|
||||
this->name = "ViaCuda";
|
||||
|
||||
/* FIXME: is this the correct
|
||||
|
@ -44,7 +43,7 @@ ViaCuda::ViaCuda()
|
|||
this->via_regs[VIA_T1LH] = 0xFF;
|
||||
this->via_regs[VIA_IER] = 0x7F;
|
||||
|
||||
//PRAM Pre-Initialization
|
||||
// PRAM Pre-Initialization
|
||||
this->pram_obj = new NVram("pram.bin", 256);
|
||||
|
||||
this->adb_obj = new ADB_Bus();
|
||||
|
@ -52,14 +51,12 @@ ViaCuda::ViaCuda()
|
|||
this->init();
|
||||
}
|
||||
|
||||
ViaCuda::~ViaCuda()
|
||||
{
|
||||
ViaCuda::~ViaCuda() {
|
||||
if (this->pram_obj)
|
||||
delete (this->pram_obj);
|
||||
}
|
||||
|
||||
void ViaCuda::init()
|
||||
{
|
||||
void ViaCuda::init() {
|
||||
this->old_tip = 0;
|
||||
this->old_byteack = 0;
|
||||
this->treq = 1;
|
||||
|
@ -68,8 +65,7 @@ void ViaCuda::init()
|
|||
this->poll_rate = 11;
|
||||
}
|
||||
|
||||
uint8_t ViaCuda::read(int reg)
|
||||
{
|
||||
uint8_t ViaCuda::read(int reg) {
|
||||
uint8_t res;
|
||||
|
||||
LOG_F(9, "Read VIA reg %x \n", (uint32_t)reg);
|
||||
|
@ -92,8 +88,7 @@ uint8_t ViaCuda::read(int reg)
|
|||
return res;
|
||||
}
|
||||
|
||||
void ViaCuda::write(int reg, uint8_t value)
|
||||
{
|
||||
void ViaCuda::write(int reg, uint8_t value) {
|
||||
switch (reg & 0xF) {
|
||||
case VIA_B:
|
||||
this->via_regs[VIA_B] = value;
|
||||
|
@ -120,8 +115,7 @@ void ViaCuda::write(int reg, uint8_t value)
|
|||
this->via_regs[VIA_ACR] = value;
|
||||
break;
|
||||
case VIA_IER:
|
||||
this->via_regs[VIA_IER] = (value & 0x80) ? value & 0x7F
|
||||
: this->via_regs[VIA_IER] & ~value;
|
||||
this->via_regs[VIA_IER] = (value & 0x80) ? value & 0x7F : this->via_regs[VIA_IER] & ~value;
|
||||
LOG_F(INFO, "VIA_IER updated to %d \n", (uint32_t)this->via_regs[VIA_IER]);
|
||||
print_enabled_ints();
|
||||
break;
|
||||
|
@ -130,9 +124,8 @@ void ViaCuda::write(int reg, uint8_t value)
|
|||
}
|
||||
}
|
||||
|
||||
void ViaCuda::print_enabled_ints()
|
||||
{
|
||||
const char *via_int_src[] = { "CA2", "CA1", "SR", "CB2", "CB1", "T2", "T1" };
|
||||
void ViaCuda::print_enabled_ints() {
|
||||
const char* via_int_src[] = {"CA2", "CA1", "SR", "CB2", "CB1", "T2", "T1"};
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
if (this->via_regs[VIA_IER] & (1 << i))
|
||||
|
@ -140,18 +133,15 @@ void ViaCuda::print_enabled_ints()
|
|||
}
|
||||
}
|
||||
|
||||
inline bool ViaCuda::ready()
|
||||
{
|
||||
inline bool ViaCuda::ready() {
|
||||
return ((this->via_regs[VIA_DIRB] & 0x38) == 0x30);
|
||||
}
|
||||
|
||||
inline void ViaCuda::assert_sr_int()
|
||||
{
|
||||
inline void ViaCuda::assert_sr_int() {
|
||||
this->via_regs[VIA_IFR] |= 0x84;
|
||||
}
|
||||
|
||||
void ViaCuda::write(uint8_t new_state)
|
||||
{
|
||||
void ViaCuda::write(uint8_t new_state) {
|
||||
if (!ready()) {
|
||||
LOG_F(WARNING, "Cuda not ready! \n");
|
||||
return;
|
||||
|
@ -183,8 +173,7 @@ void ViaCuda::write(uint8_t new_state)
|
|||
}
|
||||
|
||||
this->in_count = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(9, "Cuda: enter sync state \n");
|
||||
this->via_regs[VIA_B] &= ~CUDA_TREQ; /* assert TREQ */
|
||||
this->treq = 0;
|
||||
|
@ -193,18 +182,15 @@ void ViaCuda::write(uint8_t new_state)
|
|||
}
|
||||
|
||||
assert_sr_int(); /* send dummy byte as idle acknowledge or attention */
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (this->via_regs[VIA_ACR] & 0x10) { /* data transfer: Host --> Cuda */
|
||||
if (this->in_count < 16) {
|
||||
this->in_buf[this->in_count++] = this->via_regs[VIA_SR];
|
||||
assert_sr_int(); /* tell the system we've read the data */
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(WARNING, "Cuda input buffer exhausted! \n");
|
||||
}
|
||||
}
|
||||
else { /* data transfer: Cuda --> Host */
|
||||
} else { /* data transfer: Cuda --> Host */
|
||||
(this->*out_handler)();
|
||||
assert_sr_int(); /* tell the system we've written the data */
|
||||
}
|
||||
|
@ -212,25 +198,21 @@ void ViaCuda::write(uint8_t new_state)
|
|||
}
|
||||
|
||||
/* sends zeros to host at infinitum */
|
||||
void ViaCuda::null_out_handler()
|
||||
{
|
||||
void ViaCuda::null_out_handler() {
|
||||
this->via_regs[VIA_SR] = 0;
|
||||
}
|
||||
|
||||
/* sends data from out_buf until exhausted, then switches to next_out_handler */
|
||||
void ViaCuda::out_buf_handler()
|
||||
{
|
||||
void ViaCuda::out_buf_handler() {
|
||||
if (this->out_pos < this->out_count) {
|
||||
LOG_F(9, "OutBufHandler: sending next byte 0x%X", this->out_buf[this->out_pos]);
|
||||
this->via_regs[VIA_SR] = this->out_buf[this->out_pos++];
|
||||
}
|
||||
else if (this->is_open_ended) {
|
||||
} else if (this->is_open_ended) {
|
||||
LOG_F(9, "OutBufHandler: switching to next handler");
|
||||
this->out_handler = this->next_out_handler;
|
||||
this->next_out_handler = &ViaCuda::null_out_handler;
|
||||
(this->*out_handler)();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(9, "Sending last byte");
|
||||
this->out_count = 0;
|
||||
this->via_regs[VIA_B] |= CUDA_TREQ; /* negate TREQ */
|
||||
|
@ -238,8 +220,7 @@ void ViaCuda::out_buf_handler()
|
|||
}
|
||||
}
|
||||
|
||||
void ViaCuda::response_header(uint32_t pkt_type, uint32_t pkt_flag)
|
||||
{
|
||||
void ViaCuda::response_header(uint32_t pkt_type, uint32_t pkt_flag) {
|
||||
this->out_buf[0] = pkt_type;
|
||||
this->out_buf[1] = pkt_flag;
|
||||
this->out_buf[2] = this->in_buf[1]; /* copy original cmd */
|
||||
|
@ -250,8 +231,7 @@ void ViaCuda::response_header(uint32_t pkt_type, uint32_t pkt_flag)
|
|||
this->is_open_ended = false;
|
||||
}
|
||||
|
||||
void ViaCuda::error_response(uint32_t error)
|
||||
{
|
||||
void ViaCuda::error_response(uint32_t error) {
|
||||
this->out_buf[0] = CUDA_PKT_ERROR;
|
||||
this->out_buf[1] = error;
|
||||
this->out_buf[2] = this->in_buf[0];
|
||||
|
@ -263,8 +243,7 @@ void ViaCuda::error_response(uint32_t error)
|
|||
this->is_open_ended = false;
|
||||
}
|
||||
|
||||
void ViaCuda::process_packet()
|
||||
{
|
||||
void ViaCuda::process_packet() {
|
||||
if (this->in_count < 2) {
|
||||
LOG_F(ERROR, "Cuda: invalid packet (too few data)!\n");
|
||||
error_response(CUDA_ERR_BAD_SIZE);
|
||||
|
@ -291,57 +270,48 @@ void ViaCuda::process_packet()
|
|||
}
|
||||
}
|
||||
|
||||
void ViaCuda::process_adb_command(uint8_t cmd_byte, int data_count)
|
||||
{
|
||||
int adb_dev = cmd_byte >> 4; //2 for keyboard, 3 for mouse
|
||||
void ViaCuda::process_adb_command(uint8_t cmd_byte, int data_count) {
|
||||
int adb_dev = cmd_byte >> 4; // 2 for keyboard, 3 for mouse
|
||||
int cmd = cmd_byte & 0xF;
|
||||
|
||||
if(!cmd) {
|
||||
if (!cmd) {
|
||||
LOG_F(9, "Cuda: ADB SendReset command requested\n");
|
||||
response_header(CUDA_PKT_ADB, 0);
|
||||
}
|
||||
else if (cmd == 1) {
|
||||
} else if (cmd == 1) {
|
||||
LOG_F(9, "Cuda: ADB Flush command requested\n");
|
||||
response_header(CUDA_PKT_ADB, 0);
|
||||
}
|
||||
else if ((cmd & 0xC) == 8) {
|
||||
} else if ((cmd & 0xC) == 8) {
|
||||
LOG_F(9, "Cuda: ADB Listen command requested\n");
|
||||
int adb_reg = cmd_byte & 0x3;
|
||||
if (adb_obj->listen(adb_dev, adb_reg)){
|
||||
if (adb_obj->listen(adb_dev, adb_reg)) {
|
||||
response_header(CUDA_PKT_ADB, 0);
|
||||
for (int data_ptr = 0; data_ptr < adb_obj->get_output_len(); data_ptr++) {
|
||||
this->in_buf[(2 + data_ptr)] = adb_obj->get_output_byte(data_ptr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
response_header(CUDA_PKT_ADB, 2);
|
||||
}
|
||||
}
|
||||
else if ((cmd & 0xC) == 0xC) {
|
||||
} else if ((cmd & 0xC) == 0xC) {
|
||||
LOG_F(9, "Cuda: ADB Talk command requested\n");
|
||||
response_header(CUDA_PKT_ADB, 0);
|
||||
int adb_reg = cmd_byte & 0x3;
|
||||
if (adb_obj->talk(adb_dev, adb_reg, this->in_buf[2])) {
|
||||
response_header(CUDA_PKT_ADB, 0);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
response_header(CUDA_PKT_ADB, 2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(ERROR, "Cuda: unsupported ADB command 0x%x \n", cmd);
|
||||
error_response(CUDA_ERR_BAD_CMD);
|
||||
}
|
||||
}
|
||||
|
||||
void ViaCuda::pseudo_command(int cmd, int data_count)
|
||||
{
|
||||
void ViaCuda::pseudo_command(int cmd, int data_count) {
|
||||
switch (cmd) {
|
||||
case CUDA_START_STOP_AUTOPOLL:
|
||||
if (this->in_buf[2]) {
|
||||
LOG_F(INFO, "Cuda: autopoll started, rate: %dms", this->poll_rate);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG_F(INFO, "Cuda: autopoll stopped");
|
||||
}
|
||||
response_header(CUDA_PKT_PSEUDO, 0);
|
||||
|
@ -371,8 +341,8 @@ void ViaCuda::pseudo_command(int cmd, int data_count)
|
|||
case CUDA_COMB_FMT_I2C:
|
||||
response_header(CUDA_PKT_PSEUDO, 0);
|
||||
if (this->in_count >= 5) {
|
||||
i2c_comb_transaction(this->in_buf[2], this->in_buf[3], this->in_buf[4],
|
||||
&this->in_buf[5], this->in_count - 5);
|
||||
i2c_comb_transaction(
|
||||
this->in_buf[2], this->in_buf[3], this->in_buf[4], &this->in_buf[5], this->in_count - 5);
|
||||
}
|
||||
break;
|
||||
case CUDA_OUT_PB0: /* undocumented call! */
|
||||
|
@ -386,14 +356,11 @@ void ViaCuda::pseudo_command(int cmd, int data_count)
|
|||
}
|
||||
|
||||
/* sends data from the current I2C to host ad infinitum */
|
||||
void ViaCuda::i2c_handler()
|
||||
{
|
||||
void ViaCuda::i2c_handler() {
|
||||
this->receive_byte(this->curr_i2c_addr, &this->via_regs[VIA_SR]);
|
||||
}
|
||||
|
||||
void ViaCuda::i2c_simple_transaction(uint8_t dev_addr, const uint8_t* in_buf,
|
||||
int in_bytes)
|
||||
{
|
||||
void ViaCuda::i2c_simple_transaction(uint8_t dev_addr, const uint8_t* in_buf, int in_bytes) {
|
||||
int op_type = dev_addr & 1; /* 0 - write to device, 1 - read from device */
|
||||
|
||||
dev_addr >>= 1; /* strip RD/WR bit */
|
||||
|
@ -422,9 +389,8 @@ void ViaCuda::i2c_simple_transaction(uint8_t dev_addr, const uint8_t* in_buf,
|
|||
}
|
||||
}
|
||||
|
||||
void ViaCuda::i2c_comb_transaction(uint8_t dev_addr, uint8_t sub_addr,
|
||||
uint8_t dev_addr1, const uint8_t* in_buf, int in_bytes)
|
||||
{
|
||||
void ViaCuda::i2c_comb_transaction(
|
||||
uint8_t dev_addr, uint8_t sub_addr, uint8_t dev_addr1, const uint8_t* in_buf, int in_bytes) {
|
||||
int op_type = dev_addr1 & 1; /* 0 - write to device, 1 - read from device */
|
||||
|
||||
if ((dev_addr & 0xFE) != (dev_addr1 & 0xFE)) {
|
||||
|
|
|
@ -45,10 +45,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef VIACUDA_H
|
||||
#define VIACUDA_H
|
||||
|
||||
#include "hwcomponent.h"
|
||||
#include "nvram.h"
|
||||
#include "adb.h"
|
||||
#include "hwcomponent.h"
|
||||
#include "i2c.h"
|
||||
#include "nvram.h"
|
||||
|
||||
/** VIA register offsets. */
|
||||
enum {
|
||||
|
@ -107,8 +107,7 @@ enum {
|
|||
};
|
||||
|
||||
|
||||
class ViaCuda : public HWComponent, public I2CBus
|
||||
{
|
||||
class ViaCuda : public HWComponent, public I2CBus {
|
||||
public:
|
||||
ViaCuda();
|
||||
~ViaCuda();
|
||||
|
@ -150,7 +149,7 @@ private:
|
|||
void assert_sr_int();
|
||||
void write(uint8_t new_state);
|
||||
void response_header(uint32_t pkt_type, uint32_t pkt_flag);
|
||||
//void cuda_response_packet();
|
||||
// void cuda_response_packet();
|
||||
void error_response(uint32_t error);
|
||||
void process_packet();
|
||||
void process_adb_command(uint8_t cmd_byte, int data_count);
|
||||
|
@ -162,8 +161,8 @@ private:
|
|||
|
||||
/* I2C related methods */
|
||||
void i2c_simple_transaction(uint8_t dev_addr, const uint8_t* in_buf, int in_bytes);
|
||||
void i2c_comb_transaction(uint8_t dev_addr, uint8_t sub_addr, uint8_t dev_addr1,
|
||||
const uint8_t* in_buf, int in_bytes);
|
||||
void i2c_comb_transaction(
|
||||
uint8_t dev_addr, uint8_t sub_addr, uint8_t dev_addr1, const uint8_t* in_buf, int in_bytes);
|
||||
};
|
||||
|
||||
#endif /* VIACUDA_H */
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
#include "machinebase.h"
|
||||
#include "devices/hwcomponent.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include "machinebase.h"
|
||||
#include "devices/hwcomponent.h"
|
||||
|
||||
std::unique_ptr<MachineBase> gMachineObj = 0;
|
||||
|
||||
|
||||
MachineBase::MachineBase(std::string name)
|
||||
{
|
||||
MachineBase::MachineBase(std::string name) {
|
||||
this->name = name;
|
||||
|
||||
/* initialize internal maps */
|
||||
|
@ -17,9 +16,8 @@ MachineBase::MachineBase(std::string name)
|
|||
this->aliases.clear();
|
||||
}
|
||||
|
||||
MachineBase::~MachineBase()
|
||||
{
|
||||
for(auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) {
|
||||
MachineBase::~MachineBase() {
|
||||
for (auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) {
|
||||
delete it->second;
|
||||
}
|
||||
this->comp_map.clear();
|
||||
|
@ -27,8 +25,7 @@ MachineBase::~MachineBase()
|
|||
this->subdev_map.clear();
|
||||
}
|
||||
|
||||
bool MachineBase::add_component(std::string name, HWComponent *dev_obj)
|
||||
{
|
||||
bool MachineBase::add_component(std::string name, HWComponent* dev_obj) {
|
||||
if (this->comp_map.count(name)) {
|
||||
LOG_F(ERROR, "Component %s already exists!", name.c_str());
|
||||
return false;
|
||||
|
@ -39,8 +36,7 @@ bool MachineBase::add_component(std::string name, HWComponent *dev_obj)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MachineBase::add_subdevice(std::string name, HWComponent *dev_obj)
|
||||
{
|
||||
bool MachineBase::add_subdevice(std::string name, HWComponent* dev_obj) {
|
||||
if (this->subdev_map.count(name)) {
|
||||
LOG_F(ERROR, "Subdevice %s already exists!", name.c_str());
|
||||
return false;
|
||||
|
@ -51,13 +47,11 @@ bool MachineBase::add_subdevice(std::string name, HWComponent *dev_obj)
|
|||
return true;
|
||||
}
|
||||
|
||||
void MachineBase::add_alias(std::string name, std::string alias)
|
||||
{
|
||||
void MachineBase::add_alias(std::string name, std::string alias) {
|
||||
this->aliases[alias] = name;
|
||||
}
|
||||
|
||||
HWComponent *MachineBase::get_comp_by_name(std::string name)
|
||||
{
|
||||
HWComponent* MachineBase::get_comp_by_name(std::string name) {
|
||||
if (this->aliases.count(name)) {
|
||||
name = this->aliases[name];
|
||||
}
|
||||
|
@ -73,12 +67,11 @@ HWComponent *MachineBase::get_comp_by_name(std::string name)
|
|||
}
|
||||
}
|
||||
|
||||
HWComponent *MachineBase::get_comp_by_type(HWCompType type)
|
||||
{
|
||||
HWComponent* MachineBase::get_comp_by_type(HWCompType type) {
|
||||
std::string comp_name;
|
||||
bool found = false;
|
||||
|
||||
for(auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) {
|
||||
for (auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) {
|
||||
if (it->second->supports_type(type)) {
|
||||
comp_name = it->first;
|
||||
found = true;
|
||||
|
@ -90,7 +83,7 @@ HWComponent *MachineBase::get_comp_by_type(HWCompType type)
|
|||
return this->get_comp_by_name(comp_name);
|
||||
}
|
||||
|
||||
for(auto it = this->subdev_map.begin(); it != this->subdev_map.end(); it++) {
|
||||
for (auto it = this->subdev_map.begin(); it != this->subdev_map.end(); it++) {
|
||||
if (it->second->supports_type(type)) {
|
||||
comp_name = it->first;
|
||||
found = true;
|
||||
|
|
|
@ -27,27 +27,26 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef MACHINE_BASE_H
|
||||
#define MACHINE_BASE_H
|
||||
|
||||
#include "devices/hwcomponent.h"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "devices/hwcomponent.h"
|
||||
|
||||
class MachineBase
|
||||
{
|
||||
class MachineBase {
|
||||
public:
|
||||
MachineBase(std::string name);
|
||||
~MachineBase();
|
||||
|
||||
bool add_component(std::string name, HWComponent *dev_obj);
|
||||
bool add_subdevice(std::string name, HWComponent *dev_obj);
|
||||
bool add_component(std::string name, HWComponent* dev_obj);
|
||||
bool add_subdevice(std::string name, HWComponent* dev_obj);
|
||||
void add_alias(std::string name, std::string alias);
|
||||
HWComponent *get_comp_by_name(std::string name);
|
||||
HWComponent *get_comp_by_type(HWCompType type);
|
||||
HWComponent* get_comp_by_name(std::string name);
|
||||
HWComponent* get_comp_by_type(HWCompType type);
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
std::map<std::string, HWComponent *>comp_map;
|
||||
std::map<std::string, HWComponent *>subdev_map;
|
||||
std::map<std::string, HWComponent*> comp_map;
|
||||
std::map<std::string, HWComponent*> subdev_map;
|
||||
std::map<std::string, std::string> aliases;
|
||||
};
|
||||
|
||||
|
|
|
@ -24,15 +24,15 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
Author: Max Poliakovski
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include "memreadwrite.h"
|
||||
#include "machinefactory.h"
|
||||
#include "devices/memctrlbase.h"
|
||||
#include "memreadwrite.h"
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -43,27 +43,26 @@ using namespace std;
|
|||
or 0x30C064 (Nubus Macs).
|
||||
*/
|
||||
static const map<uint32_t, string> rom_identity = {
|
||||
{0x416C6368, "Performa 6400"}, //Alchemy
|
||||
{0x416C6368, "Performa 6400"}, // Alchemy
|
||||
//{"Come", "PowerBook 2400"}, //Comet
|
||||
{0x436F7264, "Power Mac 5200/6200 series"}, //Cordyceps
|
||||
{0x47617A65, "Power Mac 6500"}, //Gazelle
|
||||
{0x476F7373, "Power Mac G3 Beige"}, //Gossamer
|
||||
{0x436F7264, "Power Mac 5200/6200 series"}, // Cordyceps
|
||||
{0x47617A65, "Power Mac 6500"}, // Gazelle
|
||||
{0x476F7373, "Power Mac G3 Beige"}, // Gossamer
|
||||
{0x47525820, "PowerBook G3 Wallstreet"},
|
||||
//{"Hoop", "PowerBook 3400"}, //Hooper
|
||||
{0x50425820, "PowerBook Pre-G3"},
|
||||
{0x50444D20, "Nubus Power Mac or WGS"}, //Piltdown Man (6100/7100/8100)
|
||||
{0x50697020, "Bandai Pippin"}, //Pippin
|
||||
{0x50444D20, "Nubus Power Mac or WGS"}, // Piltdown Man (6100/7100/8100)
|
||||
{0x50697020, "Bandai Pippin"}, // Pippin
|
||||
//{"Powe", "Generic Power Mac"}, //PowerMac?
|
||||
//{"Spar", "20th Anniversay Mac"}, //Spartacus
|
||||
{0x544E5420, "Power Mac 7xxxx/8xxx series"}, //Trinitrotoluene :-)
|
||||
{0x5A616E7A, "Power Mac 4400/7220"}, //Zanzibar
|
||||
{0x544E5420, "Power Mac 7xxxx/8xxx series"}, // Trinitrotoluene :-)
|
||||
{0x5A616E7A, "Power Mac 4400/7220"}, // Zanzibar
|
||||
//{"????", "A clone, perhaps?"} //N/A (Placeholder ID)
|
||||
};
|
||||
|
||||
|
||||
int create_machine_for_id(uint32_t id)
|
||||
{
|
||||
switch(id) {
|
||||
int create_machine_for_id(uint32_t id) {
|
||||
switch (id) {
|
||||
case 0x476F7373:
|
||||
create_gossamer();
|
||||
break;
|
||||
|
@ -76,28 +75,26 @@ int create_machine_for_id(uint32_t id)
|
|||
|
||||
|
||||
/* Read ROM file content and transfer it to the dedicated ROM region */
|
||||
void load_rom(ifstream& rom_file, uint32_t file_size)
|
||||
{
|
||||
unsigned char *sysrom_mem = new unsigned char[file_size];
|
||||
void load_rom(ifstream& rom_file, uint32_t file_size) {
|
||||
unsigned char* sysrom_mem = new unsigned char[file_size];
|
||||
|
||||
rom_file.seekg(0, ios::beg);
|
||||
rom_file.read((char *)sysrom_mem, file_size);
|
||||
rom_file.read((char*)sysrom_mem, file_size);
|
||||
|
||||
MemCtrlBase *mem_ctrl = dynamic_cast<MemCtrlBase *>
|
||||
(gMachineObj->get_comp_by_type(HWCompType::MEM_CTRL));
|
||||
MemCtrlBase* mem_ctrl = dynamic_cast<MemCtrlBase*>(
|
||||
gMachineObj->get_comp_by_type(HWCompType::MEM_CTRL));
|
||||
|
||||
mem_ctrl->set_data(0xFFC00000, sysrom_mem, file_size);
|
||||
delete[] sysrom_mem;
|
||||
}
|
||||
|
||||
|
||||
int create_machine_for_rom(const char* rom_filepath)
|
||||
{
|
||||
int create_machine_for_rom(const char* rom_filepath) {
|
||||
ifstream rom_file;
|
||||
uint32_t file_size, config_info_offset, rom_id;
|
||||
char rom_id_str[17];
|
||||
|
||||
rom_file.open(rom_filepath, ios::in|ios::binary);
|
||||
rom_file.open(rom_filepath, ios::in | ios::binary);
|
||||
if (rom_file.fail()) {
|
||||
LOG_F(ERROR, "Cound not open the specified ROM file.");
|
||||
rom_file.close();
|
||||
|
@ -108,7 +105,7 @@ int create_machine_for_rom(const char* rom_filepath)
|
|||
file_size = rom_file.tellg();
|
||||
rom_file.seekg(0, rom_file.beg);
|
||||
|
||||
if (file_size != 0x400000UL){
|
||||
if (file_size != 0x400000UL) {
|
||||
LOG_F(ERROR, "Unxpected ROM File size. Expected size is 4 megabytes.");
|
||||
rom_file.close();
|
||||
return -1;
|
||||
|
@ -117,7 +114,7 @@ int create_machine_for_rom(const char* rom_filepath)
|
|||
/* read config info offset from file */
|
||||
config_info_offset = 0;
|
||||
rom_file.seekg(0x300080, ios::beg);
|
||||
rom_file.read((char *)&config_info_offset, 4);
|
||||
rom_file.read((char*)&config_info_offset, 4);
|
||||
config_info_offset = READ_DWORD_BE_A(&config_info_offset);
|
||||
|
||||
/* rewind to ConfigInfo.BootstrapVersion field */
|
||||
|
@ -135,8 +132,7 @@ int create_machine_for_rom(const char* rom_filepath)
|
|||
}
|
||||
|
||||
/* convert BootstrapVersion string to ROM ID */
|
||||
rom_id = (rom_id_str[5] << 24) | (rom_id_str[6] << 16) |
|
||||
(rom_id_str[7] << 8) | rom_id_str[8];
|
||||
rom_id = (rom_id_str[5] << 24) | (rom_id_str[6] << 16) | (rom_id_str[7] << 8) | rom_id_str[8];
|
||||
|
||||
LOG_F(INFO, "The machine is identified as... %s\n", rom_identity.at(rom_id).c_str());
|
||||
|
||||
|
|
|
@ -24,33 +24,31 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
Author: Max Poliakovski
|
||||
*/
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include "machinebase.h"
|
||||
#include "cpu/ppc/ppcemu.h"
|
||||
#include "devices/mpc106.h"
|
||||
#include "devices/atirage.h"
|
||||
#include "devices/machineid.h"
|
||||
#include "devices/macio.h"
|
||||
#include "devices/viacuda.h"
|
||||
#include "devices/mpc106.h"
|
||||
#include "devices/spdram.h"
|
||||
#include "devices/atirage.h"
|
||||
#include "devices/viacuda.h"
|
||||
#include "machinebase.h"
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
static void setup_ram_slot(std::string name, int i2c_addr, int capacity_megs)
|
||||
{
|
||||
static void setup_ram_slot(std::string name, int i2c_addr, int capacity_megs) {
|
||||
if (!capacity_megs)
|
||||
return;
|
||||
|
||||
gMachineObj->add_component(name, new SpdSdram168(i2c_addr));
|
||||
SpdSdram168 *ram_dimm = dynamic_cast<SpdSdram168 *>(gMachineObj->get_comp_by_name(name));
|
||||
SpdSdram168* ram_dimm = dynamic_cast<SpdSdram168*>(gMachineObj->get_comp_by_name(name));
|
||||
ram_dimm->set_capacity(capacity_megs);
|
||||
|
||||
/* register RAM DIMM with the I2C bus */
|
||||
I2CBus *i2c_bus = dynamic_cast<I2CBus *>(gMachineObj->get_comp_by_type(HWCompType::I2C_HOST));
|
||||
I2CBus* i2c_bus = dynamic_cast<I2CBus*>(gMachineObj->get_comp_by_type(HWCompType::I2C_HOST));
|
||||
i2c_bus->register_device(i2c_addr, ram_dimm);
|
||||
}
|
||||
|
||||
|
||||
int create_gossamer()
|
||||
{
|
||||
int create_gossamer() {
|
||||
if (gMachineObj) {
|
||||
LOG_F(ERROR, "Global machine object not empty!");
|
||||
return -1;
|
||||
|
@ -66,17 +64,17 @@ int create_gossamer()
|
|||
gMachineObj->add_alias("Grackle", "PCI_Host");
|
||||
|
||||
/* get raw pointer to MPC106 object */
|
||||
MPC106 *grackle_obj = dynamic_cast<MPC106 *>(gMachineObj->get_comp_by_name("Grackle"));
|
||||
MPC106* grackle_obj = dynamic_cast<MPC106*>(gMachineObj->get_comp_by_name("Grackle"));
|
||||
|
||||
/* add the machine ID register */
|
||||
gMachineObj->add_component("MachineID", new GossamerID(0x3d8c));
|
||||
grackle_obj->add_mmio_region(0xFF000004, 4096,
|
||||
dynamic_cast<MMIODevice *>(gMachineObj->get_comp_by_name("MachineID")));
|
||||
grackle_obj->add_mmio_region(
|
||||
0xFF000004, 4096, dynamic_cast<MMIODevice*>(gMachineObj->get_comp_by_name("MachineID")));
|
||||
|
||||
/* add the Heathrow I/O controller */
|
||||
gMachineObj->add_component("Heathrow", new HeathrowIC);
|
||||
grackle_obj->pci_register_device(16,
|
||||
dynamic_cast<PCIDevice *>(gMachineObj->get_comp_by_name("Heathrow")));
|
||||
grackle_obj->pci_register_device(
|
||||
16, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("Heathrow")));
|
||||
|
||||
/* allocate ROM region */
|
||||
if (!grackle_obj->add_rom_region(0xFFC00000, 0x400000)) {
|
||||
|
@ -91,8 +89,8 @@ int create_gossamer()
|
|||
|
||||
/* register ATI 3D Rage Pro video card with the PCI host bridge */
|
||||
gMachineObj->add_component("ATIRage", new ATIRage(ATI_RAGE_PRO_DEV_ID));
|
||||
grackle_obj->pci_register_device(18,
|
||||
dynamic_cast<PCIDevice *>(gMachineObj->get_comp_by_name("ATIRage")));
|
||||
grackle_obj->pci_register_device(
|
||||
18, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("ATIRage")));
|
||||
|
||||
/* Init virtual CPU and request MPC750 CPU aka G3 */
|
||||
ppc_cpu_init(grackle_obj, PPC_VER::MPC750);
|
||||
|
|
66
main.cpp
66
main.cpp
|
@ -19,26 +19,24 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//The main runfile - main.cpp
|
||||
//This is where the magic begins
|
||||
// The main runfile - main.cpp
|
||||
// This is where the magic begins
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
#include <cinttypes>
|
||||
#include <stdio.h>
|
||||
#include "ppcemu.h"
|
||||
#include "debugger/debugger.h"
|
||||
#include "machines/machinefactory.h"
|
||||
#include "ppcemu.h"
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
#include <thirdparty/SDL2/include/SDL.h>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::cout << "DingusPPC - Prototype 5bf4 (7/14/2019) " << endl;
|
||||
std::cout << "Written by divingkatae, (c) 2019. " << endl;
|
||||
std::cout << "This is not intended for general use. " << endl;
|
||||
|
@ -48,19 +46,17 @@ int main(int argc, char **argv)
|
|||
string checker = argv[1];
|
||||
cout << checker << endl;
|
||||
|
||||
if ((checker == "1") || (checker == "realtime") || \
|
||||
(checker == "-realtime") || (checker == "/realtime")) {
|
||||
if ((checker == "1") || (checker == "realtime") || (checker == "-realtime") ||
|
||||
(checker == "/realtime")) {
|
||||
loguru::g_stderr_verbosity = loguru::Verbosity_OFF;
|
||||
loguru::g_preamble_date = false;
|
||||
loguru::g_preamble_time = false;
|
||||
loguru::g_preamble_thread = false;
|
||||
loguru::init(argc, argv);
|
||||
loguru::add_file("dingusppc.log", loguru::Append, 0);
|
||||
//Replace the above line with this for maximum debugging detail:
|
||||
//loguru::add_file("dingusppc.log", loguru::Append, loguru::Verbosity_MAX);
|
||||
}
|
||||
else if ((checker == "debugger") || (checker == "/debugger") ||
|
||||
(checker == "-debugger")) {
|
||||
// Replace the above line with this for maximum debugging detail:
|
||||
// loguru::add_file("dingusppc.log", loguru::Append, loguru::Verbosity_MAX);
|
||||
} else if ((checker == "debugger") || (checker == "/debugger") || (checker == "-debugger")) {
|
||||
loguru::g_stderr_verbosity = 0;
|
||||
loguru::g_preamble_date = false;
|
||||
loguru::g_preamble_time = false;
|
||||
|
@ -87,26 +83,20 @@ int main(int argc, char **argv)
|
|||
config_output.write("video_card=0x4750\n", 19);
|
||||
|
||||
config_output.close();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
while (std::getline(config_input, line)) {
|
||||
sin.str(line.substr(line.find("=") + 1));
|
||||
if (line.find("rompath") != std::string::npos) {
|
||||
sin >> rom_file;
|
||||
}
|
||||
else if (line.find("diskpath") != std::string::npos) {
|
||||
} else if (line.find("diskpath") != std::string::npos) {
|
||||
sin >> disk_file;
|
||||
}
|
||||
else if (line.find("ramsize") != std::string::npos) {
|
||||
} else if (line.find("ramsize") != std::string::npos) {
|
||||
sin >> ram_size;
|
||||
}
|
||||
else if (line.find("machine_gestalt") != std::string::npos) {
|
||||
} else if (line.find("machine_gestalt") != std::string::npos) {
|
||||
sin >> machine_gestalt;
|
||||
}
|
||||
else if (line.find("video_vendor") != std::string::npos) {
|
||||
} else if (line.find("video_vendor") != std::string::npos) {
|
||||
sin >> video_card_vendor;
|
||||
}
|
||||
else if (line.find("video_card") != std::string::npos) {
|
||||
} else if (line.find("video_card") != std::string::npos) {
|
||||
sin >> video_card_id;
|
||||
}
|
||||
sin.clear();
|
||||
|
@ -117,20 +107,18 @@ int main(int argc, char **argv)
|
|||
goto bail;
|
||||
}
|
||||
|
||||
if (SDL_Init(SDL_INIT_AUDIO)){
|
||||
if (SDL_Init(SDL_INIT_AUDIO)) {
|
||||
LOG_F(ERROR, "SDL_Init error: %s", SDL_GetError());
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if ((checker == "1") || (checker == "realtime") || \
|
||||
(checker == "-realtime") || (checker == "/realtime")) {
|
||||
if ((checker == "1") || (checker == "realtime") || (checker == "-realtime") ||
|
||||
(checker == "/realtime")) {
|
||||
ppc_exec();
|
||||
} else if ((checker == "debugger") || (checker == "/debugger") ||
|
||||
(checker == "-debugger")) {
|
||||
} else if ((checker == "debugger") || (checker == "/debugger") || (checker == "-debugger")) {
|
||||
enter_debugger();
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
std::cout << " " << endl;
|
||||
std::cout << "Please enter one of the following commands when " << endl;
|
||||
std::cout << "booting up DingusPPC... " << endl;
|
||||
|
|
|
@ -5,102 +5,98 @@
|
|||
#ifndef MEM_READ_WRITE_H
|
||||
#define MEM_READ_WRITE_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include "endianswap.h"
|
||||
#include <cinttypes>
|
||||
|
||||
/* read an aligned big-endian WORD (16bit) */
|
||||
#define READ_WORD_BE_A(addr) (BYTESWAP_16(*((uint16_t *)((addr)))))
|
||||
#define READ_WORD_BE_A(addr) (BYTESWAP_16(*((uint16_t*)((addr)))))
|
||||
|
||||
/* read an aligned big-endian DWORD (32bit) */
|
||||
#define READ_DWORD_BE_A(addr) (BYTESWAP_32(*((uint32_t *)((addr)))))
|
||||
#define READ_DWORD_BE_A(addr) (BYTESWAP_32(*((uint32_t*)((addr)))))
|
||||
|
||||
/* read an aligned big-endian QWORD (64bit) */
|
||||
#define READ_QWORD_BE_A(addr) (BYTESWAP_64(*((uint64_t *)((addr)))))
|
||||
#define READ_QWORD_BE_A(addr) (BYTESWAP_64(*((uint64_t*)((addr)))))
|
||||
|
||||
/* read an aligned little-endian WORD (16bit) */
|
||||
#define READ_WORD_LE_A(addr) (*(uint16_t *)((addr)))
|
||||
#define READ_WORD_LE_A(addr) (*(uint16_t*)((addr)))
|
||||
|
||||
/* read an aligned little-endian DWORD (32bit) */
|
||||
#define READ_DWORD_LE_A(addr) (*(uint32_t *)((addr)))
|
||||
#define READ_DWORD_LE_A(addr) (*(uint32_t*)((addr)))
|
||||
|
||||
/* read an aligned little-endian QWORD (64bit) */
|
||||
#define READ_QWORD_LE_A(addr) (*(uint64_t *)((addr)))
|
||||
#define READ_QWORD_LE_A(addr) (*(uint64_t*)((addr)))
|
||||
|
||||
/* read an unaligned big-endian WORD (16bit) */
|
||||
#define READ_WORD_BE_U(addr) (((addr)[0] << 8) | (addr)[1])
|
||||
|
||||
/* read an unaligned big-endian DWORD (32bit) */
|
||||
#define READ_DWORD_BE_U(addr) (((addr)[0] << 24) | ((addr)[1] << 16) | \
|
||||
((addr)[2] << 8) | (addr)[3])
|
||||
#define READ_DWORD_BE_U(addr) (((addr)[0] << 24) | ((addr)[1] << 16) | ((addr)[2] << 8) | (addr)[3])
|
||||
|
||||
/* read an unaligned big-endian QWORD (32bit) */
|
||||
#define READ_QWORD_BE_U(addr) (((addr)[0] << 56) | ((addr)[1] << 48) | \
|
||||
((addr)[2] << 40) | ((addr)[3] << 32) | \
|
||||
((addr)[4] << 24) | ((addr)[5] << 16) | \
|
||||
((addr)[6] << 8) | (addr)[7])
|
||||
#define READ_QWORD_BE_U(addr) \
|
||||
(((addr)[0] << 56) | ((addr)[1] << 48) | ((addr)[2] << 40) | ((addr)[3] << 32) | \
|
||||
((addr)[4] << 24) | ((addr)[5] << 16) | ((addr)[6] << 8) | (addr)[7])
|
||||
|
||||
/* read an unaligned little-endian WORD (16bit) */
|
||||
#define READ_WORD_LE_U(addr) (((addr)[1] << 8) | (addr)[0])
|
||||
|
||||
/* read an unaligned little-endian DWORD (32bit) */
|
||||
#define READ_DWORD_LE_U(addr) (((addr)[3] << 24) | ((addr)[2] << 16) | \
|
||||
((addr)[1] << 8) | (addr)[0])
|
||||
#define READ_DWORD_LE_U(addr) (((addr)[3] << 24) | ((addr)[2] << 16) | ((addr)[1] << 8) | (addr)[0])
|
||||
|
||||
/* read an unaligned little-endian DWORD (32bit) */
|
||||
#define READ_QWORD_LE_U(addr) (((addr)[7] << 56) | ((addr)[6] << 48) | \
|
||||
((addr)[5] << 40) | ((addr)[4] << 32) | \
|
||||
((addr)[3] << 24) | ((addr)[2] << 16) | \
|
||||
((addr)[1] << 8) | (addr)[0])
|
||||
#define READ_QWORD_LE_U(addr) \
|
||||
(((addr)[7] << 56) | ((addr)[6] << 48) | ((addr)[5] << 40) | ((addr)[4] << 32) | \
|
||||
((addr)[3] << 24) | ((addr)[2] << 16) | ((addr)[1] << 8) | (addr)[0])
|
||||
|
||||
|
||||
/* write an aligned big-endian WORD (16bit) */
|
||||
#define WRITE_WORD_BE_A(addr,val) (*((uint16_t *)((addr))) = BYTESWAP_16(val))
|
||||
#define WRITE_WORD_BE_A(addr, val) (*((uint16_t*)((addr))) = BYTESWAP_16(val))
|
||||
|
||||
/* write an aligned big-endian DWORD (32bit) */
|
||||
#define WRITE_DWORD_BE_A(addr,val) (*((uint32_t *)((addr))) = BYTESWAP_32(val))
|
||||
#define WRITE_DWORD_BE_A(addr, val) (*((uint32_t*)((addr))) = BYTESWAP_32(val))
|
||||
|
||||
/* write an aligned big-endian QWORD (64bit) */
|
||||
#define WRITE_QWORD_BE_A(addr,val) (*((uint64_t *)((addr))) = BYTESWAP_64(val))
|
||||
#define WRITE_QWORD_BE_A(addr, val) (*((uint64_t*)((addr))) = BYTESWAP_64(val))
|
||||
|
||||
/* write an unaligned big-endian WORD (16bit) */
|
||||
#define WRITE_WORD_BE_U(addr, val) \
|
||||
do { \
|
||||
do { \
|
||||
(addr)[0] = ((val) >> 8) & 0xFF; \
|
||||
(addr)[1] = (val) & 0xFF; \
|
||||
} while(0)
|
||||
(addr)[1] = (val)&0xFF; \
|
||||
} while (0)
|
||||
|
||||
/* write an unaligned big-endian DWORD (32bit) */
|
||||
#define WRITE_DWORD_BE_U(addr, val) \
|
||||
do { \
|
||||
do { \
|
||||
(addr)[0] = ((val) >> 24) & 0xFF; \
|
||||
(addr)[1] = ((val) >> 16) & 0xFF; \
|
||||
(addr)[2] = ((val) >> 8) & 0xFF; \
|
||||
(addr)[3] = (val) & 0xFF; \
|
||||
} while(0)
|
||||
(addr)[3] = (val)&0xFF; \
|
||||
} while (0)
|
||||
|
||||
/* write an aligned little-endian WORD (16bit) */
|
||||
#define WRITE_WORD_LE_A(addr,val) (*((uint16_t *)((addr))) = (val))
|
||||
#define WRITE_WORD_LE_A(addr, val) (*((uint16_t*)((addr))) = (val))
|
||||
|
||||
/* write an aligned little-endian DWORD (32bit) */
|
||||
#define WRITE_DWORD_LE_A(addr,val) (*((uint32_t *)((addr))) = (val))
|
||||
#define WRITE_DWORD_LE_A(addr, val) (*((uint32_t*)((addr))) = (val))
|
||||
|
||||
/* write an aligned little-endian QWORD (64bit) */
|
||||
#define WRITE_QWORD_LE_A(addr,val) (*((uint64_t *)((addr))) = (val))
|
||||
#define WRITE_QWORD_LE_A(addr, val) (*((uint64_t*)((addr))) = (val))
|
||||
|
||||
/* write an unaligned little-endian WORD (16bit) */
|
||||
#define WRITE_WORD_LE_U(addr, val) \
|
||||
do { \
|
||||
(addr)[0] = (val) & 0xFF; \
|
||||
do { \
|
||||
(addr)[0] = (val)&0xFF; \
|
||||
(addr)[1] = ((val) >> 8) & 0xFF; \
|
||||
} while(0)
|
||||
} while (0)
|
||||
|
||||
/* write an unaligned little-endian DWORD (32bit) */
|
||||
#define WRITE_DWORD_LE_U(addr, val) \
|
||||
do { \
|
||||
(addr)[0] = (val) & 0xFF; \
|
||||
do { \
|
||||
(addr)[0] = (val)&0xFF; \
|
||||
(addr)[1] = ((val) >> 8) & 0xFF; \
|
||||
(addr)[2] = ((val) >> 16) & 0xFF; \
|
||||
(addr)[3] = ((val) >> 24) & 0xFF; \
|
||||
} while(0)
|
||||
} while (0)
|
||||
|
||||
#endif /* MEM_READ_WRITE_H */
|
||||
|
|
Loading…
Reference in New Issue