clang-format everything

This commit is contained in:
Waqar Ahmed 2020-05-12 23:55:45 +05:00
parent a5c63c1b09
commit 0ab9380be3
49 changed files with 2718 additions and 3104 deletions

78
.clang-format Normal file
View File

@ -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

View File

@ -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

View File

@ -22,11 +22,11 @@ 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
//#define EXHAUSTIVE_DEBUG 1
@ -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 {
@ -293,10 +290,8 @@ 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
extern MemCtrlBase* mem_ctrl_instance;

View File

@ -21,16 +21,14 @@ 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
exceptions_performed++;
@ -105,8 +103,7 @@ jmp_buf exc_env; /* Global exception environment. */
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,9 +113,7 @@ 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) {

View File

@ -19,16 +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 <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"
@ -60,371 +60,344 @@ clock_t clock_test_begin; //Used to make sure the TBR does not increment so quic
/** 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);
}
@ -533,20 +505,17 @@ void ppc_main_opcode() {
}
/** 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;
}
}
@ -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 &reg_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 &reg_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 &reg_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 &reg_name)
{
uint64_t get_reg(string& reg_name) {
return reg_op(reg_name, 0, false);
}
void set_reg(string &reg_name, uint64_t val)
{
void set_reg(string& reg_name, uint64_t val) {
reg_op(reg_name, val, true);
}

View File

@ -21,18 +21,18 @@ 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
uint64_t ppc_result64_a;
@ -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) {
}
}
@ -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() {
@ -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);
}
}
@ -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,7 +1288,8 @@ 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
@ -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;
}

View File

@ -21,9 +21,9 @@ 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() {
printf("Hello. There's no GameCube emulation...yet. Goodbye.");

View File

@ -28,17 +28,17 @@ 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);
@ -68,17 +68,13 @@ 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); \
} \
@ -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);
@ -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,8 +370,7 @@ 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) {
@ -420,8 +390,7 @@ 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);
@ -432,8 +401,7 @@ void mem_write_byte(uint32_t addr, uint8_t value)
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,8 +427,7 @@ 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!
@ -475,8 +441,7 @@ 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);
@ -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,8 +510,7 @@ 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) {
@ -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;
@ -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;
}

View File

@ -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

View File

@ -21,17 +21,17 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
// General opcodes for the processor - ppcopcodes.cpp
#include <thirdparty/loguru/loguru.hpp>
#include <iostream>
#include <cstring>
#include <cinttypes>
#include <array>
#include <thread>
#include <stdio.h>
#include <stdlib.h>
#include <stdexcept>
#include "ppcemu.h"
#include "ppcmmu.h"
#include <array>
#include <cinttypes>
#include <cstring>
#include <iostream>
#include <stdexcept>
#include <stdio.h>
#include <stdlib.h>
#include <thirdparty/loguru/loguru.hpp>
#include <thread>
uint32_t crf_d;
uint32_t crf_s;
@ -151,12 +151,10 @@ void ppc_changecrf0(uint32_t set_result) {
if (set_result == 0) {
ppc_state.cr |= 0x20000000UL;
}
else {
} else {
if (set_result & 0x80000000) {
ppc_state.cr |= 0x80000000UL;
}
else {
} else {
ppc_state.cr |= 0x40000000UL;
}
}
@ -169,8 +167,7 @@ void ppc_changecrf0(uint32_t set_result) {
inline void ppc_carry(uint32_t a, uint32_t b) {
if (b < a) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
}
@ -178,8 +175,7 @@ inline void ppc_carry(uint32_t a, uint32_t b) {
inline void ppc_carry_sub(uint32_t a, uint32_t b) {
if (b >= a) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
}
@ -189,16 +185,16 @@ inline void ppc_carry_sub(uint32_t a, uint32_t b) {
inline void ppc_setsoov(uint32_t a, uint32_t b, uint32_t d) {
if ((a ^ b) & (a ^ d) & 0x80000000UL) {
ppc_state.spr[SPR::XER] |= 0xC0000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xBFFFFFFFUL;
}
}
/**
The core functionality of this PPC emulation is within all of these void functions.
This is where the opcode tables in the ppcemumain.h come into play - reducing the number of comparisons needed.
This means loads of functions, but less CPU cycles needed to determine the function (theoretically).
This is where the opcode tables in the ppcemumain.h come into play - reducing the number of
comparisons needed. This means loads of functions, but less CPU cycles needed to determine the
function (theoretically).
**/
void ppc_addi() {
@ -295,8 +291,7 @@ void ppc_adde() {
ppc_result_d = ppc_result_a + ppc_result_b + xer_ca;
if ((ppc_result_d < ppc_result_a) || (xer_ca && (ppc_result_d == ppc_result_a))) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
ppc_store_result_regd();
@ -308,8 +303,7 @@ void ppc_addedot() {
ppc_result_d = ppc_result_a + ppc_result_b + xer_ca;
if ((ppc_result_d < ppc_result_a) || (xer_ca && (ppc_result_d == ppc_result_a))) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
ppc_changecrf0(ppc_result_d);
@ -322,8 +316,7 @@ void ppc_addeo() {
ppc_result_d = ppc_result_a + ppc_result_b + xer_ca;
if ((ppc_result_d < ppc_result_a) || (xer_ca && (ppc_result_d == ppc_result_a))) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
ppc_setsoov(ppc_result_a, ~ppc_result_b, ppc_result_d);
@ -336,8 +329,7 @@ void ppc_addeodot() {
ppc_result_d = ppc_result_a + ppc_result_b + xer_ca;
if ((ppc_result_d < ppc_result_a) || (xer_ca && (ppc_result_d == ppc_result_a))) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
ppc_setsoov(ppc_result_a, ~ppc_result_b, ppc_result_d);
@ -351,8 +343,7 @@ void ppc_addme() {
ppc_result_d = ppc_result_a + xer_ca - 1;
if (((xer_ca - 1) < 0xFFFFFFFFUL) | (ppc_result_d < ppc_result_a)) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
ppc_store_result_regd();
@ -364,8 +355,7 @@ void ppc_addmedot() {
ppc_result_d = ppc_result_a + xer_ca - 1;
if (((xer_ca - 1) < 0xFFFFFFFFUL) | (ppc_result_d < ppc_result_a)) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
ppc_changecrf0(ppc_result_d);
@ -379,8 +369,7 @@ void ppc_addmeo() {
ppc_setsoov(ppc_result_a, 0, ppc_result_d);
if (((xer_ca - 1) < 0xFFFFFFFFUL) | (ppc_result_d < ppc_result_a)) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
ppc_store_result_regd();
@ -394,8 +383,7 @@ void ppc_addmeodot() {
ppc_changecrf0(ppc_result_d);
if (((xer_ca - 1) < 0xFFFFFFFFUL) | (ppc_result_d < ppc_result_a)) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
ppc_store_result_regd();
@ -407,8 +395,7 @@ void ppc_addze() {
ppc_result_d = ppc_result_a + grab_xer;
if (ppc_result_d < ppc_result_a) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
ppc_store_result_regd();
@ -420,8 +407,7 @@ void ppc_addzedot() {
ppc_result_d = ppc_result_a + grab_xer;
if (ppc_result_d < ppc_result_a) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
ppc_changecrf0(ppc_result_d);
@ -435,8 +421,7 @@ void ppc_addzeo() {
ppc_setsoov(ppc_result_a, 0xFFFFFFFFUL, ppc_result_d);
if (ppc_result_d < ppc_result_a) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
ppc_store_result_regd();
@ -449,8 +434,7 @@ void ppc_addzeodot() {
ppc_setsoov(ppc_result_a, 0xFFFFFFFFUL, ppc_result_d);
if (ppc_result_d < ppc_result_a) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
ppc_changecrf0(ppc_result_d);
@ -896,8 +880,7 @@ void ppc_mullwo() {
int64_t product = (int64_t)(int32_t)ppc_result_a * (int64_t)(int32_t)ppc_result_b;
if (product != (int64_t)(int32_t)product) {
ppc_state.spr[SPR::XER] |= 0xC0000000;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xBFFFFFFFUL;
}
ppc_result_d = (uint32_t)product;
@ -909,8 +892,7 @@ void ppc_mullwodot() {
int64_t product = (int64_t)(int32_t)ppc_result_a * (int64_t)(int32_t)ppc_result_b;
if (product != (int64_t)(int32_t)product) {
ppc_state.spr[SPR::XER] |= 0xC0000000;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xBFFFFFFFUL;
}
ppc_result_d = (uint32_t)product;
@ -931,11 +913,9 @@ void ppc_divw() {
if (!ppc_result_b) { /* handle the "anything / 0" case */
ppc_result_d = (ppc_result_a & 0x80000000) ? -1 : 0; /* UNDOCUMENTED! */
}
else if (ppc_result_a == 0x80000000UL && ppc_result_b == 0xFFFFFFFFUL) {
} else if (ppc_result_a == 0x80000000UL && ppc_result_b == 0xFFFFFFFFUL) {
ppc_result_d = 0xFFFFFFFF;
}
else { /* normal signed devision */
} else { /* normal signed devision */
ppc_result_d = (int32_t)ppc_result_a / (int32_t)ppc_result_b;
}
@ -947,11 +927,9 @@ void ppc_divwdot() {
if (!ppc_result_b) { /* handle the "anything / 0" case */
ppc_result_d = (ppc_result_a & 0x80000000) ? -1 : 0; /* UNDOCUMENTED! */
}
else if (ppc_result_a == 0x80000000UL && ppc_result_b == 0xFFFFFFFFUL) {
} else if (ppc_result_a == 0x80000000UL && ppc_result_b == 0xFFFFFFFFUL) {
ppc_result_d = 0xFFFFFFFF;
}
else { /* normal signed devision */
} else { /* normal signed devision */
ppc_result_d = (int32_t)ppc_result_a / (int32_t)ppc_result_b;
}
@ -965,12 +943,10 @@ void ppc_divwo() {
if (!ppc_result_b) { /* handle the "anything / 0" case */
ppc_result_d = (ppc_result_a & 0x80000000) ? -1 : 0; /* UNDOCUMENTED! */
ppc_state.spr[SPR::XER] |= 0xC0000000;
}
else if (ppc_result_a == 0x80000000UL && ppc_result_b == 0xFFFFFFFFUL) {
} else if (ppc_result_a == 0x80000000UL && ppc_result_b == 0xFFFFFFFFUL) {
ppc_result_d = 0xFFFFFFFF;
ppc_state.spr[SPR::XER] |= 0xC0000000;
}
else { /* normal signed devision */
} else { /* normal signed devision */
ppc_result_d = (int32_t)ppc_result_a / (int32_t)ppc_result_b;
ppc_state.spr[SPR::XER] &= 0xBFFFFFFFUL;
}
@ -984,12 +960,10 @@ void ppc_divwodot() {
if (!ppc_result_b) { /* handle the "anything / 0" case */
ppc_result_d = (ppc_result_a & 0x80000000) ? -1 : 0; /* UNDOCUMENTED! */
ppc_state.spr[SPR::XER] |= 0xC0000000;
}
else if (ppc_result_a == 0x80000000UL && ppc_result_b == 0xFFFFFFFFUL) {
} else if (ppc_result_a == 0x80000000UL && ppc_result_b == 0xFFFFFFFFUL) {
ppc_result_d = 0xFFFFFFFF;
ppc_state.spr[SPR::XER] |= 0xC0000000;
}
else { /* normal signed devision */
} else { /* normal signed devision */
ppc_result_d = (int32_t)ppc_result_a / (int32_t)ppc_result_b;
ppc_state.spr[SPR::XER] &= 0xBFFFFFFFUL;
}
@ -1003,8 +977,7 @@ void ppc_divwu() {
if (!ppc_result_b) { /* division by zero */
ppc_result_d = 0;
}
else {
} else {
ppc_result_d = ppc_result_a / ppc_result_b;
}
ppc_store_result_regd();
@ -1016,8 +989,7 @@ void ppc_divwudot() {
if (!ppc_result_b) { /* division by zero */
ppc_result_d = 0;
ppc_state.cr |= 0x20000000;
}
else {
} else {
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_changecrf0(ppc_result_d);
}
@ -1030,8 +1002,7 @@ void ppc_divwuo() {
if (!ppc_result_b) { /* division by zero */
ppc_result_d = 0;
ppc_state.spr[SPR::XER] |= 0xC0000000;
}
else {
} else {
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.spr[SPR::XER] &= 0xBFFFFFFFUL;
}
@ -1044,8 +1015,7 @@ void ppc_divwuodot() {
if (!ppc_result_b) { /* division by zero */
ppc_result_d = 0;
ppc_state.spr[SPR::XER] |= 0xC0000000;
}
else {
} else {
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.spr[SPR::XER] &= 0xBFFFFFFFUL;
}
@ -1059,8 +1029,7 @@ void ppc_slw() {
ppc_grab_regssab();
if (ppc_result_b & 0x20) {
ppc_result_a = 0;
}
else {
} else {
ppc_result_a = ppc_result_d << (ppc_result_b & 0x1F);
}
ppc_store_result_rega();
@ -1070,8 +1039,7 @@ void ppc_slwdot() {
ppc_grab_regssab();
if (ppc_result_b & 0x20) {
ppc_result_a = 0;
}
else {
} else {
ppc_result_a = ppc_result_d << (ppc_result_b & 0x1F);
}
ppc_changecrf0(ppc_result_a);
@ -1082,8 +1050,7 @@ void ppc_srw() {
ppc_grab_regssab();
if (ppc_result_b & 0x20) {
ppc_result_a = 0;
}
else {
} else {
ppc_result_a = ppc_result_d >> (ppc_result_b & 0x1F);
}
ppc_store_result_rega();
@ -1093,8 +1060,7 @@ void ppc_srwdot() {
ppc_grab_regssab();
if (ppc_result_b & 0x20) {
ppc_result_a = 0;
}
else {
} else {
ppc_result_a = ppc_result_d >> (ppc_result_b & 0x1F);
}
ppc_changecrf0(ppc_result_a);
@ -1106,15 +1072,13 @@ void ppc_sraw() {
if (ppc_result_b & 0x20) {
ppc_result_a = (int32_t)ppc_result_d >> 31;
ppc_state.spr[SPR::XER] |= (ppc_result_a & 1) << 29;
}
else {
} else {
uint32_t shift = ppc_result_b & 0x1F;
uint32_t mask = (1 << shift) - 1;
ppc_result_a = (int32_t)ppc_result_d >> shift;
if ((ppc_result_d & 0x80000000UL) && (ppc_result_d & mask)) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
}
@ -1126,15 +1090,13 @@ void ppc_srawdot() {
if (ppc_result_b & 0x20) {
ppc_result_a = (int32_t)ppc_result_d >> 31;
ppc_state.spr[SPR::XER] |= (ppc_result_a & 1) << 29;
}
else {
} else {
uint32_t shift = ppc_result_b & 0x1F;
uint32_t mask = (1 << shift) - 1;
ppc_result_a = (int32_t)ppc_result_d >> shift;
if ((ppc_result_d & 0x80000000UL) && (ppc_result_d & mask)) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
}
@ -1149,8 +1111,7 @@ void ppc_srawi() {
ppc_result_a = (int32_t)ppc_result_d >> shift;
if ((ppc_result_d & 0x80000000UL) && (ppc_result_d & mask)) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
ppc_store_result_rega();
@ -1163,8 +1124,7 @@ void ppc_srawidot() {
ppc_result_a = (int32_t)ppc_result_d >> shift;
if ((ppc_result_d & 0x80000000UL) && (ppc_result_d & mask)) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
}
else {
} else {
ppc_state.spr[SPR::XER] &= 0xDFFFFFFFUL;
}
ppc_changecrf0(ppc_result_a);
@ -1172,8 +1132,7 @@ void ppc_srawidot() {
}
/** mask generator for rotate and shift instructions (§ 4.2.1.4 PowerpC PEM) */
static inline uint32_t rot_mask(unsigned rot_mb, unsigned rot_me)
{
static inline uint32_t rot_mask(unsigned rot_mb, unsigned rot_me) {
uint32_t m1 = 0xFFFFFFFFUL >> rot_mb;
uint32_t m2 = 0xFFFFFFFFUL << (31 - rot_me);
return ((rot_mb <= rot_me) ? m2 & m1 : m1 | m2);
@ -1320,8 +1279,7 @@ void ppc_mtspr() {
switch (ref_spr) {
// Mirror the TBRs in the SPR range to the user-mode TBRs.
case 284:
timebase_counter = (timebase_counter & 0xFFFFFFFF00000000ULL) +
ppc_state.gpr[reg_s];
timebase_counter = (timebase_counter & 0xFFFFFFFF00000000ULL) + ppc_state.gpr[reg_s];
break;
case 285:
timebase_counter = (timebase_counter & 0x00000000FFFFFFFFULL) +
@ -1383,21 +1341,24 @@ void ppc_mtcrf() {
void ppc_mcrxr() {
crf_d = (ppc_cur_instruction >> 23) & 7;
crf_d = crf_d << 2;
ppc_state.cr = (ppc_state.cr & ~(0xF0000000UL >> crf_d)) | ((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> crf_d);
ppc_state.cr = (ppc_state.cr & ~(0xF0000000UL >> crf_d)) |
((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> crf_d);
ppc_state.spr[SPR::XER] &= 0x0FFFFFFF;
}
void ppc_extsb() {
ppc_grab_regssa();
ppc_result_d = ppc_result_d & 0xFF;
ppc_result_a = (ppc_result_d < 0x80) ? (ppc_result_d & 0x000000FF) : (0xFFFFFF00UL | (ppc_result_d & 0x000000FF));
ppc_result_a = (ppc_result_d < 0x80) ? (ppc_result_d & 0x000000FF)
: (0xFFFFFF00UL | (ppc_result_d & 0x000000FF));
ppc_store_result_rega();
}
void ppc_extsbdot() {
ppc_grab_regssa();
ppc_result_d = ppc_result_d & 0xFF;
ppc_result_a = (ppc_result_d < 0x80) ? (ppc_result_d & 0x000000FF) : (0xFFFFFF00UL | (ppc_result_d & 0x000000FF));
ppc_result_a = (ppc_result_d < 0x80) ? (ppc_result_d & 0x000000FF)
: (0xFFFFFF00UL | (ppc_result_d & 0x000000FF));
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
@ -1405,14 +1366,16 @@ void ppc_extsbdot() {
void ppc_extsh() {
ppc_grab_regssa();
ppc_result_d = ppc_result_d & 0xFFFF;
ppc_result_a = (ppc_result_d < 0x8000) ? (ppc_result_d & 0x0000FFFF) : (0xFFFF0000UL | (ppc_result_d & 0x0000FFFF));
ppc_result_a = (ppc_result_d < 0x8000) ? (ppc_result_d & 0x0000FFFF)
: (0xFFFF0000UL | (ppc_result_d & 0x0000FFFF));
ppc_store_result_rega();
}
void ppc_extshdot() {
ppc_grab_regssa();
ppc_result_d = ppc_result_d & 0xFFFF;
ppc_result_a = (ppc_result_d < 0x8000) ? (ppc_result_d & 0x0000FFFF) : (0xFFFF0000UL | (ppc_result_d & 0x0000FFFF));
ppc_result_a = (ppc_result_d < 0x8000) ? (ppc_result_d & 0x0000FFFF)
: (0xFFFF0000UL | (ppc_result_d & 0x0000FFFF));
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
@ -1457,8 +1420,7 @@ void ppc_bla() {
bb_kind = BB_end_kind::BB_BRANCH;
}
void ppc_bc()
{
void ppc_bc() {
uint32_t ctr_ok;
uint32_t cnd_ok;
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
@ -1478,8 +1440,7 @@ void ppc_bc()
}
}
void ppc_bca()
{
void ppc_bca() {
uint32_t ctr_ok;
uint32_t cnd_ok;
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
@ -1499,8 +1460,7 @@ void ppc_bca()
}
}
void ppc_bcl()
{
void ppc_bcl() {
uint32_t ctr_ok;
uint32_t cnd_ok;
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
@ -1521,8 +1481,7 @@ void ppc_bcl()
ppc_state.spr[SPR::LR] = ppc_state.pc + 4;
}
void ppc_bcla()
{
void ppc_bcla() {
uint32_t ctr_ok;
uint32_t cnd_ok;
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
@ -1543,12 +1502,12 @@ void ppc_bcla()
ppc_state.spr[SPR::LR] = ppc_state.pc + 4;
}
void ppc_bcctr()
{
void ppc_bcctr() {
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
uint32_t br_bi = (ppc_cur_instruction >> 16) & 31;
uint32_t cnd_ok = (br_bo & 0x10) || (!(ppc_state.cr & (0x80000000UL >> br_bi)) == !(br_bo & 0x08));
uint32_t cnd_ok = (br_bo & 0x10) ||
(!(ppc_state.cr & (0x80000000UL >> br_bi)) == !(br_bo & 0x08));
if (cnd_ok) {
ppc_next_instruction_address = (ppc_state.spr[SPR::CTR] & 0xFFFFFFFCUL);
@ -1557,12 +1516,12 @@ void ppc_bcctr()
}
}
void ppc_bcctrl()
{
void ppc_bcctrl() {
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
uint32_t br_bi = (ppc_cur_instruction >> 16) & 31;
uint32_t cnd_ok = (br_bo & 0x10) || (!(ppc_state.cr & (0x80000000UL >> br_bi)) == !(br_bo & 0x08));
uint32_t cnd_ok = (br_bo & 0x10) ||
(!(ppc_state.cr & (0x80000000UL >> br_bi)) == !(br_bo & 0x08));
if (cnd_ok) {
ppc_next_instruction_address = (ppc_state.spr[SPR::CTR] & 0xFFFFFFFCUL);
@ -1572,8 +1531,7 @@ void ppc_bcctrl()
ppc_state.spr[SPR::LR] = ppc_state.pc + 4;
}
void ppc_bclr()
{
void ppc_bclr() {
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
uint32_t br_bi = (ppc_cur_instruction >> 16) & 31;
uint32_t ctr_ok;
@ -1592,8 +1550,7 @@ void ppc_bclr()
}
}
void ppc_bclrl()
{
void ppc_bclrl() {
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
uint32_t br_bi = (ppc_cur_instruction >> 16) & 31;
uint32_t ctr_ok;
@ -1626,7 +1583,9 @@ void ppc_cmp() {
crf_d = crf_d << 2;
ppc_grab_regssab();
xercon = (ppc_state.spr[SPR::XER] & 0x80000000UL) >> 3;
cmp_c = (((int32_t)ppc_result_a) == ((int32_t)ppc_result_b)) ? 0x20000000UL : (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) ? 0x40000000UL : 0x80000000UL;
cmp_c = (((int32_t)ppc_result_a) == ((int32_t)ppc_result_b))
? 0x20000000UL
: (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) ? 0x40000000UL : 0x80000000UL;
ppc_state.cr = ((ppc_state.cr & ~(0xf0000000UL >> crf_d)) | ((cmp_c + xercon) >> crf_d));
}
@ -1642,7 +1601,9 @@ void ppc_cmpi() {
crf_d = crf_d << 2;
ppc_grab_regsasimm();
xercon = (ppc_state.spr[SPR::XER] & 0x80000000UL) >> 3;
cmp_c = (((int32_t)ppc_result_a) == simm) ? 0x20000000UL : (((int32_t)ppc_result_a) > simm) ? 0x40000000UL : 0x80000000UL;
cmp_c = (((int32_t)ppc_result_a) == simm)
? 0x20000000UL
: (((int32_t)ppc_result_a) > simm) ? 0x40000000UL : 0x80000000UL;
ppc_state.cr = ((ppc_state.cr & ~(0xf0000000UL >> crf_d)) | ((cmp_c + xercon) >> crf_d));
}
@ -1658,7 +1619,9 @@ void ppc_cmpl() {
crf_d = crf_d << 2;
ppc_grab_regssab();
xercon = (ppc_state.spr[SPR::XER] & 0x80000000UL) >> 3;
cmp_c = (ppc_result_a == ppc_result_b) ? 0x20000000UL : (ppc_result_a > ppc_result_b) ? 0x40000000UL : 0x80000000UL;
cmp_c = (ppc_result_a == ppc_result_b)
? 0x20000000UL
: (ppc_result_a > ppc_result_b) ? 0x40000000UL : 0x80000000UL;
ppc_state.cr = ((ppc_state.cr & ~(0xf0000000UL >> crf_d)) | ((cmp_c + xercon) >> crf_d));
}
@ -1674,7 +1637,8 @@ void ppc_cmpli() {
crf_d = crf_d << 2;
ppc_grab_regssauimm();
xercon = (ppc_state.spr[SPR::XER] & 0x80000000UL) >> 3;
cmp_c = (ppc_result_a == uimm) ? 0x20000000UL : (ppc_result_a > uimm) ? 0x40000000UL : 0x80000000UL;
cmp_c = (ppc_result_a == uimm) ? 0x20000000UL
: (ppc_result_a > uimm) ? 0x40000000UL : 0x80000000UL;
ppc_state.cr = ((ppc_state.cr & ~(0xf0000000UL >> crf_d)) | ((cmp_c + xercon) >> crf_d));
}
@ -1684,8 +1648,7 @@ void ppc_crand() {
ppc_grab_regsdab();
if ((ppc_state.cr & (0x80000000UL >> reg_a)) && (ppc_state.cr & (0x80000000UL >> reg_b))) {
ppc_state.cr |= (0x80000000UL >> reg_d);
}
else {
} else {
ppc_state.cr &= ~(0x80000000UL >> reg_d);
}
}
@ -1693,8 +1656,7 @@ void ppc_crandc() {
ppc_grab_regsdab();
if ((ppc_state.cr & (0x80000000UL >> reg_a)) && !(ppc_state.cr & (0x80000000UL >> reg_b))) {
ppc_state.cr |= (0x80000000UL >> reg_d);
}
else {
} else {
ppc_state.cr &= ~(0x80000000UL >> reg_d);
}
}
@ -1702,8 +1664,7 @@ void ppc_creqv() {
ppc_grab_regsdab();
if (!((ppc_state.cr & (0x80000000UL >> reg_a)) ^ (ppc_state.cr & (0x80000000UL >> reg_b)))) {
ppc_state.cr |= (0x80000000UL >> reg_d);
}
else {
} else {
ppc_state.cr &= ~(0x80000000UL >> reg_d);
}
}
@ -1711,8 +1672,7 @@ void ppc_crnand() {
ppc_grab_regsdab();
if (!((ppc_state.cr & (0x80000000UL >> reg_a)) && (ppc_state.cr & (0x80000000UL >> reg_b)))) {
ppc_state.cr |= (0x80000000UL >> reg_d);
}
else {
} else {
ppc_state.cr &= ~(0x80000000UL >> reg_d);
}
}
@ -1720,8 +1680,7 @@ void ppc_crnor() {
ppc_grab_regsdab();
if (!((ppc_state.cr & (0x80000000UL >> reg_a)) || (ppc_state.cr & (0x80000000UL >> reg_b)))) {
ppc_state.cr |= (0x80000000UL >> reg_d);
}
else {
} else {
ppc_state.cr &= ~(0x80000000UL >> reg_d);
}
}
@ -1730,8 +1689,7 @@ void ppc_cror() {
ppc_grab_regsdab();
if ((ppc_state.cr & (0x80000000UL >> reg_a)) || (ppc_state.cr & (0x80000000UL >> reg_b))) {
ppc_state.cr |= (0x80000000UL >> reg_d);
}
else {
} else {
ppc_state.cr &= ~(0x80000000UL >> reg_d);
}
}
@ -1739,8 +1697,7 @@ void ppc_crorc() {
ppc_grab_regsdab();
if ((ppc_state.cr & (0x80000000UL >> reg_a)) || !(ppc_state.cr & (0x80000000UL >> reg_b))) {
ppc_state.cr |= (0x80000000UL >> reg_d);
}
else {
} else {
ppc_state.cr &= ~(0x80000000UL >> reg_d);
}
}
@ -1748,8 +1705,7 @@ void ppc_crxor() {
ppc_grab_regsdab();
if ((ppc_state.cr & (0x80000000UL >> reg_a)) ^ (ppc_state.cr & (0x80000000UL >> reg_b))) {
ppc_state.cr |= (0x80000000UL >> reg_d);
}
else {
} else {
ppc_state.cr &= ~(0x80000000UL >> reg_d);
}
}
@ -1777,17 +1733,16 @@ void ppc_tw() {
reg_a = (ppc_cur_instruction >> 11) & 31;
reg_b = (ppc_cur_instruction >> 16) & 31;
ppc_to = (ppc_cur_instruction >> 21) & 31;
if ((((int32_t)ppc_state.gpr[reg_a] < (int32_t)ppc_state.gpr[reg_b]) & (ppc_to & 0x10)) || \
(((int32_t)ppc_state.gpr[reg_a] > (int32_t)ppc_state.gpr[reg_b])& (ppc_to & 0x08)) || \
(((int32_t)ppc_state.gpr[reg_a] == (int32_t)ppc_state.gpr[reg_b]) & (ppc_to & 0x04)) || \
((ppc_state.gpr[reg_a] < ppc_state.gpr[reg_b]) & (ppc_to & 0x02)) || \
if ((((int32_t)ppc_state.gpr[reg_a] < (int32_t)ppc_state.gpr[reg_b]) & (ppc_to & 0x10)) ||
(((int32_t)ppc_state.gpr[reg_a] > (int32_t)ppc_state.gpr[reg_b]) & (ppc_to & 0x08)) ||
(((int32_t)ppc_state.gpr[reg_a] == (int32_t)ppc_state.gpr[reg_b]) & (ppc_to & 0x04)) ||
((ppc_state.gpr[reg_a] < ppc_state.gpr[reg_b]) & (ppc_to & 0x02)) ||
((ppc_state.gpr[reg_a] > ppc_state.gpr[reg_b]) & (ppc_to & 0x01))) {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
void ppc_twi()
{
void ppc_twi() {
simm = (int32_t)((int16_t)((ppc_cur_instruction)&0xFFFF));
reg_a = (ppc_cur_instruction >> 16) & 0x1F;
ppc_to = (ppc_cur_instruction >> 21) & 0x1F;
@ -1851,8 +1806,7 @@ void ppc_dcbz() {
mem_write_qword((ppc_effective_address + 8), 0);
mem_write_qword((ppc_effective_address + 16), 0);
mem_write_qword((ppc_effective_address + 24), 0);
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_ALIGNMENT, 0x00000);
}
}
@ -1880,8 +1834,7 @@ void ppc_stbu() {
ppc_effective_address += ppc_result_a;
mem_write_byte(ppc_effective_address, ppc_result_d);
ppc_state.gpr[reg_a] = ppc_effective_address;
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -1892,8 +1845,7 @@ void ppc_stbux() {
ppc_effective_address = ppc_result_a + ppc_result_b;
mem_write_byte(ppc_effective_address, ppc_result_d);
ppc_state.gpr[reg_a] = ppc_effective_address;
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -1912,8 +1864,7 @@ void ppc_sthu() {
ppc_effective_address += ppc_result_a;
mem_write_word(ppc_effective_address, ppc_result_d);
ppc_state.gpr[reg_a] = ppc_effective_address;
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -1924,8 +1875,7 @@ void ppc_sthux() {
ppc_effective_address = ppc_result_a + ppc_result_b;
mem_write_word(ppc_effective_address, ppc_result_d);
ppc_state.gpr[reg_a] = ppc_effective_address;
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -1941,7 +1891,6 @@ void ppc_sthbrx() {
ppc_effective_address = (reg_a == 0) ? ppc_result_b : (ppc_result_a + ppc_result_b);
ppc_result_d = (uint32_t)(BYTESWAP_16((uint16_t)ppc_result_d));
mem_write_word(ppc_effective_address, ppc_result_d);
}
void ppc_stw() {
ppc_grab_regssa();
@ -1964,8 +1913,7 @@ void ppc_stwcx() {
mem_write_dword(ppc_effective_address, ppc_result_d);
ppc_state.cr |= (ppc_state.spr[SPR::XER] & 0x80000000) ? 0x30000000 : 0x20000000;
ppc_state.reserve = false;
}
else {
} else {
ppc_state.cr |= (ppc_state.spr[SPR::XER] & 0x80000000) ? 0x10000000 : 0;
}
}
@ -1977,8 +1925,7 @@ void ppc_stwu() {
ppc_effective_address += ppc_result_a;
mem_write_dword(ppc_effective_address, ppc_result_d);
ppc_state.gpr[reg_a] = ppc_effective_address;
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -1989,8 +1936,7 @@ void ppc_stwux() {
ppc_effective_address = ppc_result_a + ppc_result_b;
mem_write_dword(ppc_effective_address, ppc_result_d);
ppc_state.gpr[reg_a] = ppc_effective_address;
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -2002,8 +1948,7 @@ void ppc_stwbrx() {
mem_write_dword(ppc_effective_address, ppc_result_d);
}
void ppc_stmw()
{
void ppc_stmw() {
ppc_grab_regssa();
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
@ -2036,8 +1981,7 @@ void ppc_lbzu() {
ppc_result_a = ppc_effective_address;
ppc_store_result_regd();
ppc_store_result_rega();
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -2057,8 +2001,7 @@ void ppc_lbzux() {
ppc_result_a = ppc_effective_address;
ppc_store_result_regd();
ppc_store_result_rega();
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -2081,8 +2024,7 @@ void ppc_lhzu() {
ppc_result_a = ppc_effective_address;
ppc_store_result_regd();
ppc_store_result_rega();
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -2102,8 +2044,7 @@ void ppc_lhzux() {
ppc_result_a = ppc_effective_address;
ppc_store_result_regd();
ppc_store_result_rega();
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -2115,8 +2056,7 @@ void ppc_lha() {
uint16_t val = mem_grab_word(ppc_effective_address);
if (val & 0x8000) {
ppc_result_d = 0xFFFF0000UL | (uint32_t)val;
}
else {
} else {
ppc_result_d = (uint32_t)val;
}
ppc_store_result_regd();
@ -2130,15 +2070,13 @@ void ppc_lhau() {
uint16_t val = mem_grab_word(ppc_effective_address);
if (val & 0x8000) {
ppc_result_d = 0xFFFF0000UL | (uint32_t)val;
}
else {
} else {
ppc_result_d = (uint32_t)val;
}
ppc_store_result_regd();
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -2149,8 +2087,7 @@ void ppc_lhaux() {
uint16_t val = mem_grab_word(ppc_effective_address);
if (val & 0x8000) {
ppc_result_d = 0xFFFF0000UL | (uint32_t)val;
}
else {
} else {
ppc_result_d = (uint32_t)val;
}
ppc_store_result_regd();
@ -2164,8 +2101,7 @@ void ppc_lhax() {
uint16_t val = mem_grab_word(ppc_effective_address);
if (val & 0x8000) {
ppc_result_d = 0xFFFF0000UL | (uint32_t)val;
}
else {
} else {
ppc_result_d = (uint32_t)val;
}
ppc_store_result_regd();
@ -2202,8 +2138,7 @@ void ppc_lwzu() {
ppc_store_result_regd();
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -2219,8 +2154,7 @@ void ppc_lwzux() {
ppc_grab_regsdab();
if ((reg_a != reg_d) || reg_a != 0) {
ppc_effective_address = ppc_result_a + ppc_result_b;
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
ppc_result_d = mem_grab_dword(ppc_effective_address);
@ -2276,8 +2210,7 @@ void ppc_lswi() {
ppc_store_result_regd();
break;
case 3:
ppc_result_d = (ppc_result_d & 0xFFFFFF00UL) |
mem_grab_byte(ppc_effective_address);
ppc_result_d = (ppc_result_d & 0xFFFFFF00UL) | mem_grab_byte(ppc_effective_address);
ppc_store_result_regd();
break;
default:
@ -2286,8 +2219,7 @@ void ppc_lswi() {
if (shift_times == 3) {
shift_times = 0;
reg_d = (reg_d + 1) & 0x1F;
}
else {
} else {
shift_times++;
}
ppc_effective_address++;
@ -2325,8 +2257,7 @@ void ppc_lswx() {
ppc_store_result_regd();
break;
case 3:
ppc_result_d = (ppc_result_d & 0xFFFFFF00UL) |
mem_grab_byte(ppc_effective_address);
ppc_result_d = (ppc_result_d & 0xFFFFFF00UL) | mem_grab_byte(ppc_effective_address);
ppc_store_result_regd();
break;
default:
@ -2335,14 +2266,12 @@ void ppc_lswx() {
if (shift_times == 3) {
shift_times = 0;
reg_d = (reg_d + 1) & 0x1F;
}
else {
} else {
shift_times++;
}
ppc_effective_address++;
grab_inb--;
}
}
void ppc_stswi() {
@ -2375,8 +2304,7 @@ void ppc_stswi() {
if (shift_times == 3) {
shift_times = 0;
reg_s = (reg_s + 1) & 0x1F;
}
else {
} else {
shift_times++;
}
ppc_effective_address++;
@ -2413,8 +2341,7 @@ void ppc_stswx() {
if (shift_times == 3) {
shift_times = 0;
reg_s = (reg_s + 1) & 0x1F;
}
else {
} else {
shift_times++;
}
ppc_effective_address++;

View File

@ -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;
@ -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;

View File

@ -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;
@ -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;
}

View File

@ -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;
@ -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;
}

View File

@ -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>
@ -53,29 +53,22 @@ 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;
}
}
@ -363,8 +356,7 @@ 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);
@ -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;
}

View File

@ -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();

View File

@ -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);
}

View File

@ -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,10 +111,14 @@ 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);

View File

@ -24,17 +24,16 @@ 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 */
@ -42,8 +41,7 @@ AWACDevice::AWACDevice()
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)
{
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,8 +71,7 @@ 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;
@ -99,8 +93,7 @@ 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) {
@ -120,8 +113,7 @@ static void convert_data(const uint8_t *in, uint8_t *out, uint32_t len)
}
}
static void audio_out_callback(void *user_data, uint8_t *buf, int buf_len)
{
static void audio_out_callback(void* user_data, uint8_t* buf, int buf_len) {
uint8_t* p_in;
uint32_t rem_len, got_len;
@ -139,8 +131,7 @@ static void audio_out_callback(void *user_data, uint8_t *buf, int buf_len)
}
}
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;
@ -164,8 +155,7 @@ uint32_t AWACDevice::convert_data(const uint8_t *data, int len)
return i;
}
void AWACDevice::dma_start()
{
void AWACDevice::dma_start() {
SDL_AudioSpec snd_spec, snd_settings;
SDL_zero(snd_spec);
@ -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) {}

View File

@ -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;
};

View File

@ -21,20 +21,18 @@ 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);
}
uint8_t DMAChannel::interpret_cmd()
{
uint8_t DMAChannel::interpret_cmd() {
DMACmd cmd_struct;
get_next_cmd(this->cmd_ptr, &cmd_struct);
@ -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) {
@ -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) {
@ -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;
@ -237,8 +231,7 @@ void DMAChannel::start()
//}
}
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();
}

View File

@ -69,7 +69,9 @@ public:
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);

View File

@ -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;
@ -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;
}

View File

@ -77,23 +77,15 @@ private:
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

View File

@ -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,8 +46,7 @@ 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);
@ -57,27 +55,25 @@ HeathrowIC::~HeathrowIC()
}
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,8 +82,7 @@ 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) {
@ -101,8 +96,7 @@ uint32_t HeathrowIC::dma_read(uint32_t offset, int size)
return res;
}
void HeathrowIC::dma_write(uint32_t offset, uint32_t value, int size)
{
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);
@ -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");

View File

@ -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;

View File

@ -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 {
@ -43,8 +43,12 @@ public:
/** 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) {
if (this->dev_list[dev_addr]) {

View File

@ -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;

View File

@ -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;

View File

@ -19,16 +19,15 @@ 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()
{
MemCtrlBase::~MemCtrlBase() {
for (auto& reg : mem_regions) {
if (reg)
delete (reg);
@ -38,8 +37,7 @@ MemCtrlBase::~MemCtrlBase()
}
AddressMapEntry *MemCtrlBase::find_range(uint32_t addr)
{
AddressMapEntry* MemCtrlBase::find_range(uint32_t addr) {
for (auto& entry : address_map) {
if (addr >= entry.start && addr <= entry.end)
return &entry;
@ -49,9 +47,8 @@ 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 */
@ -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,8 +102,7 @@ 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)
{
bool MemCtrlBase::set_data(uint32_t reg_addr, const uint8_t* data, uint32_t size) {
AddressMapEntry* ref_entry;
uint32_t cpy_size;
@ -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 */

View File

@ -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 */
@ -62,8 +62,8 @@ public:
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;

View File

@ -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 {

View File

@ -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,14 +164,16 @@ 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
@ -193,8 +195,7 @@ 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
@ -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;

View File

@ -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();
@ -67,7 +66,9 @@ 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);
@ -87,12 +88,9 @@ 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,
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
@ -100,8 +98,7 @@ private:
0x00, // Bus number
0x00, // Subordinate bus number
0x00, // Discount counter
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, //Performance monitor command
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // Performance monitor command
0x00, 0x00, // Performance monitor mode control
0xFF, 0xFF,
@ -110,17 +107,14 @@ private:
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
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
@ -132,8 +126,7 @@ private:
0x10, 0x00, 0x00, 0xFF, // PICR1
0x0C, 0x06, 0x0C, 0x00, // PICR2
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
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
@ -153,10 +146,8 @@ private:
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)

View File

@ -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,8 +74,7 @@ void NVram::init() {
f.close();
}
void NVram::save()
{
void NVram::save() {
ofstream f(this->file_name, ios::out | ios::binary);
/* write file identification */

View File

@ -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();

View File

@ -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,23 +45,29 @@ 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

View File

@ -8,8 +8,7 @@ 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_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice* obj) = 0;
};
#endif /* PCI_HOST_H */

View File

@ -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,7 +66,9 @@ 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) {
@ -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;

View File

@ -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
@ -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,8 +124,7 @@ void ViaCuda::write(int reg, uint8_t value)
}
}
void ViaCuda::print_enabled_ints()
{
void ViaCuda::print_enabled_ints() {
const char* via_int_src[] = {"CA2", "CA1", "SR", "CB2", "CB1", "T2", "T1"};
for (int i = 0; i < 7; 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,20 +270,17 @@ void ViaCuda::process_packet()
}
}
void ViaCuda::process_adb_command(uint8_t cmd_byte, int data_count)
{
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) {
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)) {
@ -312,36 +288,30 @@ void ViaCuda::process_adb_command(uint8_t cmd_byte, int data_count)
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)) {

View File

@ -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();
@ -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 */

View File

@ -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,8 +16,7 @@ MachineBase::MachineBase(std::string name)
this->aliases.clear();
}
MachineBase::~MachineBase()
{
MachineBase::~MachineBase() {
for (auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) {
delete it->second;
}
@ -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,8 +67,7 @@ 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;

View File

@ -27,13 +27,12 @@ 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();

View File

@ -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;
@ -61,8 +61,7 @@ static const map<uint32_t, string> rom_identity = {
};
int create_machine_for_id(uint32_t id)
{
int create_machine_for_id(uint32_t id) {
switch (id) {
case 0x476F7373:
create_gossamer();
@ -76,23 +75,21 @@ 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)
{
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);
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];
@ -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());

View File

@ -24,18 +24,17 @@ 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;
@ -49,8 +48,7 @@ static void setup_ram_slot(std::string name, int i2c_addr, int capacity_megs)
}
int create_gossamer()
{
int create_gossamer() {
if (gMachineObj) {
LOG_F(ERROR, "Global machine object not empty!");
return -1;
@ -70,13 +68,13 @@ int create_gossamer()
/* 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);

View File

@ -22,23 +22,21 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
// 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,8 +46,8 @@ 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;
@ -58,9 +56,7 @@ int main(int argc, char **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")) {
} 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();
@ -122,15 +112,13 @@ int main(int argc, char **argv)
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;

View File

@ -5,8 +5,8 @@
#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)))))
@ -30,27 +30,23 @@
#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) */