clang-format everything
This commit is contained in:
parent
a5c63c1b09
commit
0ab9380be3
|
@ -0,0 +1,78 @@
|
|||
Language: Cpp
|
||||
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveDeclarations: false
|
||||
#AlignConsecutiveMacros: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: false
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
#AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
#BreakInheritanceList: BeforeComma
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 100
|
||||
CompactNamespaces: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
FixNamespaceComments: true
|
||||
IncludeBlocks: Preserve
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: None
|
||||
PenaltyBreakAssignment: 50
|
||||
PenaltyBreakBeforeFirstCallParameter: 0
|
||||
PenaltyBreakComment: 100
|
||||
PenaltyBreakFirstLessLess: 200
|
||||
PenaltyBreakString: 100
|
||||
#PenaltyBreakTemplateDeclaration: 0
|
||||
PenaltyExcessCharacter: 10
|
||||
PenaltyReturnTypeOnItsOwnLine: 1000
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SpaceAfterCStyleCast: false
|
||||
#SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
#SpaceBeforeCpp11BracedList: true
|
||||
#SpaceBeforeCtorInitializerColon: false
|
||||
#SpaceBeforeInheritanceColon: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
#SpaceBeforeRangeBasedForLoopColon: false
|
||||
#SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 4
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
#Standard: c++17
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
|
@ -22,23 +22,22 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
// The Power-specific opcodes for the processor - ppcopcodes.cpp
|
||||
// Any shared opcodes are in ppcopcodes.cpp
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include <iostream>
|
||||
#include <array>
|
||||
#include <stdio.h>
|
||||
#include <stdexcept>
|
||||
#include "ppcemu.h"
|
||||
#include "ppcmmu.h"
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
void power_abs() {
|
||||
ppc_grab_regsda();
|
||||
if (ppc_result_a == 0x80000000) {
|
||||
ppc_result_d = ppc_result_a;
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_store_result_regd();
|
||||
|
@ -50,8 +49,7 @@ void power_absdot() {
|
|||
if (ppc_result_a == 0x80000000) {
|
||||
ppc_result_d = ppc_result_a;
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
@ -64,8 +62,7 @@ void power_abso() {
|
|||
ppc_result_d = ppc_result_a;
|
||||
ppc_state.spr[SPR::XER] |= 0x40000000;
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_store_result_regd();
|
||||
|
@ -77,8 +74,7 @@ void power_absodot() {
|
|||
ppc_result_d = ppc_result_a;
|
||||
ppc_state.spr[SPR::XER] |= 0x40000000;
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
@ -164,8 +160,7 @@ void power_doz() {
|
|||
ppc_grab_regsdab();
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
ppc_store_result_rega();
|
||||
|
@ -175,8 +170,7 @@ void power_dozdot() {
|
|||
ppc_grab_regsdab();
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
@ -186,8 +180,7 @@ void power_dozdot() {
|
|||
void power_dozo() {
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
}
|
||||
|
@ -195,8 +188,7 @@ void power_dozo() {
|
|||
void power_dozodot() {
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
}
|
||||
|
@ -205,8 +197,7 @@ void power_dozi() {
|
|||
ppc_grab_regsdab();
|
||||
if (((int32_t)ppc_result_a) > simm) {
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_d = ~ppc_result_a + simm + 1;
|
||||
}
|
||||
ppc_store_result_rega();
|
||||
|
@ -260,8 +251,7 @@ void power_lscbx() {
|
|||
if (shift_amount == 3) {
|
||||
shift_amount = 0;
|
||||
reg_d = (reg_d + 1) & 0x1F;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
shift_amount++;
|
||||
}
|
||||
} while (bytes_to_load > 0);
|
||||
|
@ -283,11 +273,9 @@ void power_maskg() {
|
|||
for (uint32_t i = mask_start; i < mask_end; i++) {
|
||||
insert_mask |= (0x80000000 >> i);
|
||||
}
|
||||
}
|
||||
else if (mask_start == (mask_end + 1)) {
|
||||
} else if (mask_start == (mask_end + 1)) {
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
for (uint32_t i = (mask_end + 1); i < (mask_start - 1); i++) {
|
||||
insert_mask &= (~(0x80000000 >> i));
|
||||
|
@ -308,11 +296,9 @@ void power_maskgdot() {
|
|||
for (uint32_t i = mask_start; i < mask_end; i++) {
|
||||
insert_mask |= (0x80000000 >> i);
|
||||
}
|
||||
}
|
||||
else if (mask_start == (mask_end + 1)) {
|
||||
} else if (mask_start == (mask_end + 1)) {
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
for (uint32_t i = (mask_end + 1); i < (mask_start - 1); i++) {
|
||||
insert_mask &= (~(0x80000000 >> i));
|
||||
|
@ -364,7 +350,6 @@ void power_mul() {
|
|||
ppc_result_d = ((uint32_t)(product >> 32));
|
||||
ppc_state.spr[SPR::MQ] = ((uint32_t)(product));
|
||||
ppc_store_result_regd();
|
||||
|
||||
}
|
||||
|
||||
void power_muldot() {
|
||||
|
@ -376,7 +361,6 @@ void power_muldot() {
|
|||
ppc_state.spr[SPR::MQ] = ((uint32_t)(product));
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
ppc_store_result_regd();
|
||||
|
||||
}
|
||||
|
||||
void power_mulo() {
|
||||
|
@ -385,7 +369,6 @@ void power_mulo() {
|
|||
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
|
||||
ppc_result_d = ((uint32_t)(product >> 32));
|
||||
ppc_state.spr[SPR::MQ] = ((uint32_t)(product));
|
||||
|
||||
}
|
||||
|
||||
void power_mulodot() {
|
||||
|
@ -394,7 +377,6 @@ void power_mulodot() {
|
|||
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
|
||||
ppc_result_d = ((uint32_t)(product >> 32));
|
||||
ppc_state.spr[SPR::MQ] = ((uint32_t)(product));
|
||||
|
||||
}
|
||||
|
||||
void power_nabs() {
|
||||
|
@ -426,11 +408,9 @@ void power_rlmi() {
|
|||
for (uint32_t i = rot_mb; i < rot_me; i++) {
|
||||
insert_mask |= (0x80000000 >> i);
|
||||
}
|
||||
}
|
||||
else if (rot_mb == (rot_me + 1)) {
|
||||
} else if (rot_mb == (rot_me + 1)) {
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
for (uint32_t i = (rot_me + 1); i < (rot_mb - 1); i++) {
|
||||
insert_mask &= (~(0x80000000 >> i));
|
||||
|
@ -446,8 +426,7 @@ void power_rrib() {
|
|||
ppc_grab_regssab();
|
||||
if (ppc_result_d & 0x80000000) {
|
||||
ppc_result_a |= (0x80000000 >> ppc_result_b);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_a &= ~(0x80000000 >> ppc_result_b);
|
||||
}
|
||||
ppc_store_result_rega();
|
||||
|
@ -457,8 +436,7 @@ void power_rribdot() {
|
|||
ppc_grab_regssab();
|
||||
if (ppc_result_d & 0x80000000) {
|
||||
ppc_result_a |= (0x80000000 >> ppc_result_b);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ppc_result_a &= ~(0x80000000 >> ppc_result_b);
|
||||
}
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 ®_name, uint64_t val, bool is_write)
|
||||
{
|
||||
uint64_t reg_op(string& reg_name, uint64_t val, bool is_write) {
|
||||
string reg_name_u, reg_num_str;
|
||||
unsigned reg_num;
|
||||
map<string, int>::iterator spr;
|
||||
|
@ -853,9 +807,7 @@ uint64_t reg_op(string ®_name, uint64_t val, bool is_write)
|
|||
reg_name_u = reg_name;
|
||||
|
||||
/* convert reg_name string to uppercase */
|
||||
std::for_each(reg_name_u.begin(), reg_name_u.end(), [](char & c) {
|
||||
c = ::toupper(c);
|
||||
});
|
||||
std::for_each(reg_name_u.begin(), reg_name_u.end(), [](char& c) { c = ::toupper(c); });
|
||||
|
||||
try {
|
||||
if (reg_name_u == "PC") {
|
||||
|
@ -925,20 +877,17 @@ uint64_t reg_op(string ®_name, uint64_t val, bool is_write)
|
|||
ppc_state.spr[spr->second] = val;
|
||||
return ppc_state.spr[spr->second];
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
bail_out:
|
||||
throw std::invalid_argument(string("Unknown register ") + reg_name);
|
||||
}
|
||||
|
||||
uint64_t get_reg(string ®_name)
|
||||
{
|
||||
uint64_t get_reg(string& reg_name) {
|
||||
return reg_op(reg_name, 0, false);
|
||||
}
|
||||
|
||||
void set_reg(string ®_name, uint64_t val)
|
||||
{
|
||||
void set_reg(string& reg_name, uint64_t val) {
|
||||
reg_op(reg_name, val, true);
|
||||
}
|
||||
|
|
|
@ -21,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -19,17 +19,16 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <atirage.h>
|
||||
#include <cstdint>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include "displayid.h"
|
||||
#include "endianswap.h"
|
||||
#include "memreadwrite.h"
|
||||
#include "pcidevice.h"
|
||||
#include "displayid.h"
|
||||
#include <atirage.h>
|
||||
#include <cstdint>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
|
||||
ATIRage::ATIRage(uint16_t dev_id) : PCIDevice("ati-rage")
|
||||
{
|
||||
ATIRage::ATIRage(uint16_t dev_id) : PCIDevice("ati-rage") {
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[0], (dev_id << 16) | ATI_PCI_VENDOR_ID);
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[8], 0x0300005C);
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[0x3C], 0x00080100);
|
||||
|
@ -37,13 +36,11 @@ ATIRage::ATIRage(uint16_t dev_id) : PCIDevice("ati-rage")
|
|||
this->disp_id = new DisplayID();
|
||||
}
|
||||
|
||||
ATIRage::~ATIRage()
|
||||
{
|
||||
ATIRage::~ATIRage() {
|
||||
delete (this->disp_id);
|
||||
}
|
||||
|
||||
uint32_t ATIRage::size_dep_read(uint8_t *buf, uint32_t size)
|
||||
{
|
||||
uint32_t ATIRage::size_dep_read(uint8_t* buf, uint32_t size) {
|
||||
switch (size) {
|
||||
case 4:
|
||||
return READ_DWORD_LE_A(buf);
|
||||
|
@ -60,8 +57,7 @@ uint32_t ATIRage::size_dep_read(uint8_t *buf, uint32_t size)
|
|||
}
|
||||
}
|
||||
|
||||
void ATIRage::size_dep_write(uint8_t *buf, uint32_t value, uint32_t size)
|
||||
{
|
||||
void ATIRage::size_dep_write(uint8_t* buf, uint32_t value, uint32_t size) {
|
||||
switch (size) {
|
||||
case 4:
|
||||
WRITE_DWORD_BE_A(buf, value);
|
||||
|
@ -74,8 +70,7 @@ void ATIRage::size_dep_write(uint8_t *buf, uint32_t value, uint32_t size)
|
|||
}
|
||||
}
|
||||
|
||||
const char* ATIRage::get_reg_name(uint32_t reg_offset)
|
||||
{
|
||||
const char* ATIRage::get_reg_name(uint32_t reg_offset) {
|
||||
const char* reg_name;
|
||||
|
||||
switch (reg_offset & ~3) {
|
||||
|
@ -152,16 +147,19 @@ const char* ATIRage::get_reg_name(uint32_t reg_offset)
|
|||
return reg_name;
|
||||
}
|
||||
|
||||
uint32_t ATIRage::read_reg(uint32_t offset, uint32_t size)
|
||||
{
|
||||
uint32_t ATIRage::read_reg(uint32_t offset, uint32_t size) {
|
||||
uint32_t res;
|
||||
|
||||
switch (offset & ~3) {
|
||||
case ATI_GP_IO:
|
||||
break;
|
||||
default:
|
||||
LOG_F(INFO, "ATI Rage: read I/O reg %s at 0x%X, size=%d, val=0x%X",
|
||||
get_reg_name(offset), offset, size,
|
||||
LOG_F(
|
||||
INFO,
|
||||
"ATI Rage: read I/O reg %s at 0x%X, size=%d, val=0x%X",
|
||||
get_reg_name(offset),
|
||||
offset,
|
||||
size,
|
||||
size_dep_read(&this->block_io_regs[offset], size));
|
||||
}
|
||||
|
||||
|
@ -170,8 +168,7 @@ uint32_t ATIRage::read_reg(uint32_t offset, uint32_t size)
|
|||
return res;
|
||||
}
|
||||
|
||||
void ATIRage::write_reg(uint32_t offset, uint32_t value, uint32_t size)
|
||||
{
|
||||
void ATIRage::write_reg(uint32_t offset, uint32_t value, uint32_t size) {
|
||||
uint32_t gpio_val;
|
||||
uint16_t gpio_dir;
|
||||
|
||||
|
@ -183,20 +180,23 @@ void ATIRage::write_reg(uint32_t offset, uint32_t value, uint32_t size)
|
|||
if (offset < (ATI_GP_IO + 2)) {
|
||||
gpio_val = READ_DWORD_LE_A(&this->block_io_regs[ATI_GP_IO]);
|
||||
gpio_dir = (gpio_val >> 16) & 0x3FFF;
|
||||
WRITE_WORD_LE_A(&this->block_io_regs[ATI_GP_IO],
|
||||
WRITE_WORD_LE_A(
|
||||
&this->block_io_regs[ATI_GP_IO],
|
||||
this->disp_id->read_monitor_sense(gpio_val, gpio_dir));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_F(INFO, "ATI Rage: %s register at 0x%X set to 0x%X",
|
||||
get_reg_name(offset), offset & ~3,
|
||||
LOG_F(
|
||||
INFO,
|
||||
"ATI Rage: %s register at 0x%X set to 0x%X",
|
||||
get_reg_name(offset),
|
||||
offset & ~3,
|
||||
READ_DWORD_LE_A(&this->block_io_regs[offset & ~3]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size)
|
||||
{
|
||||
uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size) {
|
||||
uint32_t res = 0;
|
||||
|
||||
LOG_F(INFO, "Reading ATI Rage config space, offset = 0x%X, size=%d", reg_offs, size);
|
||||
|
@ -207,32 +207,32 @@ uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size)
|
|||
return res;
|
||||
}
|
||||
|
||||
void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
|
||||
{
|
||||
LOG_F(INFO, "Writing into ATI Rage PCI config space, offset = 0x%X, val=0x%X size=%d",
|
||||
reg_offs, BYTESWAP_32(value), size);
|
||||
void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) {
|
||||
LOG_F(
|
||||
INFO,
|
||||
"Writing into ATI Rage PCI config space, offset = 0x%X, val=0x%X size=%d",
|
||||
reg_offs,
|
||||
BYTESWAP_32(value),
|
||||
size);
|
||||
|
||||
switch (reg_offs) {
|
||||
case 0x10: /* BAR 0 */
|
||||
if (value == 0xFFFFFFFFUL) {
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR0], 0xFF000008);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR0], value);
|
||||
}
|
||||
break;
|
||||
case 0x14: /* BAR 1: I/O space base, 256 bytes wide */
|
||||
if (value == 0xFFFFFFFFUL) {
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR1], 0x0000FFF1);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR1], value);
|
||||
}
|
||||
case 0x18: /* BAR 2 */
|
||||
if (value == 0xFFFFFFFFUL) {
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR2], 0xFFFFF000);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR2], value);
|
||||
}
|
||||
break;
|
||||
|
@ -248,8 +248,7 @@ void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
|
|||
}
|
||||
|
||||
|
||||
bool ATIRage::io_access_allowed(uint32_t offset, uint32_t *p_io_base)
|
||||
{
|
||||
bool ATIRage::io_access_allowed(uint32_t offset, uint32_t* p_io_base) {
|
||||
if (!(this->pci_cfg[CFG_REG_CMD] & 1)) {
|
||||
LOG_F(WARNING, "ATI I/O space disabled in the command reg");
|
||||
return false;
|
||||
|
@ -268,8 +267,7 @@ bool ATIRage::io_access_allowed(uint32_t offset, uint32_t *p_io_base)
|
|||
}
|
||||
|
||||
|
||||
bool ATIRage::pci_io_read(uint32_t offset, uint32_t size, uint32_t *res)
|
||||
{
|
||||
bool ATIRage::pci_io_read(uint32_t offset, uint32_t size, uint32_t* res) {
|
||||
uint32_t io_base;
|
||||
|
||||
if (!this->io_access_allowed(offset, &io_base)) {
|
||||
|
@ -281,8 +279,7 @@ bool ATIRage::pci_io_read(uint32_t offset, uint32_t size, uint32_t *res)
|
|||
}
|
||||
|
||||
|
||||
bool ATIRage::pci_io_write(uint32_t offset, uint32_t value, uint32_t size)
|
||||
{
|
||||
bool ATIRage::pci_io_write(uint32_t offset, uint32_t value, uint32_t size) {
|
||||
uint32_t io_base;
|
||||
|
||||
if (!this->io_access_allowed(offset, &io_base)) {
|
||||
|
@ -294,13 +291,11 @@ bool ATIRage::pci_io_write(uint32_t offset, uint32_t value, uint32_t size)
|
|||
}
|
||||
|
||||
|
||||
uint32_t ATIRage::read(uint32_t reg_start, uint32_t offset, int size)
|
||||
{
|
||||
uint32_t ATIRage::read(uint32_t reg_start, uint32_t offset, int size) {
|
||||
LOG_F(INFO, "Reading reg=%X, size %d", offset, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ATIRage::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
|
||||
{
|
||||
void ATIRage::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) {
|
||||
LOG_F(INFO, "Writing reg=%X, value=%X, size %d", offset, value, size);
|
||||
}
|
||||
|
|
|
@ -22,9 +22,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef ATI_RAGE_H
|
||||
#define ATI_RAGE_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include "pcidevice.h"
|
||||
#include "displayid.h"
|
||||
#include "pcidevice.h"
|
||||
#include <cinttypes>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -102,8 +102,7 @@ enum {
|
|||
ATI_TVO_CNTL = 0x0500,
|
||||
};
|
||||
|
||||
class ATIRage : public PCIDevice
|
||||
{
|
||||
class ATIRage : public PCIDevice {
|
||||
public:
|
||||
ATIRage(uint16_t dev_id);
|
||||
~ATIRage();
|
||||
|
@ -112,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);
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -45,8 +45,12 @@ class HWComponent {
|
|||
public:
|
||||
virtual ~HWComponent() = default;
|
||||
|
||||
virtual std::string get_name(void) { return this->name; };
|
||||
virtual void set_name(std::string name) { this->name = name; };
|
||||
virtual std::string get_name(void) {
|
||||
return this->name;
|
||||
};
|
||||
virtual void set_name(std::string name) {
|
||||
this->name = name;
|
||||
};
|
||||
|
||||
virtual bool supports_type(HWCompType type) = 0;
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef I2C_H
|
||||
#define I2C_H
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
/** Base class for I2C devices */
|
||||
class I2CDevice {
|
||||
|
@ -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]) {
|
||||
|
|
|
@ -22,9 +22,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef MACHINE_ID_H
|
||||
#define MACHINE_ID_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include "hwcomponent.h"
|
||||
#include "mmiodevice.h"
|
||||
#include <cinttypes>
|
||||
|
||||
/**
|
||||
@file Contains definitions for PowerMacintosh machine ID registers.
|
||||
|
@ -44,7 +44,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
*/
|
||||
class GossamerID : public MMIODevice {
|
||||
public:
|
||||
GossamerID(const uint16_t id) { this->id = id, this->name = "Machine-id"; };
|
||||
GossamerID(const uint16_t id) {
|
||||
this->id = id, this->name = "Machine-id";
|
||||
};
|
||||
~GossamerID() = default;
|
||||
|
||||
bool supports_type(HWCompType type) {
|
||||
|
@ -52,10 +54,10 @@ public:
|
|||
};
|
||||
|
||||
uint32_t read(uint32_t reg_start, uint32_t offset, int size) {
|
||||
return ((!offset && size == 2) ? this->id : 0); };
|
||||
return ((!offset && size == 2) ? this->id : 0);
|
||||
};
|
||||
|
||||
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
|
||||
{}; /* not writable */
|
||||
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size){}; /* not writable */
|
||||
|
||||
private:
|
||||
uint16_t id;
|
||||
|
|
|
@ -51,16 +51,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef MACIO_H
|
||||
#define MACIO_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include "hwcomponent.h"
|
||||
#include "pcidevice.h"
|
||||
#include "memctrlbase.h"
|
||||
#include "mmiodevice.h"
|
||||
#include "pcihost.h"
|
||||
#include "viacuda.h"
|
||||
#include "nvram.h"
|
||||
#include "awacs.h"
|
||||
#include "dbdma.h"
|
||||
#include "hwcomponent.h"
|
||||
#include "memctrlbase.h"
|
||||
#include "mmiodevice.h"
|
||||
#include "nvram.h"
|
||||
#include "pcidevice.h"
|
||||
#include "pcihost.h"
|
||||
#include "viacuda.h"
|
||||
#include <cinttypes>
|
||||
|
||||
/**
|
||||
Heathrow ASIC emulation
|
||||
|
@ -86,16 +86,19 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
VIA-CUDA register space: 0x00016000, size: 0x00002000
|
||||
*/
|
||||
|
||||
class HeathrowIC : public PCIDevice
|
||||
{
|
||||
class HeathrowIC : public PCIDevice {
|
||||
public:
|
||||
HeathrowIC();
|
||||
~HeathrowIC();
|
||||
|
||||
bool supports_type(HWCompType type) { return type == HWCompType::MMIO_DEV; };
|
||||
bool supports_type(HWCompType type) {
|
||||
return type == HWCompType::MMIO_DEV;
|
||||
};
|
||||
|
||||
/* PCI device methods */
|
||||
bool supports_io_space(void) { return false; };
|
||||
bool supports_io_space(void) {
|
||||
return false;
|
||||
};
|
||||
|
||||
uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size);
|
||||
void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size);
|
||||
|
@ -113,17 +116,23 @@ protected:
|
|||
|
||||
private:
|
||||
uint8_t pci_cfg_hdr[256] = {
|
||||
0x6B, 0x10, // vendor ID: Apple Computer Inc.
|
||||
0x10, 0x00, // device ID: Heathrow Mac I/O
|
||||
0x00, 0x00, // PCI command (set to 0 at power-up?)
|
||||
0x00, 0x00, // PCI status (set to 0 at power-up?)
|
||||
0x6B,
|
||||
0x10, // vendor ID: Apple Computer Inc.
|
||||
0x10,
|
||||
0x00, // device ID: Heathrow Mac I/O
|
||||
0x00,
|
||||
0x00, // PCI command (set to 0 at power-up?)
|
||||
0x00,
|
||||
0x00, // PCI status (set to 0 at power-up?)
|
||||
0x01, // revision ID
|
||||
// class code is reported in OF property "class-code" as 0xff0000
|
||||
0x00, // standard programming
|
||||
0x00, // subclass code
|
||||
0xFF, // class code: unassigned
|
||||
0x00, 0x00, // unknown defaults
|
||||
0x00, 0x00 // unknown defaults
|
||||
0x00,
|
||||
0x00, // unknown defaults
|
||||
0x00,
|
||||
0x00 // unknown defaults
|
||||
};
|
||||
|
||||
uint32_t int_mask2;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -22,9 +22,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef MMIO_DEVICE_H
|
||||
#define MMIO_DEVICE_H
|
||||
|
||||
#include "hwcomponent.h"
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
#include "hwcomponent.h"
|
||||
|
||||
/** Abstract class representing a simple, memory-mapped I/O device */
|
||||
class MMIODevice : public HWComponent {
|
||||
|
|
|
@ -24,20 +24,19 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
Author: Max Poliakovski
|
||||
*/
|
||||
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
#include "memreadwrite.h"
|
||||
#include "memctrlbase.h"
|
||||
#include "mmiodevice.h"
|
||||
#include "hwcomponent.h"
|
||||
#include "memctrlbase.h"
|
||||
#include "memreadwrite.h"
|
||||
#include "mmiodevice.h"
|
||||
#include "mpc106.h"
|
||||
|
||||
|
||||
MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle PCI host bridge")
|
||||
{
|
||||
MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle PCI host bridge") {
|
||||
this->name = "Grackle";
|
||||
|
||||
/* add PCI/ISA I/O space, 64K for now */
|
||||
|
@ -50,13 +49,11 @@ MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle PCI host bridge")
|
|||
this->io_space_devs.clear();
|
||||
}
|
||||
|
||||
MPC106::~MPC106()
|
||||
{
|
||||
MPC106::~MPC106() {
|
||||
this->pci_0_bus.clear();
|
||||
}
|
||||
|
||||
bool MPC106::supports_type(HWCompType type)
|
||||
{
|
||||
bool MPC106::supports_type(HWCompType type) {
|
||||
if (type == HWCompType::MEM_CTRL || type == HWCompType::MMIO_DEV ||
|
||||
type == HWCompType::PCI_HOST || type == HWCompType::PCI_DEV) {
|
||||
return true;
|
||||
|
@ -65,8 +62,7 @@ bool MPC106::supports_type(HWCompType type)
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t MPC106::read(uint32_t reg_start, uint32_t offset, int size)
|
||||
{
|
||||
uint32_t MPC106::read(uint32_t reg_start, uint32_t offset, int size) {
|
||||
uint32_t result;
|
||||
|
||||
if (reg_start == 0xFE000000) {
|
||||
|
@ -78,8 +74,7 @@ uint32_t MPC106::read(uint32_t reg_start, uint32_t offset, int size)
|
|||
}
|
||||
}
|
||||
LOG_F(ERROR, "Attempt to read from unmapped PCI I/O space, offset=0x%X", offset);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (offset >= 0x200000) {
|
||||
if (this->config_addr & 0x80) // process only if bit E (enable) is set
|
||||
return pci_read(size);
|
||||
|
@ -91,8 +86,7 @@ uint32_t MPC106::read(uint32_t reg_start, uint32_t offset, int size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void MPC106::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
|
||||
{
|
||||
void MPC106::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) {
|
||||
if (reg_start == 0xFE000000) {
|
||||
/* broadcast I/O request to devices that support I/O space
|
||||
until a device returns true that means "request accepted" */
|
||||
|
@ -102,26 +96,26 @@ void MPC106::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size
|
|||
}
|
||||
}
|
||||
LOG_F(ERROR, "Attempt to write to unmapped PCI I/O space, offset=0x%X", offset);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (offset < 0x200000) {
|
||||
this->config_addr = value;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (this->config_addr & 0x80) // process only if bit E (enable) is set
|
||||
return pci_write(value, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t MPC106::pci_read(uint32_t size)
|
||||
{
|
||||
uint32_t MPC106::pci_read(uint32_t size) {
|
||||
int bus_num, dev_num, fun_num, reg_offs;
|
||||
|
||||
bus_num = (this->config_addr >> 8) & 0xFF;
|
||||
if (bus_num) {
|
||||
LOG_F(ERROR, "%s err: read attempt from non-local PCI bus, config_addr = %x \n", \
|
||||
this->name.c_str(), this->config_addr);
|
||||
LOG_F(
|
||||
ERROR,
|
||||
"%s err: read attempt from non-local PCI bus, config_addr = %x \n",
|
||||
this->name.c_str(),
|
||||
this->config_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -135,7 +129,11 @@ uint32_t MPC106::pci_read(uint32_t size)
|
|||
if (this->pci_0_bus.count(dev_num)) {
|
||||
return this->pci_0_bus[dev_num]->pci_cfg_read(reg_offs, size);
|
||||
} else {
|
||||
LOG_F(ERROR, "%s err: read attempt from non-existing PCI device %d \n", this->name.c_str(), dev_num);
|
||||
LOG_F(
|
||||
ERROR,
|
||||
"%s err: read attempt from non-existing PCI device %d \n",
|
||||
this->name.c_str(),
|
||||
dev_num);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -143,14 +141,16 @@ uint32_t MPC106::pci_read(uint32_t size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void MPC106::pci_write(uint32_t value, uint32_t size)
|
||||
{
|
||||
void MPC106::pci_write(uint32_t value, uint32_t size) {
|
||||
int bus_num, dev_num, fun_num, reg_offs;
|
||||
|
||||
bus_num = (this->config_addr >> 8) & 0xFF;
|
||||
if (bus_num) {
|
||||
LOG_F(ERROR, "%s err: write attempt to non-local PCI bus, config_addr = %x \n",
|
||||
this->name.c_str(), this->config_addr);
|
||||
LOG_F(
|
||||
ERROR,
|
||||
"%s err: write attempt to non-local PCI bus, config_addr = %x \n",
|
||||
this->name.c_str(),
|
||||
this->config_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -164,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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -22,8 +22,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef NVRAM_H
|
||||
#define NVRAM_H
|
||||
|
||||
#include <string>
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
|
||||
/** @file Non-volatile RAM emulation.
|
||||
|
||||
|
@ -31,8 +31,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
automatically saved to and restored from the dedicated file.
|
||||
*/
|
||||
|
||||
class NVram
|
||||
{
|
||||
class NVram {
|
||||
public:
|
||||
NVram(std::string file_name = "nvram.bin", uint32_t ram_size = 8192);
|
||||
~NVram();
|
||||
|
|
|
@ -22,10 +22,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#ifndef PCI_DEVICE_H
|
||||
#define PCI_DEVICE_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
#include "mmiodevice.h"
|
||||
#include "pcihost.h"
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
|
||||
/* convert little-endian DWORD to big-endian DWORD */
|
||||
#define LE2BE(x) (x >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | (x << 24)
|
||||
|
@ -45,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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
56
main.cpp
56
main.cpp
|
@ -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;
|
||||
|
|
|
@ -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) */
|
||||
|
|
Loading…
Reference in New Issue