clang-format everything

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

78
.clang-format Normal file
View File

@ -0,0 +1,78 @@
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: false
#AlignConsecutiveMacros: false
AlignEscapedNewlines: Right
AlignOperands: false
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
#AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
BinPackParameters: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeComma
#BreakInheritanceList: BeforeComma
BreakStringLiterals: true
ColumnLimit: 100
CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
FixNamespaceComments: true
IncludeBlocks: Preserve
IndentCaseLabels: false
IndentPPDirectives: AfterHash
IndentWidth: 4
IndentWrappedFunctionNames: true
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
PenaltyBreakAssignment: 50
PenaltyBreakBeforeFirstCallParameter: 0
PenaltyBreakComment: 100
PenaltyBreakFirstLessLess: 200
PenaltyBreakString: 100
#PenaltyBreakTemplateDeclaration: 0
PenaltyExcessCharacter: 10
PenaltyReturnTypeOnItsOwnLine: 1000
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
#SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
#SpaceBeforeCpp11BracedList: true
#SpaceBeforeCtorInitializerColon: false
#SpaceBeforeInheritanceColon: false
SpaceBeforeParens: ControlStatements
#SpaceBeforeRangeBasedForLoopColon: false
#SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 4
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
#Standard: c++17
TabWidth: 4
UseTab: Never

View File

@ -22,23 +22,22 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
// The Power-specific opcodes for the processor - ppcopcodes.cpp
// Any shared opcodes are in ppcopcodes.cpp
#include <thirdparty/loguru/loguru.hpp>
#include <iostream>
#include <array>
#include <stdio.h>
#include <stdexcept>
#include "ppcemu.h"
#include "ppcmmu.h"
#include <array>
#include <cmath>
#include <iostream>
#include <limits>
#include <stdexcept>
#include <stdio.h>
#include <thirdparty/loguru/loguru.hpp>
void power_abs() {
ppc_grab_regsda();
if (ppc_result_a == 0x80000000) {
ppc_result_d = ppc_result_a;
}
else {
} else {
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
}
ppc_store_result_regd();
@ -50,8 +49,7 @@ void power_absdot() {
if (ppc_result_a == 0x80000000) {
ppc_result_d = ppc_result_a;
}
else {
} else {
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
}
ppc_changecrf0(ppc_result_d);
@ -64,8 +62,7 @@ void power_abso() {
ppc_result_d = ppc_result_a;
ppc_state.spr[SPR::XER] |= 0x40000000;
}
else {
} else {
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
}
ppc_store_result_regd();
@ -77,8 +74,7 @@ void power_absodot() {
ppc_result_d = ppc_result_a;
ppc_state.spr[SPR::XER] |= 0x40000000;
}
else {
} else {
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
}
ppc_changecrf0(ppc_result_d);
@ -118,45 +114,45 @@ void power_clcsdot() {
void power_div() {
ppc_grab_regsdab();
ppc_result_d = (ppc_result_a | ppc_state.spr[SPR::MQ]) / ppc_result_b;
ppc_result_d = (ppc_result_a | ppc_state.spr[SPR::MQ]) / ppc_result_b;
ppc_state.spr[SPR::MQ] = (ppc_result_a | ppc_state.spr[SPR::MQ]) % ppc_result_b;
ppc_store_result_regd();
}
void power_divdot() {
ppc_result_d = (ppc_result_a | ppc_state.spr[SPR::MQ]) / ppc_result_b;
ppc_result_d = (ppc_result_a | ppc_state.spr[SPR::MQ]) / ppc_result_b;
ppc_state.spr[SPR::MQ] = (ppc_result_a | ppc_state.spr[SPR::MQ]) % ppc_result_b;
}
void power_divo() {
ppc_result_d = (ppc_result_a | ppc_state.spr[SPR::MQ]) / ppc_result_b;
ppc_result_d = (ppc_result_a | ppc_state.spr[SPR::MQ]) / ppc_result_b;
ppc_state.spr[SPR::MQ] = (ppc_result_a | ppc_state.spr[SPR::MQ]) % ppc_result_b;
}
void power_divodot() {
ppc_result_d = (ppc_result_a | ppc_state.spr[SPR::MQ]) / ppc_result_b;
ppc_result_d = (ppc_result_a | ppc_state.spr[SPR::MQ]) / ppc_result_b;
ppc_state.spr[SPR::MQ] = (ppc_result_a | ppc_state.spr[SPR::MQ]) % ppc_result_b;
}
void power_divs() {
ppc_grab_regsdab();
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.spr[SPR::MQ] = (ppc_result_a % ppc_result_b);
ppc_store_result_regd();
}
void power_divsdot() {
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.spr[SPR::MQ] = (ppc_result_a % ppc_result_b);
}
void power_divso() {
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.spr[SPR::MQ] = (ppc_result_a % ppc_result_b);
}
void power_divsodot() {
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.spr[SPR::MQ] = (ppc_result_a % ppc_result_b);
}
@ -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();
@ -215,7 +206,7 @@ void power_dozi() {
void power_lscbx() {
ppc_grab_regsdab();
uint32_t bytes_copied = 0;
bool match_found = false;
bool match_found = false;
uint32_t shift_amount = 0;
uint8_t return_value;
uint8_t byte_compared = (uint8_t)((ppc_state.spr[SPR::XER] & 0xFF00) >> 8);
@ -223,7 +214,7 @@ void power_lscbx() {
return;
}
uint32_t bytes_to_load = (ppc_state.spr[SPR::XER] & 0x7f) + 1;
ppc_effective_address = (reg_a == 0) ? ppc_result_b : ppc_result_a + ppc_result_b;
ppc_effective_address = (reg_a == 0) ? ppc_result_b : ppc_result_a + ppc_result_b;
do {
ppc_effective_address++;
bytes_to_load--;
@ -259,9 +250,8 @@ void power_lscbx() {
if (shift_amount == 3) {
shift_amount = 0;
reg_d = (reg_d + 1) & 0x1F;
}
else {
reg_d = (reg_d + 1) & 0x1F;
} else {
shift_amount++;
}
} while (bytes_to_load > 0);
@ -275,19 +265,17 @@ void power_lscbxdot() {
void power_maskg() {
ppc_grab_regssab();
uint32_t mask_start = ppc_result_d & 31;
uint32_t mask_end = ppc_result_b & 31;
uint32_t mask_start = ppc_result_d & 31;
uint32_t mask_end = ppc_result_b & 31;
uint32_t insert_mask = 0;
if (mask_start < (mask_end + 1)) {
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));
@ -300,19 +288,17 @@ void power_maskg() {
void power_maskgdot() {
ppc_grab_regssab();
uint32_t mask_start = ppc_result_d & 31;
uint32_t mask_end = ppc_result_b & 31;
uint32_t mask_start = ppc_result_d & 31;
uint32_t mask_end = ppc_result_b & 31;
uint32_t insert_mask = 0;
if (mask_start < (mask_end + 1)) {
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));
@ -326,7 +312,7 @@ void power_maskgdot() {
void power_maskir() {
ppc_grab_regssab();
uint32_t mask_insert = ppc_result_a;
uint32_t insert_rot = 0x80000000;
uint32_t insert_rot = 0x80000000;
do {
if (ppc_result_b & insert_rot) {
mask_insert &= ~insert_rot;
@ -342,7 +328,7 @@ void power_maskir() {
void power_maskirdot() {
ppc_grab_regssab();
uint32_t mask_insert = ppc_result_a;
uint32_t insert_rot = 0x80000000;
uint32_t insert_rot = 0x80000000;
do {
if (ppc_result_b & insert_rot) {
mask_insert &= ~insert_rot;
@ -360,41 +346,37 @@ void power_mul() {
ppc_grab_regsdab();
uint64_t product;
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
ppc_result_d = ((uint32_t)(product >> 32));
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));
ppc_store_result_regd();
}
void power_muldot() {
ppc_grab_regsdab();
uint64_t product;
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
ppc_result_d = ((uint32_t)(product >> 32));
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));
ppc_changecrf0(ppc_result_d);
ppc_store_result_regd();
}
void power_mulo() {
uint64_t product;
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
ppc_result_d = ((uint32_t)(product >> 32));
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() {
uint64_t product;
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
ppc_result_d = ((uint32_t)(product >> 32));
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() {
@ -417,20 +399,18 @@ void power_nabsodot() {
void power_rlmi() {
ppc_grab_regssab();
unsigned rot_mb = (ppc_cur_instruction >> 6) & 31;
unsigned rot_me = (ppc_cur_instruction >> 1) & 31;
uint32_t rot_amt = ppc_result_b & 31;
unsigned rot_mb = (ppc_cur_instruction >> 6) & 31;
unsigned rot_me = (ppc_cur_instruction >> 1) & 31;
uint32_t rot_amt = ppc_result_b & 31;
uint32_t insert_mask = 0;
if (rot_mb < (rot_me + 1)) {
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));
@ -438,7 +418,7 @@ void power_rlmi() {
}
uint32_t step2 = (ppc_result_d << rot_amt) | (ppc_result_d >> rot_amt);
ppc_result_a = step2 & insert_mask;
ppc_result_a = step2 & insert_mask;
ppc_store_result_rega();
}
@ -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);
@ -468,26 +446,26 @@ void power_rribdot() {
void power_sle() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_final = ((ppc_result_d << rot_amt) | (ppc_result_d >> (32 - rot_amt)));
uint32_t insert_final = ((ppc_result_d << rot_amt) | (ppc_result_d >> (32 - rot_amt)));
ppc_state.spr[SPR::MQ] = insert_final & insert_mask;
ppc_result_a = insert_final & insert_mask;
ppc_result_a = insert_final & insert_mask;
ppc_store_result_rega();
}
void power_sledot() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_final = ((ppc_result_d << rot_amt) | (ppc_result_d >> (32 - rot_amt)));
uint32_t insert_final = ((ppc_result_d << rot_amt) | (ppc_result_d >> (32 - rot_amt)));
ppc_state.spr[SPR::MQ] = insert_final & insert_mask;
ppc_result_a = insert_final & insert_mask;
ppc_result_a = insert_final & insert_mask;
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
@ -495,12 +473,12 @@ void power_sledot() {
void power_sleq() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start = ((ppc_result_d << rot_amt) | (ppc_result_d >> (rot_amt - 31)));
uint32_t insert_end = ppc_state.spr[SPR::MQ];
uint32_t insert_end = ppc_state.spr[SPR::MQ];
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
@ -509,7 +487,7 @@ void power_sleq() {
}
}
ppc_result_a = insert_end;
ppc_result_a = insert_end;
ppc_state.spr[SPR::MQ] = insert_start;
ppc_store_result_rega();
}
@ -517,12 +495,12 @@ void power_sleq() {
void power_sleqdot() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start = ((ppc_result_d << rot_amt) | (ppc_result_d >> (rot_amt - 31)));
uint32_t insert_end = ppc_state.spr[SPR::MQ];
uint32_t insert_end = ppc_state.spr[SPR::MQ];
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
@ -531,7 +509,7 @@ void power_sleqdot() {
}
}
ppc_result_a = insert_end;
ppc_result_a = insert_end;
ppc_state.spr[SPR::MQ] = insert_start;
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
@ -540,12 +518,12 @@ void power_sleqdot() {
void power_sliq() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start = ((ppc_result_d << rot_sh) | (ppc_result_d >> (rot_sh - 31)));
uint32_t insert_end = ppc_state.spr[SPR::MQ];
uint32_t insert_end = ppc_state.spr[SPR::MQ];
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
@ -554,7 +532,7 @@ void power_sliq() {
}
}
ppc_result_a = insert_end & insert_mask;
ppc_result_a = insert_end & insert_mask;
ppc_state.spr[SPR::MQ] = insert_start;
ppc_store_result_rega();
}
@ -562,12 +540,12 @@ void power_sliq() {
void power_sliqdot() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start = ((ppc_result_d << rot_sh) | (ppc_result_d >> (rot_sh - 31)));
uint32_t insert_end = ppc_state.spr[SPR::MQ];
uint32_t insert_end = ppc_state.spr[SPR::MQ];
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
@ -576,7 +554,7 @@ void power_sliqdot() {
}
}
ppc_result_a = insert_end & insert_mask;
ppc_result_a = insert_end & insert_mask;
ppc_state.spr[SPR::MQ] = insert_start;
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
@ -585,12 +563,12 @@ void power_sliqdot() {
void power_slliq() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
uint32_t insert_end = ppc_state.spr[SPR::MQ];
uint32_t insert_end = ppc_state.spr[SPR::MQ];
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
@ -599,7 +577,7 @@ void power_slliq() {
}
}
ppc_result_a = insert_end;
ppc_result_a = insert_end;
ppc_state.spr[SPR::MQ] = insert_start;
ppc_store_result_rega();
}
@ -607,12 +585,12 @@ void power_slliq() {
void power_slliqdot() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
uint32_t insert_end = ppc_state.spr[SPR::MQ];
uint32_t insert_end = ppc_state.spr[SPR::MQ];
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
@ -621,7 +599,7 @@ void power_slliqdot() {
}
}
ppc_result_a = insert_end;
ppc_result_a = insert_end;
ppc_state.spr[SPR::MQ] = insert_start;
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
@ -662,26 +640,26 @@ void power_sraqdot() {
void power_sre() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_final = ((ppc_result_d >> rot_amt) | (ppc_result_d << (32 - rot_amt)));
uint32_t insert_final = ((ppc_result_d >> rot_amt) | (ppc_result_d << (32 - rot_amt)));
ppc_state.spr[SPR::MQ] = insert_final & insert_mask;
ppc_result_a = insert_final;
ppc_result_a = insert_final;
ppc_store_result_rega();
}
void power_sredot() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_final = ((ppc_result_d >> rot_amt) | (ppc_result_d << (32 - rot_amt)));
uint32_t insert_final = ((ppc_result_d >> rot_amt) | (ppc_result_d << (32 - rot_amt)));
ppc_state.spr[SPR::MQ] = insert_final & insert_mask;
ppc_result_a = insert_final;
ppc_result_a = insert_final;
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
@ -697,12 +675,12 @@ void power_sreadot() {
void power_sreq() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = ppc_result_b & 31;
unsigned rot_sh = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start = ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_end = ppc_state.spr[SPR::MQ];
uint32_t insert_end = ppc_state.spr[SPR::MQ];
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
@ -711,7 +689,7 @@ void power_sreq() {
}
}
ppc_result_a = insert_end;
ppc_result_a = insert_end;
ppc_state.spr[SPR::MQ] = insert_start;
ppc_store_result_rega();
}
@ -719,12 +697,12 @@ void power_sreq() {
void power_sreqdot() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = ppc_result_b & 31;
unsigned rot_sh = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start = ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_end = ppc_state.spr[SPR::MQ];
uint32_t insert_end = ppc_state.spr[SPR::MQ];
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
@ -733,7 +711,7 @@ void power_sreqdot() {
}
}
ppc_result_a = insert_end;
ppc_result_a = insert_end;
ppc_state.spr[SPR::MQ] = insert_start;
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
@ -742,12 +720,12 @@ void power_sreqdot() {
void power_sriq() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start = ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_end = ppc_state.spr[SPR::MQ];
uint32_t insert_end = ppc_state.spr[SPR::MQ];
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
@ -756,7 +734,7 @@ void power_sriq() {
}
}
ppc_result_a = insert_end;
ppc_result_a = insert_end;
ppc_state.spr[SPR::MQ] = insert_start;
ppc_store_result_rega();
}
@ -764,12 +742,12 @@ void power_sriq() {
void power_sriqdot() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start = ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_end = ppc_state.spr[SPR::MQ];
uint32_t insert_end = ppc_state.spr[SPR::MQ];
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
@ -778,7 +756,7 @@ void power_sriqdot() {
}
}
ppc_result_a = insert_end;
ppc_result_a = insert_end;
ppc_state.spr[SPR::MQ] = insert_start;
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();

File diff suppressed because it is too large Load Diff

View File

@ -26,17 +26,17 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <string>
typedef struct PPCDisasmContext {
uint32_t instr_addr;
uint32_t instr_code;
uint32_t instr_addr;
uint32_t instr_code;
std::string instr_str;
bool simplified; /* true if we should output simplified mnemonics */
bool simplified; /* true if we should output simplified mnemonics */
} PPCDisasmContext;
std::string disassemble_single(PPCDisasmContext *ctx);
std::string disassemble_single(PPCDisasmContext* ctx);
int test_ppc_disasm(void);
/** sign-extend an integer. */
#define SIGNEXT(x, sb) ((x) | (((x) & (1 << (sb))) ? ~((1 << (sb))-1) : 0))
#define SIGNEXT(x, sb) ((x) | (((x) & (1 << (sb))) ? ~((1 << (sb)) - 1) : 0))
#endif /* PPCDISASM_H */

View File

@ -22,22 +22,22 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#ifndef PPCEMU_H
#define PPCEMU_H
#include <cinttypes>
#include <string>
#include <setjmp.h>
#include "endianswap.h"
#include "devices/memctrlbase.h"
#include "endianswap.h"
#include <cinttypes>
#include <setjmp.h>
#include <string>
//Uncomment this to help debug the emulator further
// Uncomment this to help debug the emulator further
//#define EXHAUSTIVE_DEBUG 1
//Uncomment this to have a more graceful approach to illegal opcodes
// Uncomment this to have a more graceful approach to illegal opcodes
//#define ILLEGAL_OP_SAFE 1
//Uncomment this to use GCC built-in functions.
// Uncomment this to use GCC built-in functions.
//#define USE_GCC_BUILTINS 1
//Uncomment this to use Visual Studio built-in functions.
// Uncomment this to use Visual Studio built-in functions.
//#define USE_VS_BUILTINS 1
enum endian_switch { big_end = 0, little_end = 1 };
@ -45,8 +45,8 @@ enum endian_switch { big_end = 0, little_end = 1 };
typedef void (*PPCOpcode)(void);
union FPR_storage {
double dbl64_r; // double floating-point representation
uint64_t int64_r; // double integer representation
double dbl64_r; // double floating-point representation
uint64_t int64_r; // double integer representation
};
/**
@ -65,7 +65,7 @@ fpscr = FP Status and Condition Register
typedef struct struct_ppc_state {
FPR_storage fpr[32];
uint32_t pc; //Referred as the CIA in the PPC manual
uint32_t pc; // Referred as the CIA in the PPC manual
uint32_t gpr[32];
uint32_t cr;
uint32_t fpscr;
@ -73,7 +73,7 @@ typedef struct struct_ppc_state {
uint32_t spr[1024];
uint32_t msr;
uint32_t sr[16];
bool reserve; //reserve bit used for lwarx and stcwx
bool reserve; // reserve bit used for lwarx and stcwx
} SetPRS;
extern SetPRS ppc_state;
@ -94,10 +94,7 @@ enum SPR : int {
};
/** symbolic names for frequently used SPRs */
enum TBR : int {
TBL = 0,
TBU = 1
};
enum TBR : int { TBL = 0, TBU = 1 };
/** symbolic names for common PPC processors */
enum PPC_VER : uint32_t {
@ -147,10 +144,10 @@ SUPERVISOR MODEL
536 - 543 are the Data BAT registers
**/
extern uint32_t opcode_value; //used for interpreting opcodes
extern uint64_t timebase_counter; //used for storing time base value
extern uint32_t opcode_value; // used for interpreting opcodes
extern uint64_t timebase_counter; // used for storing time base value
//Additional steps to prevent overflow?
// Additional steps to prevent overflow?
extern int32_t add_result;
extern int32_t simult_result;
extern uint32_t uiadd_result;
@ -176,19 +173,19 @@ extern uint32_t rot_mb;
extern uint32_t rot_me;
extern uint32_t uimm;
extern uint32_t grab_sr;
extern uint32_t grab_inb; //This is for grabbing the number of immediate bytes for loading and storing
extern uint32_t grab_inb; // This is for grabbing the number of immediate bytes for loading and storing
extern uint32_t ppc_to;
extern int32_t simm;
extern int32_t adr_li;
extern int32_t br_bd;
//Used for GP calcs
// Used for GP calcs
extern uint32_t ppc_result_a;
extern uint32_t ppc_result_b;
extern uint32_t ppc_result_c;
extern uint32_t ppc_result_d;
//Used for FP calcs
// Used for FP calcs
extern uint64_t ppc_result64_a;
extern uint64_t ppc_result64_b;
extern uint64_t ppc_result64_c;
@ -197,7 +194,7 @@ extern uint64_t ppc_result64_d;
/* The precise end of a basic block. */
enum class BB_end_kind {
BB_NONE = 0, /* no basic block end is reached */
BB_NONE = 0, /* no basic block end is reached */
BB_BRANCH = 1, /* a branch instruction is encountered */
BB_EXCEPTION, /* an exception is occured */
BB_RFI /* the rfi instruction is encountered */
@ -215,10 +212,10 @@ enum class Except_Type {
EXC_NO_FPU,
EXC_DECR,
EXC_SYSCALL = 12,
EXC_TRACE = 13
EXC_TRACE = 13
};
//extern bool bb_end;
// extern bool bb_end;
extern BB_end_kind bb_kind;
extern jmp_buf exc_env;
@ -229,23 +226,23 @@ extern bool grab_return;
extern bool power_on;
extern bool is_601; //For PowerPC 601 Emulation
extern bool is_gekko; //For GameCube Emulation
extern bool is_altivec; //For Altivec Emulation
extern bool is_64bit; //For PowerPC G5 Emulation
extern bool is_601; // For PowerPC 601 Emulation
extern bool is_gekko; // For GameCube Emulation
extern bool is_altivec; // For Altivec Emulation
extern bool is_64bit; // For PowerPC G5 Emulation
//Important Addressing Integers
// Important Addressing Integers
extern uint32_t ppc_cur_instruction;
extern uint32_t ppc_effective_address;
extern uint32_t ppc_next_instruction_address;
//Profiling Stats
// Profiling Stats
extern uint32_t mmu_translations_num;
extern uint32_t exceptions_performed;
extern uint32_t supervisor_inst_num;
//Function prototypes
extern void ppc_cpu_init(MemCtrlBase *mem_ctrl, uint32_t proc_version);
// Function prototypes
extern void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t proc_version);
extern void ppc_mmu_init();
void ppc_illegalop();
@ -293,15 +290,13 @@ void ppc_fp_changecrf1();
void ppc_tbr_update();
/* Exception handlers. */
[[noreturn]] void ppc_exception_handler(Except_Type exception_type,
uint32_t srr1_bits);
[[noreturn]] void dbg_exception_handler(Except_Type exception_type,
uint32_t srr1_bits);
[[noreturn]] void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits);
[[noreturn]] void dbg_exception_handler(Except_Type exception_type, uint32_t srr1_bits);
//MEMORY DECLARATIONS
// MEMORY DECLARATIONS
extern MemCtrlBase* mem_ctrl_instance;
//The functions used by the PowerPC processor
// The functions used by the PowerPC processor
extern void ppc_bcctr();
extern void ppc_bcctrl();
extern void ppc_bclr();
@ -599,7 +594,7 @@ extern void ppc_fsqrtsdot();
extern void ppc_fcmpo();
extern void ppc_fcmpu();
//Power-specific instructions
// Power-specific instructions
extern void power_abs();
extern void power_absdot();
extern void power_abso();
@ -667,17 +662,17 @@ extern void power_srlqdot();
extern void power_srq();
extern void power_srqdot();
//Gekko instructions
// Gekko instructions
extern void ppc_psq_l();
extern void ppc_psq_lu();
extern void ppc_psq_st();
extern void ppc_psq_stu();
//AltiVec instructions
// AltiVec instructions
//64-bit instructions
// 64-bit instructions
//G5+ instructions
// G5+ instructions
extern void ppc_main_opcode(void);
extern void ppc_exec(void);
@ -685,9 +680,9 @@ extern void ppc_exec_single(void);
extern void ppc_exec_until(uint32_t goal_addr);
/* debugging support API */
void print_gprs(void); /* print content of the general purpose registers */
void print_fprs(void); /* print content of the floating-point registers */
uint64_t get_reg(std::string &reg_name); /* get content of the register reg_name */
void set_reg(std::string &reg_name, uint64_t val); /* set reg_name to val */
void print_gprs(void); /* print content of the general purpose registers */
void print_fprs(void); /* print content of the floating-point registers */
uint64_t get_reg(std::string& reg_name); /* get content of the register reg_name */
void set_reg(std::string& reg_name, uint64_t val); /* set reg_name to val */
#endif /* PPCEMU_H */

View File

@ -21,92 +21,89 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
/** @file Handling of low-level PPC exceptions. */
#include <setjmp.h>
#include <string>
#include <stdexcept>
#include "ppcemu.h"
#include <setjmp.h>
#include <stdexcept>
#include <string>
jmp_buf exc_env; /* Global exception environment. */
[[noreturn]] void ppc_exception_handler(Except_Type exception_type,
uint32_t srr1_bits)
{
[[noreturn]] void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits) {
grab_exception = true;
#ifdef PROFILER
#ifdef PROFILER
exceptions_performed++;
#endif
#endif
bb_kind = BB_end_kind::BB_EXCEPTION;
switch(exception_type) {
case Except_Type::EXC_SYSTEM_RESET:
ppc_state.spr[SPR::SRR0] = ppc_state.pc & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0100;
break;
switch (exception_type) {
case Except_Type::EXC_SYSTEM_RESET:
ppc_state.spr[SPR::SRR0] = ppc_state.pc & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0100;
break;
case Except_Type::EXC_MACHINE_CHECK:
if (!(ppc_state.msr & 0x1000)) {
/* TODO: handle internal checkstop */
}
ppc_state.spr[SPR::SRR0] = ppc_state.pc & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0200;
break;
case Except_Type::EXC_MACHINE_CHECK:
if (!(ppc_state.msr & 0x1000)) {
/* TODO: handle internal checkstop */
}
ppc_state.spr[SPR::SRR0] = ppc_state.pc & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0200;
break;
case Except_Type::EXC_DSI:
ppc_state.spr[SPR::SRR0] = ppc_state.pc & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0300;
break;
case Except_Type::EXC_DSI:
ppc_state.spr[SPR::SRR0] = ppc_state.pc & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0300;
break;
case Except_Type::EXC_ISI:
ppc_state.spr[SPR::SRR0] = ppc_next_instruction_address;
ppc_next_instruction_address = 0x0400;
break;
case Except_Type::EXC_ISI:
ppc_state.spr[SPR::SRR0] = ppc_next_instruction_address;
ppc_next_instruction_address = 0x0400;
break;
case Except_Type::EXC_EXT_INT:
ppc_state.spr[SPR::SRR0] = ppc_next_instruction_address;
ppc_next_instruction_address = 0x0500;
break;
case Except_Type::EXC_EXT_INT:
ppc_state.spr[SPR::SRR0] = ppc_next_instruction_address;
ppc_next_instruction_address = 0x0500;
break;
case Except_Type::EXC_ALIGNMENT:
ppc_state.spr[SPR::SRR0] = ppc_state.pc & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0600;
break;
case Except_Type::EXC_ALIGNMENT:
ppc_state.spr[SPR::SRR0] = ppc_state.pc & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0600;
break;
case Except_Type::EXC_PROGRAM:
ppc_state.spr[SPR::SRR0] = ppc_state.pc & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0700;
break;
case Except_Type::EXC_PROGRAM:
ppc_state.spr[SPR::SRR0] = ppc_state.pc & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0700;
break;
case Except_Type::EXC_NO_FPU:
ppc_state.spr[SPR::SRR0] = ppc_state.pc & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0800;
break;
case Except_Type::EXC_NO_FPU:
ppc_state.spr[SPR::SRR0] = ppc_state.pc & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0800;
break;
case Except_Type::EXC_DECR:
ppc_state.spr[SPR::SRR0] = (ppc_state.pc & 0xFFFFFFFC) + 4;
ppc_next_instruction_address = 0x0900;
break;
case Except_Type::EXC_DECR:
ppc_state.spr[SPR::SRR0] = (ppc_state.pc & 0xFFFFFFFC) + 4;
ppc_next_instruction_address = 0x0900;
break;
case Except_Type::EXC_SYSCALL:
ppc_state.spr[SPR::SRR0] = (ppc_state.pc & 0xFFFFFFFC) + 4;
ppc_next_instruction_address = 0x0C00;
break;
case Except_Type::EXC_SYSCALL:
ppc_state.spr[SPR::SRR0] = (ppc_state.pc & 0xFFFFFFFC) + 4;
ppc_next_instruction_address = 0x0C00;
break;
case Except_Type::EXC_TRACE:
ppc_state.spr[SPR::SRR0] = (ppc_state.pc & 0xFFFFFFFC) + 4;
ppc_next_instruction_address = 0x0D00;
break;
case Except_Type::EXC_TRACE:
ppc_state.spr[SPR::SRR0] = (ppc_state.pc & 0xFFFFFFFC) + 4;
ppc_next_instruction_address = 0x0D00;
break;
default:
//printf("Unknown exception occured: %X\n", exception_type);
//exit(-1);
break;
default:
// printf("Unknown exception occured: %X\n", exception_type);
// exit(-1);
break;
}
ppc_state.spr[SPR::SRR1] = (ppc_state.msr & 0x0000FF73) | srr1_bits;
ppc_state.msr &= 0xFFFB1041;
/* copy MSR[ILE] to MSR[LE] */
ppc_state.msr = (ppc_state.msr & 0xFFFFFFFE) |
((ppc_state.msr >> 16) & 1);
ppc_state.msr = (ppc_state.msr & 0xFFFFFFFE) | ((ppc_state.msr >> 16) & 1);
if (ppc_state.msr & 0x40) {
ppc_next_instruction_address |= 0xFFF00000;
@ -116,61 +113,59 @@ 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) {
case Except_Type::EXC_SYSTEM_RESET:
exc_descriptor = "System reset exception occured";
break;
switch (exception_type) {
case Except_Type::EXC_SYSTEM_RESET:
exc_descriptor = "System reset exception occured";
break;
case Except_Type::EXC_MACHINE_CHECK:
exc_descriptor = "Machine check exception occured";
break;
case Except_Type::EXC_MACHINE_CHECK:
exc_descriptor = "Machine check exception occured";
break;
case Except_Type::EXC_DSI:
case Except_Type::EXC_ISI:
if (ppc_state.spr[SPR::DSISR] & 0x40000000)
exc_descriptor = "DSI/ISI exception: unmapped memory access";
else if (ppc_state.spr[SPR::DSISR] & 0x08000000)
exc_descriptor = "DSI/ISI exception: access protection violation";
else {
if (exception_type == Except_Type::EXC_DSI)
exc_descriptor = "DSI exception";
else
exc_descriptor = "ISI exception";
}
break;
case Except_Type::EXC_DSI:
case Except_Type::EXC_ISI:
if (ppc_state.spr[SPR::DSISR] & 0x40000000)
exc_descriptor = "DSI/ISI exception: unmapped memory access";
else if (ppc_state.spr[SPR::DSISR] & 0x08000000)
exc_descriptor = "DSI/ISI exception: access protection violation";
else {
if (exception_type == Except_Type::EXC_DSI)
exc_descriptor = "DSI exception";
else
exc_descriptor = "ISI exception";
}
break;
case Except_Type::EXC_EXT_INT:
exc_descriptor = "External interrupt exception occured";
break;
case Except_Type::EXC_EXT_INT:
exc_descriptor = "External interrupt exception occured";
break;
case Except_Type::EXC_ALIGNMENT:
exc_descriptor = "Alignment exception occured";
break;
case Except_Type::EXC_ALIGNMENT:
exc_descriptor = "Alignment exception occured";
break;
case Except_Type::EXC_PROGRAM:
exc_descriptor = "Program exception occured";
break;
case Except_Type::EXC_PROGRAM:
exc_descriptor = "Program exception occured";
break;
case Except_Type::EXC_NO_FPU:
exc_descriptor = "Floating-Point unavailable exception occured";
break;
case Except_Type::EXC_NO_FPU:
exc_descriptor = "Floating-Point unavailable exception occured";
break;
case Except_Type::EXC_DECR:
exc_descriptor = "Decrementer exception occured";
break;
case Except_Type::EXC_DECR:
exc_descriptor = "Decrementer exception occured";
break;
case Except_Type::EXC_SYSCALL:
exc_descriptor = "Syscall exception occured";
break;
case Except_Type::EXC_SYSCALL:
exc_descriptor = "Syscall exception occured";
break;
case Except_Type::EXC_TRACE:
exc_descriptor = "Trace exception occured";
break;
case Except_Type::EXC_TRACE:
exc_descriptor = "Trace exception occured";
break;
}
throw std::invalid_argument(exc_descriptor);

File diff suppressed because it is too large Load Diff

View File

@ -21,20 +21,20 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
// The opcodes for the processor - ppcopcodes.cpp
#include <iostream>
#include <map>
#include <unordered_map>
#include <cinttypes>
#include <array>
#include <stdio.h>
#include <stdexcept>
#include "ppcemu.h"
#include "ppcmmu.h"
#include <array>
#include <cfenv>
#include <cinttypes>
#include <cmath>
#include <iostream>
#include <limits>
#include <map>
#include <stdexcept>
#include <stdio.h>
#include <unordered_map>
//Used for FP calcs
// Used for FP calcs
uint64_t ppc_result64_a;
uint64_t ppc_result64_b;
uint64_t ppc_result64_c;
@ -48,7 +48,7 @@ double ppc_dblresult64_d;
double snan = std::numeric_limits<double>::signaling_NaN();
double qnan = std::numeric_limits<double>::quiet_NaN();
//Storage and register retrieval functions for the floating point functions.
// Storage and register retrieval functions for the floating point functions.
double fp_return_double(uint32_t reg) {
return ppc_state.fpr[reg].dbl64_r;
@ -62,8 +62,7 @@ void ppc_store_sfpresult(bool int_rep) {
if (int_rep) {
ppc_state.fpr[reg_d].int64_r = ppc_result64_d;
ppc_state.fpr[reg_d].dbl64_r = *(double*)&ppc_result64_d;
}
else {
} else {
ppc_state.fpr[reg_d].dbl64_r = ppc_dblresult64_d;
ppc_state.fpr[reg_d].int64_r = *(uint64_t*)&ppc_dblresult64_d;
}
@ -73,8 +72,7 @@ void ppc_store_dfpresult(bool int_rep) {
if (int_rep) {
ppc_state.fpr[reg_d].int64_r = ppc_result64_d;
ppc_state.fpr[reg_d].dbl64_r = *(double*)&ppc_result64_d;
}
else {
} else {
ppc_state.fpr[reg_d].dbl64_r = ppc_dblresult64_d;
ppc_state.fpr[reg_d].int64_r = *(uint64_t*)&ppc_dblresult64_d;
}
@ -85,8 +83,7 @@ void ppc_grab_regsfpdb(bool int_rep) {
reg_b = (ppc_cur_instruction >> 11) & 31;
if (int_rep) {
ppc_result64_b = ppc_state.fpr[reg_b].int64_r;
}
else {
} else {
ppc_dblresult64_b = ppc_state.fpr[reg_b].dbl64_r;
}
}
@ -96,32 +93,31 @@ 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];
}
void ppc_grab_regsfpdia(bool int_rep) {
reg_d = (ppc_cur_instruction >> 21) & 31;
reg_a = (ppc_cur_instruction >> 16) & 31;
reg_d = (ppc_cur_instruction >> 21) & 31;
reg_a = (ppc_cur_instruction >> 16) & 31;
ppc_result_a = ppc_state.gpr[reg_a];
}
void ppc_grab_regsfpsia(bool int_rep) {
reg_s = (ppc_cur_instruction >> 21) & 31;
reg_a = (ppc_cur_instruction >> 16) & 31;
reg_s = (ppc_cur_instruction >> 21) & 31;
reg_a = (ppc_cur_instruction >> 16) & 31;
ppc_result_d = ppc_state.gpr[reg_s];
ppc_result_a = ppc_state.gpr[reg_a];
}
void ppc_grab_regsfpsiab(bool int_rep) {
reg_s = (ppc_cur_instruction >> 21) & 31;
reg_a = (ppc_cur_instruction >> 16) & 31;
reg_b = (ppc_cur_instruction >> 11) & 31;
reg_s = (ppc_cur_instruction >> 21) & 31;
reg_a = (ppc_cur_instruction >> 16) & 31;
reg_b = (ppc_cur_instruction >> 11) & 31;
ppc_result64_d = ppc_state.fpr[reg_s].int64_r;
ppc_result_a = ppc_state.gpr[reg_a];
ppc_result_b = ppc_state.gpr[reg_b];
ppc_result_a = ppc_state.gpr[reg_a];
ppc_result_b = ppc_state.gpr[reg_b];
}
void ppc_grab_regsfpsab(bool int_rep) {
@ -132,8 +128,7 @@ void ppc_grab_regsfpsab(bool int_rep) {
ppc_result64_d = ppc_state.fpr[reg_s].int64_r;
ppc_result64_a = ppc_state.fpr[reg_a].int64_r;
ppc_result64_b = ppc_state.fpr[reg_b].int64_r;
}
else {
} else {
ppc_dblresult64_d = fp_return_double(reg_s);
ppc_dblresult64_a = fp_return_double(reg_a);
ppc_dblresult64_c = fp_return_double(reg_c);
@ -147,8 +142,7 @@ void ppc_grab_regsfpdab(bool int_rep) {
if (int_rep) {
ppc_result64_a = fp_return_uint64(reg_a);
ppc_result64_b = fp_return_uint64(reg_b);
}
else {
} else {
ppc_dblresult64_a = fp_return_double(reg_a);
ppc_dblresult64_b = fp_return_double(reg_b);
}
@ -161,8 +155,7 @@ void ppc_grab_regsfpdac(bool int_rep) {
if (int_rep) {
ppc_result64_a = fp_return_uint64(reg_a);
ppc_result64_c = fp_return_uint64(reg_c);
}
else {
} else {
ppc_dblresult64_a = fp_return_double(reg_a);
ppc_dblresult64_c = fp_return_double(reg_c);
}
@ -177,8 +170,7 @@ void ppc_grab_regsfpdabc(bool int_rep) {
ppc_result64_a = fp_return_uint64(reg_a);
ppc_result64_b = fp_return_uint64(reg_b);
ppc_result64_c = fp_return_uint64(reg_c);
}
else {
} else {
ppc_dblresult64_a = fp_return_double(reg_a);
ppc_dblresult64_b = fp_return_double(reg_b);
ppc_dblresult64_c = fp_return_double(reg_c);
@ -203,7 +195,6 @@ void fp_save_uint64(uint64_t entry) {
void fp_save_uint32(uint32_t entry) {
ppc_state.fpr[reg_d].int64_r = entry;
ppc_state.fpr[reg_d].dbl64_r = (double)entry;
}
void ppc_fp_changecrf1() {
@ -222,8 +213,7 @@ void ppc_divbyzero(uint64_t input_a, uint64_t input_b, bool is_single) {
int64_t round_to_nearest(double f) {
if (f >= 0.0) {
return (int32_t)(int64_t)(f + 0.5);
}
else {
} else {
return (int32_t)(-(int64_t)(-f + 0.5));
}
}
@ -265,8 +255,7 @@ bool ppc_confirm_inf_nan(uint32_t chosen_reg_1, uint32_t chosen_reg_2, bool is_s
ppc_state.fpscr |= 0x80400000;
ppc_toggle_fpscr_fex();
return true;
}
else if ((input_a == 0) & (input_b == 0)) {
} else if ((input_a == 0) & (input_b == 0)) {
ppc_state.fpscr |= 0x80200000;
ppc_toggle_fpscr_fex();
return true;
@ -297,8 +286,7 @@ bool ppc_confirm_inf_nan(uint32_t chosen_reg_1, uint32_t chosen_reg_2, bool is_s
default:
return false;
}
}
else {
} else {
uint32_t exp_a = (input_a >> 52) & 0x7ff;
uint32_t exp_b = (input_b >> 52) & 0x7ff;
@ -310,8 +298,7 @@ bool ppc_confirm_inf_nan(uint32_t chosen_reg_1, uint32_t chosen_reg_2, bool is_s
ppc_state.fpscr |= 0x80400000;
ppc_toggle_fpscr_fex();
return true;
}
else if ((input_a == 0) & (input_b == 0)) {
} else if ((input_a == 0) & (input_b == 0)) {
ppc_state.fpscr |= 0x80200000;
ppc_toggle_fpscr_fex();
return true;
@ -348,7 +335,6 @@ bool ppc_confirm_inf_nan(uint32_t chosen_reg_1, uint32_t chosen_reg_2, bool is_s
}
void fpresult_update(uint64_t set_result, bool confirm_arc) {
bool confirm_ov = (bool)std::fetestexcept(FE_OVERFLOW);
if (confirm_ov) {
@ -362,15 +348,12 @@ void fpresult_update(uint64_t set_result, bool confirm_arc) {
if (set_result == 0) {
ppc_state.fpscr |= 0x2000;
}
else {
} else {
if (set_result < 0) {
ppc_state.fpscr |= 0x8000;
}
else if (set_result > 0) {
} else if (set_result > 0) {
ppc_state.fpscr |= 0x4000;
}
else {
} else {
ppc_state.fpscr |= 0x1000;
}
}
@ -378,9 +361,7 @@ void fpresult_update(uint64_t set_result, bool confirm_arc) {
}
void ppc_frsqrte_result() {
if (ppc_result64_d & 0x007FF000000000000UL) {
}
}
@ -389,7 +370,7 @@ void ppc_changecrf1() {
ppc_state.cr |= (ppc_state.fpscr & 0xF0000000) >> 4;
}
//Floating Point Arithmetic
// Floating Point Arithmetic
void ppc_fadd() {
ppc_grab_regsfpdab(false);
@ -585,7 +566,7 @@ void ppc_fadds() {
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
float intermediate = (float)ppc_dblresult64_a + (float)ppc_dblresult64_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_store_dfpresult(false);
}
}
@ -595,7 +576,7 @@ void ppc_faddsdot() {
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
float intermediate = (float)ppc_dblresult64_a + (float)ppc_dblresult64_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_store_dfpresult(false);
}
@ -607,7 +588,7 @@ void ppc_fsubs() {
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 56)) {
float intermediate = (float)ppc_dblresult64_a - (float)ppc_dblresult64_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_store_dfpresult(false);
}
}
@ -617,7 +598,7 @@ void ppc_fsubsdot() {
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 56)) {
float intermediate = (float)ppc_dblresult64_a - (float)ppc_dblresult64_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_store_dfpresult(false);
}
@ -629,7 +610,7 @@ void ppc_fmults() {
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_dblresult64_d = static_cast<double>(intermediate);
ppc_store_dfpresult(false);
}
}
@ -638,9 +619,8 @@ 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_dblresult64_d = static_cast<double>(intermediate);
ppc_store_dfpresult(false);
}
ppc_changecrf1();
@ -651,7 +631,7 @@ void ppc_fdivs() {
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 36)) {
float intermediate = (float)ppc_dblresult64_a / (float)ppc_dblresult64_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_dblresult64_d = static_cast<double>(intermediate);
ppc_store_dfpresult(false);
}
}
@ -661,7 +641,7 @@ void ppc_fdivsdot() {
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 36)) {
float intermediate = (float)ppc_dblresult64_a / (float)ppc_dblresult64_b;
ppc_dblresult64_d = static_cast<double>(intermediate);
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;
}
@ -914,7 +888,7 @@ void ppc_fsqrts() {
test += 127 << 23;
test >>= 1;
uint64_t* pre_final = (uint64_t*)&test;
ppc_result64_d = *pre_final;
ppc_result64_d = *pre_final;
ppc_store_dfpresult(true);
}
@ -924,7 +898,7 @@ void ppc_fsqrtsdot() {
test += 127 << 23;
test >>= 1;
uint64_t* pre_final = (uint64_t*)&test;
ppc_result64_d = *pre_final;
ppc_result64_d = *pre_final;
ppc_store_dfpresult(true);
ppc_changecrf1();
}
@ -954,16 +928,16 @@ void ppc_frsqrtedot() {
void ppc_frsp() {
ppc_grab_regsfpdb(false);
double testd2 = (double)ppc_result64_b;
float testf2 = (float)testd2;
double testd2 = (double)ppc_result64_b;
float testf2 = (float)testd2;
ppc_dblresult64_d = (double)testf2;
ppc_store_dfpresult(false);
}
void ppc_frspdot() {
ppc_grab_regsfpdb(false);
double testd2 = (double)ppc_result64_b;
float testf2 = (float)testd2;
double testd2 = (double)ppc_result64_b;
float testf2 = (float)testd2;
ppc_dblresult64_d = (double)testf2;
ppc_store_dfpresult(false);
ppc_changecrf1();
@ -971,16 +945,16 @@ void ppc_frspdot() {
void ppc_fres() {
ppc_grab_regsfpdb(false);
float testf2 = (float)ppc_dblresult64_b;
testf2 = 1 / testf2;
float testf2 = (float)ppc_dblresult64_b;
testf2 = 1 / testf2;
ppc_dblresult64_d = (double)testf2;
ppc_store_dfpresult(false);
}
void ppc_fresdot() {
ppc_grab_regsfpdb(false);
float testf2 = (float)ppc_dblresult64_b;
testf2 = 1 / testf2;
float testf2 = (float)ppc_dblresult64_b;
testf2 = 1 / testf2;
ppc_dblresult64_d = (double)testf2;
ppc_store_dfpresult(false);
ppc_changecrf1();
@ -1001,7 +975,6 @@ void ppc_fctiw() {
}
ppc_store_dfpresult(true);
}
void ppc_fctiwdot() {
@ -1037,7 +1010,7 @@ void ppc_fctiwzdot() {
ppc_changecrf1();
}
//Floating Point Store and Load
// Floating Point Store and Load
void ppc_lfs() {
ppc_grab_regsfpdia(true);
@ -1054,11 +1027,10 @@ void ppc_lfsu() {
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
ppc_result64_d = mem_grab_dword(ppc_effective_address);
ppc_result_a = ppc_effective_address;
ppc_result_a = ppc_effective_address;
ppc_store_dfpresult(true);
ppc_store_result_rega();
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -1066,7 +1038,7 @@ void ppc_lfsu() {
void ppc_lfsx() {
ppc_grab_regsfpdiab(true);
ppc_effective_address = (reg_a == 0) ? ppc_result_b : ppc_result_a + ppc_result_b;
ppc_result64_d = mem_grab_dword(ppc_effective_address);
ppc_result64_d = mem_grab_dword(ppc_effective_address);
ppc_store_dfpresult(true);
}
@ -1074,12 +1046,11 @@ void ppc_lfsux() {
ppc_grab_regsfpdiab(true);
if (reg_a == 0) {
ppc_effective_address = ppc_result_a + ppc_result_b;
ppc_result64_d = mem_grab_dword(ppc_effective_address);
ppc_result_a = ppc_effective_address;
ppc_result64_d = mem_grab_dword(ppc_effective_address);
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);
}
}
@ -1118,12 +1088,11 @@ void ppc_lfdux() {
ppc_grab_regsfpdiab(true);
if (reg_a == 0) {
ppc_effective_address = ppc_result_a + ppc_result_b;
ppc_result64_d = mem_grab_qword(ppc_effective_address);
ppc_result64_d = mem_grab_qword(ppc_effective_address);
ppc_store_dfpresult(true);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -1143,8 +1112,7 @@ void ppc_stfsu() {
mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -1162,8 +1130,7 @@ void ppc_stfsux() {
mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -1183,8 +1150,7 @@ void ppc_stfdu() {
mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -1202,8 +1168,7 @@ void ppc_stfdux() {
mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
else {
} else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -1214,7 +1179,7 @@ void ppc_stfiwx() {
mem_write_dword(ppc_effective_address, (uint32_t)(ppc_state.fpr[reg_s].int64_r));
}
//Floating Point Register Transfer
// Floating Point Register Transfer
void ppc_fmr() {
ppc_grab_regsfpdb(true);
@ -1241,7 +1206,7 @@ void ppc_mffsdot() {
}
void ppc_mtfsf() {
reg_b = (ppc_cur_instruction >> 11) & 31;
reg_b = (ppc_cur_instruction >> 11) & 31;
uint32_t fm_mask = (ppc_cur_instruction >> 17) & 255;
crm += ((fm_mask & 1) == 1) ? 0xF0000000 : 0x00000000;
crm += (((fm_mask >> 1) & 1) == 1) ? 0x0F000000 : 0x00000000;
@ -1252,11 +1217,11 @@ void ppc_mtfsf() {
crm += (((fm_mask >> 6) & 1) == 1) ? 0x000000F0 : 0x00000000;
crm += (((fm_mask >> 7) & 1) == 1) ? 0x0000000F : 0x00000000;
uint32_t quickfprval = (uint32_t)ppc_state.fpr[reg_b].int64_r;
ppc_state.fpscr = (quickfprval & crm) | (quickfprval & ~(crm));
ppc_state.fpscr = (quickfprval & crm) | (quickfprval & ~(crm));
}
void ppc_mtfsfdot() {
reg_b = (ppc_cur_instruction >> 11) & 31;
reg_b = (ppc_cur_instruction >> 11) & 31;
uint32_t fm_mask = (ppc_cur_instruction >> 17) & 255;
crm += ((fm_mask & 1) == 1) ? 0xF0000000 : 0x00000000;
crm += (((fm_mask >> 1) & 1) == 1) ? 0x0F000000 : 0x00000000;
@ -1267,22 +1232,24 @@ void ppc_mtfsfdot() {
crm += (((fm_mask >> 6) & 1) == 1) ? 0x000000F0 : 0x00000000;
crm += (((fm_mask >> 7) & 1) == 1) ? 0x0000000F : 0x00000000;
uint32_t quickfprval = (uint32_t)ppc_state.fpr[reg_b].int64_r;
ppc_state.fpscr = (quickfprval & crm) | (quickfprval & ~(crm));
ppc_state.fpscr = (quickfprval & crm) | (quickfprval & ~(crm));
ppc_fp_changecrf1();
}
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_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);
}
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_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_fp_changecrf1();
}
@ -1317,14 +1284,15 @@ void ppc_mtfsb1dot() {
}
void ppc_mcrfs() {
crf_d = (ppc_cur_instruction >> 23) & 7;
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)));
crf_d = (ppc_cur_instruction >> 23) & 7;
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)));
}
//Floating Point Comparisons
// Floating Point Comparisons
void ppc_fcmpo() {
ppc_grab_regsfpsab(true);
@ -1339,14 +1307,11 @@ void ppc_fcmpo() {
if (std::isnan(db_test_a) || std::isnan(db_test_b)) {
cmp_c |= 0x01;
}
else if (db_test_a < db_test_b) {
} else if (db_test_a < db_test_b) {
cmp_c |= 0x08;
}
else if (db_test_a > db_test_b) {
} else if (db_test_a > db_test_b) {
cmp_c |= 0x04;
}
else {
} else {
cmp_c |= 0x02;
}
@ -1358,11 +1323,9 @@ void ppc_fcmpo() {
if (ppc_state.fpscr & 0x80) {
ppc_state.fpscr |= 0x80000;
}
}
else if ((db_test_a == qnan) || (db_test_b == qnan)) {
} else if ((db_test_a == qnan) || (db_test_b == qnan)) {
ppc_state.fpscr |= 0x80000;
}
}
void ppc_fcmpu() {
@ -1378,14 +1341,11 @@ void ppc_fcmpu() {
if (std::isnan(db_test_a) || std::isnan(db_test_b)) {
cmp_c |= 0x01;
}
else if (db_test_a < db_test_b) {
} else if (db_test_a < db_test_b) {
cmp_c |= 0x08;
}
else if (db_test_a > db_test_b) {
} else if (db_test_a > db_test_b) {
cmp_c |= 0x04;
}
else {
} else {
cmp_c |= 0x02;
}

View File

@ -21,26 +21,26 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
// The uniquely Gekko opcodes for the processor - ppcgekkoopcodes.cpp
#include "ppcemu.h"
#include <iostream>
#include <stdio.h>
#include "ppcemu.h"
void ppc_psq_l(){
void ppc_psq_l() {
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
exit(0);
}
void ppc_psq_lu(){
void ppc_psq_lu() {
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
exit(0);
}
void ppc_psq_st(){
void ppc_psq_st() {
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
exit(0);
}
void ppc_psq_stu(){
void ppc_psq_stu() {
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
exit(0);
}

View File

@ -28,193 +28,173 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
- clarify what to do in the case of unaligned memory accesses
*/
#include <thirdparty/loguru/loguru.hpp>
#include <iostream>
#include <cstdint>
#include <cinttypes>
#include <string>
#include <stdexcept>
#include <array>
#include "memreadwrite.h"
#include "ppcemu.h"
#include "ppcmmu.h"
#include "devices/memctrlbase.h"
#include "memreadwrite.h"
#include "ppcemu.h"
#include <array>
#include <cinttypes>
#include <cstdint>
#include <iostream>
#include <stdexcept>
#include <string>
#include <thirdparty/loguru/loguru.hpp>
/* pointer to exception handler to be called when a MMU exception is occured. */
void (*mmu_exception_handler)(Except_Type exception_type, uint32_t srr1_bits);
/** PowerPC-style MMU BAT arrays (NULL initialization isn't prescribed). */
PPC_BAT_entry ibat_array[4] = { {0} };
PPC_BAT_entry dbat_array[4] = { {0} };
PPC_BAT_entry ibat_array[4] = {{0}};
PPC_BAT_entry dbat_array[4] = {{0}};
/** remember recently used physical memory regions for quicker translation. */
AddressMapEntry last_read_area = { 0 };
AddressMapEntry last_write_area = { 0 };
AddressMapEntry last_exec_area = { 0 };
AddressMapEntry last_ptab_area = { 0 };
AddressMapEntry last_dma_area = { 0 };
AddressMapEntry last_read_area = {0};
AddressMapEntry last_write_area = {0};
AddressMapEntry last_exec_area = {0};
AddressMapEntry last_ptab_area = {0};
AddressMapEntry last_dma_area = {0};
/* macro for generating code reading from physical memory */
#define READ_PHYS_MEM(ENTRY, ADDR, OP, SIZE, UNVAL) \
{ \
if ((ADDR) >= (ENTRY).start && ((ADDR) + (SIZE)) <= (ENTRY).end) { \
ret = OP((ENTRY).mem_ptr + ((ADDR) - (ENTRY).start)); \
} else { \
AddressMapEntry* entry = mem_ctrl_instance->find_range((ADDR)); \
if (entry) { \
if (entry->type & (RT_ROM | RT_RAM)) { \
(ENTRY).start = entry->start; \
(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 { \
LOG_F(ERROR, "Please check your address map! \n"); \
ret = (UNVAL); \
} \
} \
else { \
LOG_F(WARNING, "Read from unmapped memory at 0x%08X!\n", (ADDR)); \
ret = (UNVAL); \
} \
} \
}
#define READ_PHYS_MEM(ENTRY, ADDR, OP, SIZE, UNVAL) \
{ \
if ((ADDR) >= (ENTRY).start && ((ADDR) + (SIZE)) <= (ENTRY).end) { \
ret = OP((ENTRY).mem_ptr + ((ADDR) - (ENTRY).start)); \
} else { \
AddressMapEntry* entry = mem_ctrl_instance->find_range((ADDR)); \
if (entry) { \
if (entry->type & (RT_ROM | RT_RAM)) { \
(ENTRY).start = entry->start; \
(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 { \
LOG_F(ERROR, "Please check your address map! \n"); \
ret = (UNVAL); \
} \
} else { \
LOG_F(WARNING, "Read from unmapped memory at 0x%08X!\n", (ADDR)); \
ret = (UNVAL); \
} \
} \
}
/* macro for generating code writing to physical memory */
#define WRITE_PHYS_MEM(ENTRY, ADDR, OP, VAL, SIZE) \
{ \
if ((ADDR) >= (ENTRY).start && ((ADDR) + (SIZE)) <= (ENTRY).end) { \
OP((ENTRY).mem_ptr + ((ADDR) - (ENTRY).start), (VAL)); \
} else { \
AddressMapEntry* entry = mem_ctrl_instance->find_range((ADDR)); \
if (entry) { \
if (entry->type & RT_RAM) { \
(ENTRY).start = entry->start; \
(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 { \
LOG_F(ERROR, "Please check your address map!\n"); \
} \
} \
else { \
LOG_F(WARNING, "Write to unmapped memory at 0x%08X!\n", (ADDR)); \
} \
} \
}
#define WRITE_PHYS_MEM(ENTRY, ADDR, OP, VAL, SIZE) \
{ \
if ((ADDR) >= (ENTRY).start && ((ADDR) + (SIZE)) <= (ENTRY).end) { \
OP((ENTRY).mem_ptr + ((ADDR) - (ENTRY).start), (VAL)); \
} else { \
AddressMapEntry* entry = mem_ctrl_instance->find_range((ADDR)); \
if (entry) { \
if (entry->type & RT_RAM) { \
(ENTRY).start = entry->start; \
(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 { \
LOG_F(ERROR, "Please check your address map!\n"); \
} \
} 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!
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;
upper_reg_num = bat_reg & 0xFFFFFFFE;
if (ppc_state.spr[upper_reg_num] & 3) { // is that BAT pair valid?
if (ppc_state.spr[upper_reg_num] & 3) { // is that BAT pair valid?
bat_entry = &ibat_array[(bat_reg - 528) >> 1];
bl = (ppc_state.spr[upper_reg_num] >> 2) & 0x7FF;
lo_mask = (bl << 17) | 0x1FFFF;
bl = (ppc_state.spr[upper_reg_num] >> 2) & 0x7FF;
lo_mask = (bl << 17) | 0x1FFFF;
bat_entry->access = ppc_state.spr[upper_reg_num] & 3;
bat_entry->prot = ppc_state.spr[upper_reg_num + 1] & 3;
bat_entry->access = ppc_state.spr[upper_reg_num] & 3;
bat_entry->prot = ppc_state.spr[upper_reg_num + 1] & 3;
bat_entry->lo_mask = lo_mask;
bat_entry->phys_hi = ppc_state.spr[upper_reg_num + 1] & ~lo_mask;
bat_entry->bepi = ppc_state.spr[upper_reg_num] & ~lo_mask;
bat_entry->bepi = ppc_state.spr[upper_reg_num] & ~lo_mask;
}
}
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;
upper_reg_num = bat_reg & 0xFFFFFFFE;
if (ppc_state.spr[upper_reg_num] & 3) { // is that BAT pair valid?
if (ppc_state.spr[upper_reg_num] & 3) { // is that BAT pair valid?
bat_entry = &dbat_array[(bat_reg - 536) >> 1];
bl = (ppc_state.spr[upper_reg_num] >> 2) & 0x7FF;
lo_mask = (bl << 17) | 0x1FFFF;
bl = (ppc_state.spr[upper_reg_num] >> 2) & 0x7FF;
lo_mask = (bl << 17) | 0x1FFFF;
bat_entry->access = ppc_state.spr[upper_reg_num] & 3;
bat_entry->prot = ppc_state.spr[upper_reg_num + 1] & 3;
bat_entry->access = ppc_state.spr[upper_reg_num] & 3;
bat_entry->prot = ppc_state.spr[upper_reg_num + 1] & 3;
bat_entry->lo_mask = lo_mask;
bat_entry->phys_hi = ppc_state.spr[upper_reg_num + 1] & ~lo_mask;
bat_entry->bepi = ppc_state.spr[upper_reg_num] & ~lo_mask;
bat_entry->bepi = ppc_state.spr[upper_reg_num] & ~lo_mask;
}
}
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!
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,11 +209,10 @@ 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;
*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;
@ -259,7 +236,7 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
sr_val = ppc_state.sr[(la >> 28) & 0x0F];
if (sr_val & 0x80000000) {
LOG_F(ERROR, "Direct-store segments not supported, LA=%0xX\n", la);
exit(-1); // FIXME: ugly error handling, must be the proper exception!
exit(-1); // FIXME: ugly error handling, must be the proper exception!
}
/* instruction fetch from a no-execute segment will cause ISI exception */
@ -269,16 +246,15 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
page_index = (la >> 12) & 0xFFFF;
pteg_hash1 = (sr_val & 0x7FFFF) ^ page_index;
vsid = sr_val & 0x0FFFFFF;
vsid = sr_val & 0x0FFFFFF;
if (!search_pteg(calc_pteg_addr(pteg_hash1), &pte_addr, vsid, page_index, 0)) {
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;
ppc_state.spr[SPR::DAR] = la;
mmu_exception_handler(Except_Type::EXC_DSI, 0);
}
}
@ -286,7 +262,7 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
pte_word2 = READ_DWORD_BE_A(pte_addr + 4);
key = (((sr_val >> 29) & 1)& msr_pr) | (((sr_val >> 30) & 1)& (msr_pr ^ 1));
key = (((sr_val >> 29) & 1) & msr_pr) | (((sr_val >> 30) & 1) & (msr_pr ^ 1));
/* check page access */
pp = pte_word2 & 3;
@ -298,10 +274,9 @@ 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;
ppc_state.spr[SPR::DAR] = la;
mmu_exception_handler(Except_Type::EXC_DSI, 0);
}
}
@ -318,11 +293,10 @@ 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;
bool bat_hit = false;
unsigned msr_pr = !!(ppc_state.msr & 0x4000);
// Format: %XY
@ -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,15 +329,14 @@ 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
uint32_t pa; /* translated physical address */
bool bat_hit = false;
bool bat_hit = false;
unsigned msr_pr = !!(ppc_state.msr & 0x4000);
// Format: %XY
@ -375,13 +347,12 @@ 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)) {
ppc_state.spr[SPR::DSISR] = 0x08000000 | (is_write << 25);
ppc_state.spr[SPR::DAR] = la;
ppc_state.spr[SPR::DAR] = la;
mmu_exception_handler(Except_Type::EXC_DSI, 0);
}
@ -399,13 +370,12 @@ static uint32_t ppc_mmu_addr_translate(uint32_t la, int is_write)
return pa;
}
static void mem_write_unaligned(uint32_t addr, uint32_t value, uint32_t size)
{
static void mem_write_unaligned(uint32_t addr, uint32_t value, uint32_t size) {
LOG_F(WARNING, "Attempt to write unaligned %d bytes to 0x%08X\n", size, addr);
if (((addr & 0xFFF) + size) > 0x1000) {
LOG_F(ERROR, "SOS! Cross-page unaligned write, addr=%08X, size=%d\n", addr, size);
exit(-1); //FIXME!
exit(-1); // FIXME!
} else {
/* data address translation if enabled */
if (ppc_state.msr & 0x10) {
@ -420,20 +390,18 @@ static void mem_write_unaligned(uint32_t addr, uint32_t value, uint32_t size)
}
}
void mem_write_byte(uint32_t addr, uint8_t value)
{
void mem_write_byte(uint32_t addr, uint8_t value) {
/* data address translation if enabled */
if (ppc_state.msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 1);
}
#define WRITE_BYTE(addr, val) (*(addr) = val)
#define WRITE_BYTE(addr, val) (*(addr) = val)
WRITE_PHYS_MEM(last_write_area, addr, WRITE_BYTE, value, 1);
}
void mem_write_word(uint32_t addr, uint16_t value)
{
void mem_write_word(uint32_t addr, uint16_t value) {
if (addr & 1) {
mem_write_unaligned(addr, value, 2);
}
@ -446,8 +414,7 @@ void mem_write_word(uint32_t addr, uint16_t value)
WRITE_PHYS_MEM(last_write_area, addr, WRITE_WORD_BE_A, value, 2);
}
void mem_write_dword(uint32_t addr, uint32_t value)
{
void mem_write_dword(uint32_t addr, uint32_t value) {
if (addr & 3) {
mem_write_unaligned(addr, value, 4);
}
@ -460,11 +427,10 @@ void mem_write_dword(uint32_t addr, uint32_t value)
WRITE_PHYS_MEM(last_write_area, addr, WRITE_DWORD_BE_A, value, 4);
}
void mem_write_qword(uint32_t addr, uint64_t value)
{
void mem_write_qword(uint32_t addr, uint64_t value) {
if (addr & 7) {
LOG_F(ERROR, "SOS! Attempt to write unaligned QWORD to 0x%08X\n", addr);
exit(-1); //FIXME!
exit(-1); // FIXME!
}
/* data address translation if enabled */
@ -475,15 +441,14 @@ void mem_write_qword(uint32_t addr, uint64_t value)
WRITE_PHYS_MEM(last_write_area, addr, WRITE_QWORD_BE_A, value, 8);
}
static uint32_t mem_grab_unaligned(uint32_t addr, uint32_t size)
{
static uint32_t mem_grab_unaligned(uint32_t addr, uint32_t size) {
uint32_t ret = 0;
LOG_F(WARNING, "Attempt to read unaligned %d bytes from 0x%08X\n", size, addr);
if (((addr & 0xFFF) + size) > 0x1000) {
LOG_F(ERROR, "SOS! Cross-page unaligned read, addr=%08X, size=%d\n", addr, size);
exit(-1); //FIXME!
exit(-1); // FIXME!
} else {
/* data address translation if enabled */
if (ppc_state.msr & 0x10) {
@ -501,8 +466,7 @@ static uint32_t mem_grab_unaligned(uint32_t addr, uint32_t size)
}
/** Grab a value from memory into a register */
uint8_t mem_grab_byte(uint32_t addr)
{
uint8_t mem_grab_byte(uint32_t addr) {
uint8_t ret;
/* data address translation if enabled */
@ -514,8 +478,7 @@ uint8_t mem_grab_byte(uint32_t addr)
return ret;
}
uint16_t mem_grab_word(uint32_t addr)
{
uint16_t mem_grab_word(uint32_t addr) {
uint16_t ret;
if (addr & 1) {
@ -531,8 +494,7 @@ uint16_t mem_grab_word(uint32_t addr)
return ret;
}
uint32_t mem_grab_dword(uint32_t addr)
{
uint32_t mem_grab_dword(uint32_t addr) {
uint32_t ret;
if (addr & 3) {
@ -548,13 +510,12 @@ uint32_t mem_grab_dword(uint32_t addr)
return ret;
}
uint64_t mem_grab_qword(uint32_t addr)
{
uint64_t mem_grab_qword(uint32_t addr) {
uint64_t ret;
if (addr & 7) {
LOG_F(ERROR, "SOS! Attempt to read unaligned QWORD at 0x%08X\n", addr);
exit(-1); //FIXME!
exit(-1); // FIXME!
}
/* data address translation if enabled */
@ -566,8 +527,7 @@ uint64_t mem_grab_qword(uint32_t addr)
return ret;
}
uint8_t* quickinstruction_translate(uint32_t addr)
{
uint8_t* quickinstruction_translate(uint32_t addr) {
uint8_t* real_addr;
/* perform instruction address translation if enabled */
@ -578,72 +538,67 @@ 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;
last_exec_area.end = entry->end;
last_exec_area.mem_ptr = entry->mem_ptr;
real_addr = last_exec_area.mem_ptr + (addr - last_exec_area.start);
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!
exit(-1); // FIXME: ugly error handling, must be the proper exception!
}
}
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;
/* save MMU-related CPU state */
save_dsisr = ppc_state.spr[SPR::DSISR];
save_dar = ppc_state.spr[SPR::DAR];
save_dsisr = ppc_state.spr[SPR::DSISR];
save_dar = ppc_state.spr[SPR::DAR];
mmu_exception_handler = dbg_exception_handler;
try {
switch(size) {
case 1:
ret_val = mem_grab_byte(virt_addr);
break;
case 2:
ret_val = mem_grab_word(virt_addr);
break;
case 4:
ret_val = mem_grab_dword(virt_addr);
break;
case 8:
ret_val = mem_grab_qword(virt_addr);
break;
default:
ret_val = mem_grab_byte(virt_addr);
switch (size) {
case 1:
ret_val = mem_grab_byte(virt_addr);
break;
case 2:
ret_val = mem_grab_word(virt_addr);
break;
case 4:
ret_val = mem_grab_dword(virt_addr);
break;
case 8:
ret_val = mem_grab_qword(virt_addr);
break;
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;
mmu_exception_handler = ppc_exception_handler;
ppc_state.spr[SPR::DSISR] = save_dsisr;
ppc_state.spr[SPR::DAR] = save_dar;
ppc_state.spr[SPR::DAR] = save_dar;
/* rethrow MMU exception */
throw exc;
}
/* restore MMU-related CPU state */
mmu_exception_handler = ppc_exception_handler;
mmu_exception_handler = ppc_exception_handler;
ppc_state.spr[SPR::DSISR] = save_dsisr;
ppc_state.spr[SPR::DAR] = save_dar;
ppc_state.spr[SPR::DAR] = save_dar;
return ret_val;
}
void ppc_mmu_init()
{
void ppc_mmu_init() {
mmu_exception_handler = ppc_exception_handler;
}

View File

@ -24,38 +24,38 @@ 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
/** generic PowerPC BAT descriptor (MMU internal state) */
typedef struct PPC_BAT_entry {
uint8_t access; /* copy of Vs | Vp bits */
uint8_t prot; /* copy of PP bits */
uint32_t phys_hi; /* high-order bits for physical address generation */
uint32_t lo_mask; /* mask for low-order logical address bits */
uint32_t bepi; /* copy of Block effective page index */
uint8_t access; /* copy of Vs | Vp bits */
uint8_t prot; /* copy of PP bits */
uint32_t phys_hi; /* high-order bits for physical address generation */
uint32_t lo_mask; /* mask for low-order logical address bits */
uint32_t bepi; /* copy of Block effective page index */
} PPC_BAT_entry;
extern void ibat_update(uint32_t bat_reg);
extern void dbat_update(uint32_t bat_reg);
extern uint8_t *mmu_get_dma_mem(uint32_t addr, uint32_t size);
extern uint8_t* mmu_get_dma_mem(uint32_t addr, uint32_t size);
extern void ppc_set_cur_instruction(const uint8_t* ptr);
extern void mem_write_byte(uint32_t addr, uint8_t value);
extern void mem_write_word(uint32_t addr, uint16_t value);
extern void mem_write_dword(uint32_t addr, uint32_t value);
extern void mem_write_qword(uint32_t addr, uint64_t value);
extern uint8_t mem_grab_byte(uint32_t addr);
extern uint8_t mem_grab_byte(uint32_t addr);
extern uint16_t mem_grab_word(uint32_t addr);
extern uint32_t mem_grab_dword(uint32_t addr);
extern uint64_t mem_grab_qword(uint32_t addr);
extern uint64_t mem_read_dbg(uint32_t virt_addr, uint32_t size);
extern uint8_t* quickinstruction_translate(uint32_t address_grab);
#endif // PPCMEMORY_H
#endif // PPCMEMORY_H

File diff suppressed because it is too large Load Diff

View File

@ -1,72 +1,68 @@
#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)
{
ppc_state.gpr[3] = 2;
ppc_state.gpr[4] = 2;
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_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()
{
xer_ov_test("ADDCO", 0x7C632414);
xer_ov_test("ADDCO.", 0x7C632415);
xer_ov_test("ADDO", 0x7C632614);
xer_ov_test("ADDO.", 0x7C632615);
xer_ov_test("ADDEO", 0x7C632514);
xer_ov_test("ADDEO.", 0x7C632515);
xer_ov_test("ADDMEO", 0x7C6305D4);
xer_ov_test("ADDMEO.", 0x7C6305D5);
xer_ov_test("ADDZEO", 0x7C630594);
xer_ov_test("ADDZEO.", 0x7C630595);
xer_ov_test("DIVWO", 0x7C6327D6);
xer_ov_test("DIVWO.", 0x7C6327D7);
xer_ov_test("DIVWUO", 0x7C632796);
xer_ov_test("DIVWUO.", 0x7C632797);
xer_ov_test("MULLWO", 0x7C6325D6);
xer_ov_test("MULLWO.", 0x7C6325D7);
xer_ov_test("NEGO", 0x7C6304D0);
xer_ov_test("NEGO.", 0x7C6304D1);
xer_ov_test("SUBFO", 0x7C632450);
xer_ov_test("SUBFO.", 0x7C632451);
xer_ov_test("SUBFCO", 0x7C632410);
xer_ov_test("SUBFCO.", 0x7C632411);
xer_ov_test("SUBFEO", 0x7C632510);
xer_ov_test("SUBFEO.", 0x7C632511);
xer_ov_test("SUBFMEO", 0x7C6305D0);
void xer_update_test() {
xer_ov_test("ADDCO", 0x7C632414);
xer_ov_test("ADDCO.", 0x7C632415);
xer_ov_test("ADDO", 0x7C632614);
xer_ov_test("ADDO.", 0x7C632615);
xer_ov_test("ADDEO", 0x7C632514);
xer_ov_test("ADDEO.", 0x7C632515);
xer_ov_test("ADDMEO", 0x7C6305D4);
xer_ov_test("ADDMEO.", 0x7C6305D5);
xer_ov_test("ADDZEO", 0x7C630594);
xer_ov_test("ADDZEO.", 0x7C630595);
xer_ov_test("DIVWO", 0x7C6327D6);
xer_ov_test("DIVWO.", 0x7C6327D7);
xer_ov_test("DIVWUO", 0x7C632796);
xer_ov_test("DIVWUO.", 0x7C632797);
xer_ov_test("MULLWO", 0x7C6325D6);
xer_ov_test("MULLWO.", 0x7C6325D7);
xer_ov_test("NEGO", 0x7C6304D0);
xer_ov_test("NEGO.", 0x7C6304D1);
xer_ov_test("SUBFO", 0x7C632450);
xer_ov_test("SUBFO.", 0x7C632451);
xer_ov_test("SUBFCO", 0x7C632410);
xer_ov_test("SUBFCO.", 0x7C632411);
xer_ov_test("SUBFEO", 0x7C632510);
xer_ov_test("SUBFEO.", 0x7C632511);
xer_ov_test("SUBFMEO", 0x7C6305D0);
xer_ov_test("SUBFMEO.", 0x7C6305D1);
xer_ov_test("SUBFZEO", 0x7C630590);
xer_ov_test("SUBFZEO", 0x7C630590);
xer_ov_test("SUBFZEO.", 0x7C630591);
}
/** testing vehicle */
static void read_test_data()
{
string line, token;
int i, lineno;
static void read_test_data() {
string line, token;
int i, lineno;
uint32_t opcode, dest, src1, src2, check_xer, check_cr;
ifstream tfstream("ppcinttests.csv");
ifstream tfstream("ppcinttests.csv");
if (!tfstream.is_open()) {
cout << "Could not open tests CSV file. Exiting..." << endl;
return;
@ -74,7 +70,7 @@ static void read_test_data()
lineno = 0;
while(getline(tfstream, line)) {
while (getline(tfstream, line)) {
lineno++;
if (line.empty() || !line.rfind("#", 0))
@ -84,7 +80,7 @@ static void read_test_data()
vector<string> tokens;
while(getline(lnstream, token, ',' )) {
while (getline(lnstream, token, ',')) {
tokens.push_back(token);
}
@ -95,9 +91,9 @@ static void read_test_data()
opcode = stoul(tokens[1], NULL, 16);
dest = 0;
src1 = 0;
src2 = 0;
dest = 0;
src1 = 0;
src2 = 0;
check_xer = 0;
check_cr = 0;
@ -113,16 +109,16 @@ 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);
}
}
ppc_state.gpr[3] = src1;
ppc_state.gpr[4] = src2;
ppc_state.gpr[3] = src1;
ppc_state.gpr[4] = src2;
ppc_state.spr[SPR::XER] = 0;
ppc_state.cr = 0;
ppc_state.cr = 0;
ppc_cur_instruction = opcode;
@ -131,15 +127,13 @@ static void read_test_data()
ntested++;
if ((tokens[0].rfind("CMP") && (ppc_state.gpr[3] != dest)) ||
(ppc_state.spr[SPR::XER] != check_xer) ||
(ppc_state.cr != check_cr)) {
cout << "Mismatch: instr=" << tokens[0] << ", src1=0x" << hex << src1
<< ", src2=0x" << hex << src2 << endl;
cout << "expected: dest=0x" << hex << dest << ", XER=0x" << hex
<< check_xer << ", CR=0x" << hex << check_cr << endl;
cout << "got: dest=0x" << hex << ppc_state.gpr[3] << ", XER=0x"
<< hex << ppc_state.spr[SPR::XER] << ", CR=0x" << hex
<< ppc_state.cr << endl;
(ppc_state.spr[SPR::XER] != check_xer) || (ppc_state.cr != check_cr)) {
cout << "Mismatch: instr=" << tokens[0] << ", src1=0x" << hex << src1 << ", src2=0x"
<< hex << src2 << endl;
cout << "expected: dest=0x" << hex << dest << ", XER=0x" << hex << check_xer
<< ", CR=0x" << hex << check_cr << endl;
cout << "got: dest=0x" << hex << ppc_state.gpr[3] << ", XER=0x" << hex
<< ppc_state.spr[SPR::XER] << ", CR=0x" << hex << ppc_state.cr << endl;
cout << "Test file line #: " << dec << lineno << endl << endl;
nfailed++;
@ -147,9 +141,7 @@ static void read_test_data()
}
}
int main()
{
int main() {
cout << "Running DingusPPC emulator tests..." << endl << endl;
ntested = 0;

View File

@ -1,22 +1,21 @@
#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()
{
string line, token;
int i, lineno;
static vector<PPCDisasmContext> read_test_data() {
string line, token;
int i, lineno;
PPCDisasmContext ctx;
vector<PPCDisasmContext> tstvec;
ifstream tfstream("ppcdisasmtest.csv");
ifstream tfstream("ppcdisasmtest.csv");
if (!tfstream.is_open()) {
cout << "Could not open tests CSV file. Exiting..." << endl;
return tstvec;
@ -24,18 +23,18 @@ static vector<PPCDisasmContext> read_test_data()
lineno = 0;
while(getline(tfstream, line)) {
while (getline(tfstream, line)) {
lineno++;
if (line.empty() || !line.rfind("#", 0))
continue; // skip empty/comment lines
continue; // skip empty/comment lines
istringstream lnstream(line);
vector<string> tokens;
while(getline(lnstream, token, ',' )) {
//cout << "Token: " << token << endl;
while (getline(lnstream, token, ',')) {
// cout << "Token: " << token << endl;
tokens.push_back(token);
}
@ -44,7 +43,7 @@ static vector<PPCDisasmContext> read_test_data()
continue;
}
ctx = {0};
ctx = {0};
ctx.instr_addr = stoul(tokens[0], NULL, 16);
ctx.instr_code = stoul(tokens[1], NULL, 16);
@ -64,7 +63,7 @@ static vector<PPCDisasmContext> read_test_data()
ctx.instr_str = idisasm.str();
//cout << idisasm.str() << endl;
// cout << idisasm.str() << endl;
tstvec.push_back(ctx);
}
@ -72,8 +71,7 @@ static vector<PPCDisasmContext> read_test_data()
return tstvec;
}
int test_ppc_disasm()
{
int test_ppc_disasm() {
int i, nfailed;
PPCDisasmContext ctx;
@ -84,7 +82,7 @@ int test_ppc_disasm()
nfailed = 0;
for (i = 0; i < testdata.size(); i++) {
ctx = {0};
ctx = {0};
ctx.instr_addr = testdata[i].instr_addr;
ctx.instr_code = testdata[i].instr_code;
ctx.simplified = true;
@ -92,14 +90,13 @@ int test_ppc_disasm()
std::string disas = disassemble_single(&ctx);
if (disas != testdata[i].instr_str) {
cout << "Mismatch found, expected={" << testdata[i].instr_str <<
"}, got={" << disas << "}" << endl;
cout << "Mismatch found, expected={" << testdata[i].instr_str << "}, got={" << disas
<< "}" << endl;
nfailed++;
}
}
cout << "Tested " << testdata.size() << " instructions. Failed: " <<
nfailed << "." << endl;
cout << "Tested " << testdata.size() << " instructions. Failed: " << nfailed << "." << endl;
return 0;
}

View File

@ -19,43 +19,38 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <map>
#include "../cpu/ppc/ppcdisasm.h"
#include "../cpu/ppc/ppcemu.h"
#include "../cpu/ppc/ppcmmu.h"
#include "../cpu/ppc/ppcdisasm.h"
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <sstream>
#include <stdio.h>
#include <string>
#include <thirdparty/loguru/loguru.hpp>
using namespace std;
static uint32_t str2addr(string& addr_str)
{
static uint32_t str2addr(string& addr_str) {
try {
return stoul(addr_str, NULL, 0);
}
catch (invalid_argument& exc) {
} catch (invalid_argument& exc) {
throw invalid_argument(string("Cannot convert ") + addr_str);
}
}
static uint32_t str2num(string& num_str)
{
static uint32_t str2num(string& num_str) {
try {
return stol(num_str, NULL, 0);
}
catch (invalid_argument & exc) {
} catch (invalid_argument& exc) {
throw invalid_argument(string("Cannot convert ") + num_str);
}
}
static void show_help()
{
static void show_help() {
cout << "Debugger commands:" << endl;
cout << " step -- execute single instruction" << endl;
cout << " si -- shortcut for step" << endl;
@ -80,8 +75,7 @@ static void show_help()
cout << "Pressing ENTER will repeat last command." << endl;
}
static void disasm(uint32_t count, uint32_t address)
{
static void disasm(uint32_t count, uint32_t address) {
PPCDisasmContext ctx;
ctx.instr_addr = address;
@ -94,8 +88,7 @@ static void disasm(uint32_t count, uint32_t address)
}
}
static void dump_mem(string& params)
{
static void dump_mem(string& params) {
int cell_size, chars_per_line;
bool is_char;
uint32_t count, addr;
@ -110,55 +103,52 @@ static void dump_mem(string& params)
}
num_type_str = params.substr(0, params.find_first_of(","));
addr_str = params.substr(params.find_first_of(",") + 1);
addr_str = params.substr(params.find_first_of(",") + 1);
is_char = false;
switch(num_type_str.back()) {
case 'b':
case 'B':
cell_size = 1;
break;
case 'w':
case 'W':
cell_size = 2;
break;
case 'd':
case 'D':
cell_size = 4;
break;
case 'q':
case 'Q':
cell_size = 8;
break;
case 'c':
case 'C':
cell_size = 1;
is_char = true;
break;
default:
cout << "Invalid data type " << num_type_str << endl;
return;
switch (num_type_str.back()) {
case 'b':
case 'B':
cell_size = 1;
break;
case 'w':
case 'W':
cell_size = 2;
break;
case 'd':
case 'D':
cell_size = 4;
break;
case 'q':
case 'Q':
cell_size = 8;
break;
case 'c':
case 'C':
cell_size = 1;
is_char = true;
break;
default:
cout << "Invalid data type " << num_type_str << endl;
return;
}
try {
num_type_str = num_type_str.substr(0, num_type_str.length() - 1);
count = str2addr(num_type_str);
}
catch (invalid_argument& exc) {
count = str2addr(num_type_str);
} catch (invalid_argument& exc) {
cout << exc.what() << endl;
return;
}
try {
addr = str2addr(addr_str);
}
catch (invalid_argument& exc) {
addr = str2addr(addr_str);
} 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;
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) {
@ -294,41 +271,35 @@ void enter_debugger()
continue;
}
inst_num_str = expr_str.substr(0, expr_str.find_first_of(","));
inst_grab = stol(inst_num_str, NULL, 0);
addr_str = expr_str.substr(expr_str.find_first_of(",") + 1);
inst_grab = stol(inst_num_str, NULL, 0);
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);
addr = get_reg(addr_str);
disasm(1, addr);
}
}
else if (cmd == "dump") {
} else if (cmd == "dump") {
expr_str = "";
ss >> expr_str;
dump_mem(expr_str);
}
else {
} else {
cout << "Unknown command: " << cmd << endl;
continue;
}

View File

@ -3,4 +3,4 @@
void enter_debugger(void);
#endif // DEBUGGER_H_
#endif // DEBUGGER_H_

View File

@ -25,9 +25,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "devices/adb.h"
#include <cinttypes>
#include <cstring>
#include "devices/adb.h"
#include <thirdparty/SDL2/include/SDL.h>
#include <thirdparty/SDL2/include/SDL_events.h>
@ -40,63 +40,56 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
using namespace std;
ADB_Bus::ADB_Bus() {
//set data streams as clear
// set data streams as clear
this->adb_mouse_register0 = 0x8080;
input_stream_len = 0;
input_stream_len = 0;
output_stream_len = 2;
adb_keybd_register3 = 0x6201;
adb_mouse_register3 = 0x6302;
keyboard_access_no = adb_encoded;
mouse_access_no = adb_relative;
mouse_access_no = adb_relative;
}
ADB_Bus::~ADB_Bus() {
}
ADB_Bus::~ADB_Bus() {}
bool ADB_Bus::listen(int device, int reg) {
if (device == keyboard_access_no) {
if (adb_keybd_listen(reg)) {
return true;
}
else {
} else {
return false;
}
}
else if (device == mouse_access_no) {
} else if (device == mouse_access_no) {
if (adb_mouse_listen(reg)) {
return true;
}
else {
} else {
return false;
}
}
else {
} else {
return false;
}
}
bool ADB_Bus::talk(int device, int reg, uint16_t value) {
//temp code
// temp code
return false;
}
bool ADB_Bus::bus_reset() {
//temp code
// temp code
return true;
}
bool ADB_Bus::set_addr(int dev_addr, int new_addr) {
//temp code
// temp code
return false;
}
bool ADB_Bus::flush(int dev_addr) {
//temp code
// temp code
return false;
}
@ -108,7 +101,7 @@ bool ADB_Bus::adb_keybd_listen(int reg) {
}
while (SDL_PollEvent(&adb_keybd_evt)) {
//Poll our SDL key event for any keystrokes.
// Poll our SDL key event for any keystrokes.
switch (adb_keybd_evt.type) {
case SDL_KEYDOWN:
switch (adb_keybd_evt.key.keysym.sym) {
@ -323,36 +316,36 @@ bool ADB_Bus::adb_keybd_listen(int reg) {
ask_key_pressed = 0x5C;
break;
case SDLK_BACKSPACE:
//ask_key_pressed = 0x33;
// ask_key_pressed = 0x33;
confirm_ask_reg_2 = true;
mod_key_pressed = 0x40;
mod_key_pressed = 0x40;
break;
case SDLK_CAPSLOCK:
//ask_key_pressed = 0x39;
// ask_key_pressed = 0x39;
confirm_ask_reg_2 = true;
mod_key_pressed = 0x20;
mod_key_pressed = 0x20;
break;
case SDLK_RALT:
case SDLK_RCTRL: //Temp key for Control key
//ask_key_pressed = 0x36;
case SDLK_RCTRL: // Temp key for Control key
// ask_key_pressed = 0x36;
confirm_ask_reg_2 = true;
mod_key_pressed = 0x8;
mod_key_pressed = 0x8;
break;
case SDLK_LSHIFT:
case SDLK_RSHIFT:
//ask_key_pressed = 0x38;
// ask_key_pressed = 0x38;
confirm_ask_reg_2 = true;
mod_key_pressed = 0x4;
mod_key_pressed = 0x4;
break;
case SDLK_LALT:
//ask_key_pressed = 0x3A;
// ask_key_pressed = 0x3A;
confirm_ask_reg_2 = true;
mod_key_pressed = 0x2;
mod_key_pressed = 0x2;
break;
case SDLK_LCTRL: //Temp key for the Command/Apple key
//ask_key_pressed = 0x37;
case SDLK_LCTRL: // Temp key for the Command/Apple key
// ask_key_pressed = 0x37;
confirm_ask_reg_2 = true;
mod_key_pressed = 0x1;
mod_key_pressed = 0x1;
break;
default:
break;
@ -363,15 +356,14 @@ bool ADB_Bus::adb_keybd_listen(int reg) {
adb_keybd_register0 &= (ask_key_pressed << 8);
output_data_stream[0] = (adb_keybd_register0 >> 8);
output_data_stream[1] = (adb_keybd_register0 & 0xff);
}
else if (adb_keybd_register0 & 0x80) {
} else if (adb_keybd_register0 & 0x80) {
adb_keybd_register0 &= 0xFF7F;
adb_keybd_register0 &= (ask_key_pressed);
output_data_stream[0] = (adb_keybd_register0 >> 8);
output_data_stream[1] = (adb_keybd_register0 & 0xff);
}
//check if mod keys are being pressed
// check if mod keys are being pressed
if (confirm_ask_reg_2) {
adb_keybd_register0 |= (mod_key_pressed << 8);
@ -386,25 +378,23 @@ 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);
output_data_stream[0] = (adb_keybd_register0 >> 8);
output_data_stream[1] = (adb_keybd_register0 & 0xff);
if (confirm_ask_reg_2) {
adb_keybd_register2 &= (mod_key_pressed << 8);
output_data_stream[0] = (adb_keybd_register2 >> 8);
output_data_stream[1] = (adb_keybd_register2 & 0xff);
confirm_ask_reg_2 = false;
confirm_ask_reg_2 = false;
}
}
}
if ((reg != 1)) {
return true;
}
else {
} else {
return false;
}
}
@ -421,11 +411,9 @@ bool ADB_Bus::adb_mouse_listen(int reg) {
if (adb_mouse_evt.motion.xrel < 0) {
if (adb_mouse_evt.motion.xrel <= -64) {
this->adb_mouse_register0 |= 0x7F;
}
else if (adb_mouse_evt.motion.xrel >= 63) {
} else if (adb_mouse_evt.motion.xrel >= 63) {
this->adb_mouse_register0 |= 0x3F;
}
else {
} else {
this->adb_mouse_register0 |= adb_mouse_evt.motion.xrel;
}
}
@ -436,15 +424,12 @@ bool ADB_Bus::adb_mouse_listen(int reg) {
if (adb_mouse_evt.motion.yrel < 0) {
if (adb_mouse_evt.motion.yrel <= -64) {
this->adb_mouse_register0 |= 0x7F00;
}
else if (adb_mouse_evt.motion.yrel >= 63) {
} else if (adb_mouse_evt.motion.yrel >= 63) {
this->adb_mouse_register0 |= 0x3F00;
}
else {
} else {
this->adb_mouse_register0 |= (adb_mouse_evt.motion.yrel << 8);
}
}
}
switch (adb_mouse_evt.type) {
@ -458,13 +443,11 @@ bool ADB_Bus::adb_mouse_listen(int reg) {
if (reg == 0) {
output_data_stream[0] = (adb_mouse_register0 >> 8);
output_data_stream[1] = (adb_mouse_register0 & 0xff);
}
else if (reg == 3) {
} else if (reg == 3) {
output_data_stream[0] = (adb_mouse_register3 >> 8);
output_data_stream[1] = (adb_mouse_register3 & 0xff);
}
return true;
}

View File

@ -26,15 +26,26 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <thirdparty/SDL2/include/SDL.h>
#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
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
};
class ADB_Bus
{
class ADB_Bus {
public:
ADB_Bus();
~ADB_Bus();
@ -58,7 +69,7 @@ private:
int keyboard_access_no;
int mouse_access_no;
//Keyboard Variables
// Keyboard Variables
uint16_t adb_keybd_register0;
uint16_t adb_keybd_register2;
@ -71,15 +82,15 @@ private:
bool confirm_ask_reg_2;
//Mouse Variables
// Mouse Variables
SDL_Event adb_mouse_evt;
uint16_t adb_mouse_register0;
uint16_t adb_mouse_register3;
uint8_t input_data_stream[16]; //temp buffer
uint8_t input_data_stream[16]; // temp buffer
int input_stream_len;
uint8_t output_data_stream[16]; //temp buffer
uint8_t output_data_stream[16]; // temp buffer
int output_stream_len;
};

View File

@ -19,17 +19,16 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <atirage.h>
#include <cstdint>
#include <thirdparty/loguru/loguru.hpp>
#include "displayid.h"
#include "endianswap.h"
#include "memreadwrite.h"
#include "pcidevice.h"
#include "displayid.h"
#include <atirage.h>
#include <cstdint>
#include <thirdparty/loguru/loguru.hpp>
ATIRage::ATIRage(uint16_t dev_id) : PCIDevice("ati-rage")
{
ATIRage::ATIRage(uint16_t dev_id) : PCIDevice("ati-rage") {
WRITE_DWORD_BE_A(&this->pci_cfg[0], (dev_id << 16) | ATI_PCI_VENDOR_ID);
WRITE_DWORD_BE_A(&this->pci_cfg[8], 0x0300005C);
WRITE_DWORD_BE_A(&this->pci_cfg[0x3C], 0x00080100);
@ -37,13 +36,11 @@ ATIRage::ATIRage(uint16_t dev_id) : PCIDevice("ati-rage")
this->disp_id = new DisplayID();
}
ATIRage::~ATIRage()
{
ATIRage::~ATIRage() {
delete (this->disp_id);
}
uint32_t ATIRage::size_dep_read(uint8_t *buf, uint32_t size)
{
uint32_t ATIRage::size_dep_read(uint8_t* buf, uint32_t size) {
switch (size) {
case 4:
return READ_DWORD_LE_A(buf);
@ -60,8 +57,7 @@ uint32_t ATIRage::size_dep_read(uint8_t *buf, uint32_t size)
}
}
void ATIRage::size_dep_write(uint8_t *buf, uint32_t value, uint32_t size)
{
void ATIRage::size_dep_write(uint8_t* buf, uint32_t value, uint32_t size) {
switch (size) {
case 4:
WRITE_DWORD_BE_A(buf, value);
@ -74,8 +70,7 @@ void ATIRage::size_dep_write(uint8_t *buf, uint32_t value, uint32_t size)
}
}
const char* ATIRage::get_reg_name(uint32_t reg_offset)
{
const char* ATIRage::get_reg_name(uint32_t reg_offset) {
const char* reg_name;
switch (reg_offset & ~3) {
@ -152,16 +147,19 @@ const char* ATIRage::get_reg_name(uint32_t reg_offset)
return reg_name;
}
uint32_t ATIRage::read_reg(uint32_t offset, uint32_t size)
{
uint32_t ATIRage::read_reg(uint32_t offset, uint32_t size) {
uint32_t res;
switch (offset & ~3) {
case ATI_GP_IO:
break;
default:
LOG_F(INFO, "ATI Rage: read I/O reg %s at 0x%X, size=%d, val=0x%X",
get_reg_name(offset), offset, size,
LOG_F(
INFO,
"ATI Rage: read I/O reg %s at 0x%X, size=%d, val=0x%X",
get_reg_name(offset),
offset,
size,
size_dep_read(&this->block_io_regs[offset], size));
}
@ -170,8 +168,7 @@ uint32_t ATIRage::read_reg(uint32_t offset, uint32_t size)
return res;
}
void ATIRage::write_reg(uint32_t offset, uint32_t value, uint32_t size)
{
void ATIRage::write_reg(uint32_t offset, uint32_t value, uint32_t size) {
uint32_t gpio_val;
uint16_t gpio_dir;
@ -183,20 +180,23 @@ void ATIRage::write_reg(uint32_t offset, uint32_t value, uint32_t size)
if (offset < (ATI_GP_IO + 2)) {
gpio_val = READ_DWORD_LE_A(&this->block_io_regs[ATI_GP_IO]);
gpio_dir = (gpio_val >> 16) & 0x3FFF;
WRITE_WORD_LE_A(&this->block_io_regs[ATI_GP_IO],
WRITE_WORD_LE_A(
&this->block_io_regs[ATI_GP_IO],
this->disp_id->read_monitor_sense(gpio_val, gpio_dir));
}
break;
default:
LOG_F(INFO, "ATI Rage: %s register at 0x%X set to 0x%X",
get_reg_name(offset), offset & ~3,
LOG_F(
INFO,
"ATI Rage: %s register at 0x%X set to 0x%X",
get_reg_name(offset),
offset & ~3,
READ_DWORD_LE_A(&this->block_io_regs[offset & ~3]));
}
}
uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size)
{
uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size) {
uint32_t res = 0;
LOG_F(INFO, "Reading ATI Rage config space, offset = 0x%X, size=%d", reg_offs, size);
@ -207,32 +207,32 @@ uint32_t ATIRage::pci_cfg_read(uint32_t reg_offs, uint32_t size)
return res;
}
void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
{
LOG_F(INFO, "Writing into ATI Rage PCI config space, offset = 0x%X, val=0x%X size=%d",
reg_offs, BYTESWAP_32(value), size);
void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) {
LOG_F(
INFO,
"Writing into ATI Rage PCI config space, offset = 0x%X, val=0x%X size=%d",
reg_offs,
BYTESWAP_32(value),
size);
switch (reg_offs) {
case 0x10: /* BAR 0 */
if (value == 0xFFFFFFFFUL) {
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR0], 0xFF000008);
}
else {
} else {
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR0], value);
}
break;
case 0x14: /* BAR 1: I/O space base, 256 bytes wide */
if (value == 0xFFFFFFFFUL) {
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR1], 0x0000FFF1);
}
else {
} else {
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR1], value);
}
case 0x18: /* BAR 2 */
if (value == 0xFFFFFFFFUL) {
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR2], 0xFFFFF000);
}
else {
} else {
WRITE_DWORD_BE_A(&this->pci_cfg[CFG_REG_BAR2], value);
}
break;
@ -248,8 +248,7 @@ void ATIRage::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
}
bool ATIRage::io_access_allowed(uint32_t offset, uint32_t *p_io_base)
{
bool ATIRage::io_access_allowed(uint32_t offset, uint32_t* p_io_base) {
if (!(this->pci_cfg[CFG_REG_CMD] & 1)) {
LOG_F(WARNING, "ATI I/O space disabled in the command reg");
return false;
@ -268,8 +267,7 @@ bool ATIRage::io_access_allowed(uint32_t offset, uint32_t *p_io_base)
}
bool ATIRage::pci_io_read(uint32_t offset, uint32_t size, uint32_t *res)
{
bool ATIRage::pci_io_read(uint32_t offset, uint32_t size, uint32_t* res) {
uint32_t io_base;
if (!this->io_access_allowed(offset, &io_base)) {
@ -281,8 +279,7 @@ bool ATIRage::pci_io_read(uint32_t offset, uint32_t size, uint32_t *res)
}
bool ATIRage::pci_io_write(uint32_t offset, uint32_t value, uint32_t size)
{
bool ATIRage::pci_io_write(uint32_t offset, uint32_t value, uint32_t size) {
uint32_t io_base;
if (!this->io_access_allowed(offset, &io_base)) {
@ -294,13 +291,11 @@ bool ATIRage::pci_io_write(uint32_t offset, uint32_t value, uint32_t size)
}
uint32_t ATIRage::read(uint32_t reg_start, uint32_t offset, int size)
{
uint32_t ATIRage::read(uint32_t reg_start, uint32_t offset, int size) {
LOG_F(INFO, "Reading reg=%X, size %d", offset, size);
return 0;
}
void ATIRage::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
{
void ATIRage::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) {
LOG_F(INFO, "Writing reg=%X, value=%X, size %d", offset, value, size);
}

View File

@ -22,9 +22,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#ifndef ATI_RAGE_H
#define ATI_RAGE_H
#include <cinttypes>
#include "pcidevice.h"
#include "displayid.h"
#include "pcidevice.h"
#include <cinttypes>
using namespace std;
@ -37,73 +37,72 @@ enum {
/** Mach registers offsets. */
enum {
ATI_CRTC_H_TOTAL_DISP = 0x0000,
ATI_CRTC_H_SYNC_STRT_WID = 0x0004,
ATI_CRTC_V_TOTAL_DISP = 0x0008,
ATI_CRTC_V_SYNC_STRT_WID = 0x000C,
ATI_CRTC_OFF_PITCH = 0x0014,
ATI_CRTC_INT_CNTL = 0x0018,
ATI_CRTC_GEN_CNTL = 0x001C,
ATI_DSP_CONFIG = 0x0020,
ATI_DSP_ON_OFF = 0x0024,
ATI_TIMER_CFG = 0x0028,
ATI_MEM_BUF_CNTL = 0x002C,
ATI_MEM_ADDR_CFG = 0x0034,
ATI_CRT_TRAP = 0x0038,
ATI_I2C_CNTL_0 = 0x003C,
ATI_OVR_CLR = 0x0040,
ATI_OVR_WID_LEFT_RIGHT = 0x0044,
ATI_OVR_WID_TOP_BOTTOM = 0x0048,
ATI_VGA_DSP_CFG = 0x004C,
ATI_VGA_DSP_TGL = 0x0050,
ATI_DSP2_CONFIG = 0x0054,
ATI_DSP2_TOGGLE = 0x0058,
ATI_CRTC2_OFF_PITCH = 0x005C,
ATI_CUR_CLR0 = 0x0060,
ATI_CUR_CLR1 = 0x0064,
ATI_CUR_OFFSET = 0x0068,
ATI_CUR_HORZ_VERT_POSN = 0x006C,
ATI_CUR_HORZ_VERT_OFF = 0x0070,
ATI_GP_IO = 0x0078,
ATI_HW_DEBUG = 0x007C,
ATI_SCRATCH_REG0 = 0x0080,
ATI_SCRATCH_REG1 = 0x0084,
ATI_SCRATCH_REG2 = 0x0088,
ATI_SCRATCH_REG3 = 0x008C,
ATI_CLOCK_CNTL = 0x0090,
ATI_CLONFIG_STAT1 = 0x0094,
ATI_CLONFIG_STAT2 = 0x0098,
ATI_BUS_CNTL = 0x00A0,
ATI_EXT_MEM_CNTL = 0x00AC,
ATI_MEM_CNTL = 0x00B0,
ATI_VGA_WP_SEL = 0x00B4,
ATI_VGA_RP_SEL = 0x00B8,
ATI_I2C_CNTL_1 = 0x00BC,
ATI_DAC_REGS = 0x00C0,
ATI_DAC_CNTL = 0x00C4,
ATI_GEN_TEST_CNTL = 0x00D0,
ATI_CUSTOM_MACRO_CNTL = 0x00D4,
ATI_CONFIG_CNTL = 0x00DC,
ATI_CFG_CHIP_ID = 0x00E0,
ATI_CFG_STAT0 = 0x00E4,
ATI_CRC_SIG = 0x00E8,
ATI_DST_OFF_PITCH = 0x0100,
ATI_SRC_OFF_PITCH = 0x0180,
ATI_HOST_CNTL = 0x0240,
ATI_DP_WRITE_MSK = 0x02C8,
ATI_DP_PIX_WIDTH = 0x02D0,
ATI_DST_X_Y = 0x02E8,
ATI_DST_WIDTH_HEIGHT = 0x02EC,
ATI_CONTEXT_MASK = 0x0320,
ATI_MPP_CONFIG = 0x04C0,
ATI_MPP_STROBE_SEQ = 0x04C4,
ATI_MPP_ADDR = 0x04C8,
ATI_MPP_DATA = 0x04CC,
ATI_TVO_CNTL = 0x0500,
ATI_CRTC_H_TOTAL_DISP = 0x0000,
ATI_CRTC_H_SYNC_STRT_WID = 0x0004,
ATI_CRTC_V_TOTAL_DISP = 0x0008,
ATI_CRTC_V_SYNC_STRT_WID = 0x000C,
ATI_CRTC_OFF_PITCH = 0x0014,
ATI_CRTC_INT_CNTL = 0x0018,
ATI_CRTC_GEN_CNTL = 0x001C,
ATI_DSP_CONFIG = 0x0020,
ATI_DSP_ON_OFF = 0x0024,
ATI_TIMER_CFG = 0x0028,
ATI_MEM_BUF_CNTL = 0x002C,
ATI_MEM_ADDR_CFG = 0x0034,
ATI_CRT_TRAP = 0x0038,
ATI_I2C_CNTL_0 = 0x003C,
ATI_OVR_CLR = 0x0040,
ATI_OVR_WID_LEFT_RIGHT = 0x0044,
ATI_OVR_WID_TOP_BOTTOM = 0x0048,
ATI_VGA_DSP_CFG = 0x004C,
ATI_VGA_DSP_TGL = 0x0050,
ATI_DSP2_CONFIG = 0x0054,
ATI_DSP2_TOGGLE = 0x0058,
ATI_CRTC2_OFF_PITCH = 0x005C,
ATI_CUR_CLR0 = 0x0060,
ATI_CUR_CLR1 = 0x0064,
ATI_CUR_OFFSET = 0x0068,
ATI_CUR_HORZ_VERT_POSN = 0x006C,
ATI_CUR_HORZ_VERT_OFF = 0x0070,
ATI_GP_IO = 0x0078,
ATI_HW_DEBUG = 0x007C,
ATI_SCRATCH_REG0 = 0x0080,
ATI_SCRATCH_REG1 = 0x0084,
ATI_SCRATCH_REG2 = 0x0088,
ATI_SCRATCH_REG3 = 0x008C,
ATI_CLOCK_CNTL = 0x0090,
ATI_CLONFIG_STAT1 = 0x0094,
ATI_CLONFIG_STAT2 = 0x0098,
ATI_BUS_CNTL = 0x00A0,
ATI_EXT_MEM_CNTL = 0x00AC,
ATI_MEM_CNTL = 0x00B0,
ATI_VGA_WP_SEL = 0x00B4,
ATI_VGA_RP_SEL = 0x00B8,
ATI_I2C_CNTL_1 = 0x00BC,
ATI_DAC_REGS = 0x00C0,
ATI_DAC_CNTL = 0x00C4,
ATI_GEN_TEST_CNTL = 0x00D0,
ATI_CUSTOM_MACRO_CNTL = 0x00D4,
ATI_CONFIG_CNTL = 0x00DC,
ATI_CFG_CHIP_ID = 0x00E0,
ATI_CFG_STAT0 = 0x00E4,
ATI_CRC_SIG = 0x00E8,
ATI_DST_OFF_PITCH = 0x0100,
ATI_SRC_OFF_PITCH = 0x0180,
ATI_HOST_CNTL = 0x0240,
ATI_DP_WRITE_MSK = 0x02C8,
ATI_DP_PIX_WIDTH = 0x02D0,
ATI_DST_X_Y = 0x02E8,
ATI_DST_WIDTH_HEIGHT = 0x02EC,
ATI_CONTEXT_MASK = 0x0320,
ATI_MPP_CONFIG = 0x04C0,
ATI_MPP_STROBE_SEQ = 0x04C4,
ATI_MPP_ADDR = 0x04C8,
ATI_MPP_DATA = 0x04CC,
ATI_TVO_CNTL = 0x0500,
};
class ATIRage : public PCIDevice
{
class ATIRage : public PCIDevice {
public:
ATIRage(uint16_t dev_id);
~ATIRage();
@ -112,17 +111,21 @@ public:
uint32_t read(uint32_t reg_start, uint32_t offset, int size);
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size);
bool supports_type(HWCompType type) { return type == HWCompType::MMIO_DEV; };
bool supports_type(HWCompType type) {
return type == HWCompType::MMIO_DEV;
};
/* PCI device methods */
bool supports_io_space(void) { return true; };
bool supports_io_space(void) {
return true;
};
uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size);
void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size);
void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size);
/* I/O space access methods */
bool pci_io_read(uint32_t offset, uint32_t size, uint32_t *res);
bool pci_io_write(uint32_t offset, uint32_t value, uint32_t size) ;
bool pci_io_read(uint32_t offset, uint32_t size, uint32_t* res);
bool pci_io_write(uint32_t offset, uint32_t value, uint32_t size);
protected:
uint32_t size_dep_read(uint8_t* buf, uint32_t size);
@ -133,14 +136,14 @@ protected:
void write_reg(uint32_t offset, uint32_t value, uint32_t size);
private:
//uint32_t atirage_membuf_regs[9]; /* ATI Rage Memory Buffer Registers */
//uint32_t atirage_scratch_regs[4]; /* ATI Rage Scratch Registers */
//uint32_t atirage_cmdfifo_regs[3]; /* ATI Rage Command FIFO Registers */
//uint32_t atirage_datapath_regs[12]; /* ATI Rage Data Path Registers*/
// uint32_t atirage_membuf_regs[9]; /* ATI Rage Memory Buffer Registers */
// uint32_t atirage_scratch_regs[4]; /* ATI Rage Scratch Registers */
// uint32_t atirage_cmdfifo_regs[3]; /* ATI Rage Command FIFO Registers */
// uint32_t atirage_datapath_regs[12]; /* ATI Rage Data Path Registers*/
uint8_t block_io_regs[256] = { 0 };
uint8_t block_io_regs[256] = {0};
uint8_t pci_cfg[256] = { 0 }; /* PCI configuration space */
uint8_t pci_cfg[256] = {0}; /* PCI configuration space */
DisplayID* disp_id;
};

View File

@ -24,26 +24,24 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
Author: Max Poliakovski 2019-20
*/
#include <thirdparty/loguru/loguru.hpp>
#include "endianswap.h"
#include "awacs.h"
#include "dbdma.h"
#include "endianswap.h"
#include "machines/machinebase.h"
#include <thirdparty/SDL2/include/SDL.h>
#include <thirdparty/loguru/loguru.hpp>
static int awac_freqs[8] = {44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350};
AWACDevice::AWACDevice()
{
AWACDevice::AWACDevice() {
this->audio_proc = new AudioProcessor();
/* register audio processor chip with the I2C bus */
I2CBus *i2c_bus = dynamic_cast<I2CBus *>(gMachineObj->get_comp_by_type(HWCompType::I2C_HOST));
I2CBus* i2c_bus = dynamic_cast<I2CBus*>(gMachineObj->get_comp_by_type(HWCompType::I2C_HOST));
i2c_bus->register_device(0x45, this->audio_proc);
}
AWACDevice::~AWACDevice()
{
AWACDevice::~AWACDevice() {
delete this->audio_proc;
if (this->snd_buf)
@ -53,21 +51,18 @@ AWACDevice::~AWACDevice()
SDL_CloseAudioDevice(snd_out_dev);
}
void AWACDevice::set_dma_out(DMAChannel *dma_out_ch)
{
void AWACDevice::set_dma_out(DMAChannel* dma_out_ch) {
this->dma_out_ch = dma_out_ch;
}
uint32_t AWACDevice::snd_ctrl_read(uint32_t offset, int size)
{
switch(offset) {
uint32_t AWACDevice::snd_ctrl_read(uint32_t offset, int size) {
switch (offset) {
case AWAC_SOUND_CTRL_REG:
return this->snd_ctrl_reg;
case AWAC_CODEC_CTRL_REG:
return this->is_busy;
case AWAC_CODEC_STATUS_REG:
return (AWAC_AVAILABLE << 8) | (AWAC_MAKER_CRYSTAL << 16) |
(AWAC_REV_SCREAMER << 20);
return (AWAC_AVAILABLE << 8) | (AWAC_MAKER_CRYSTAL << 16) | (AWAC_REV_SCREAMER << 20);
break;
default:
LOG_F(ERROR, "AWAC: unsupported register at offset 0x%X", offset);
@ -76,12 +71,11 @@ uint32_t AWACDevice::snd_ctrl_read(uint32_t offset, int size)
return 0;
}
void AWACDevice::snd_ctrl_write(uint32_t offset, uint32_t value, int size)
{
void AWACDevice::snd_ctrl_write(uint32_t offset, uint32_t value, int size) {
int subframe, reg_num;
uint16_t data;
switch(offset) {
switch (offset) {
case AWAC_SOUND_CTRL_REG:
this->snd_ctrl_reg = BYTESWAP_32(value);
LOG_F(INFO, "New sound control value = 0x%X", this->snd_ctrl_reg);
@ -89,7 +83,7 @@ void AWACDevice::snd_ctrl_write(uint32_t offset, uint32_t value, int size)
case AWAC_CODEC_CTRL_REG:
subframe = (value >> 14) & 3;
reg_num = (value >> 20) & 7;
data = ((value >> 8) & 0xF00) | ((value >> 24) & 0xFF);
data = ((value >> 8) & 0xF00) | ((value >> 24) & 0xFF);
LOG_F(INFO, "AWAC subframe = %d, reg = %d, data = %08X\n", subframe, reg_num, data);
if (!subframe)
this->control_regs[reg_num] = data;
@ -99,48 +93,45 @@ void AWACDevice::snd_ctrl_write(uint32_t offset, uint32_t value, int size)
}
}
static void convert_data(const uint8_t *in, uint8_t *out, uint32_t len)
{
static void convert_data(const uint8_t* in, uint8_t* out, uint32_t len) {
uint16_t *p_in, *p_out;
if (len & 7) {
LOG_F(WARNING, "AWAC sound buffer len not a multiply of 8, %d", len);
}
p_in = (uint16_t *)in;
p_out = (uint16_t *)out;
p_in = (uint16_t*)in;
p_out = (uint16_t*)out;
len >>= 1;
/* AWAC data comes as LLRR -> convert it to LRLR */
for (int i = 0; i < len; i += 8) {
p_out[i] = p_in[i];
p_out[i+1] = p_in[i+2];
p_out[i+2] = p_in[i+1];
p_out[i+3] = p_in[i+3];
p_out[i] = p_in[i];
p_out[i + 1] = p_in[i + 2];
p_out[i + 2] = p_in[i + 1];
p_out[i + 3] = p_in[i + 3];
}
}
static void audio_out_callback(void *user_data, uint8_t *buf, int buf_len)
{
uint8_t *p_in;
static void audio_out_callback(void* user_data, uint8_t* buf, int buf_len) {
uint8_t* p_in;
uint32_t rem_len, got_len;
DMAChannel *dma_ch = (DMAChannel *)user_data; /* C API baby! */
DMAChannel* dma_ch = (DMAChannel*)user_data; /* C API baby! */
for (rem_len = buf_len; rem_len > 0; rem_len -= got_len, buf += got_len) {
if (!dma_ch->get_data(rem_len, &got_len, &p_in)) {
convert_data(p_in, buf, got_len);
//LOG_F(9, "Converted sound data, len = %d", got_len);
} else { /* no more data */
// LOG_F(9, "Converted sound data, len = %d", got_len);
} else { /* no more data */
memset(buf, 0, rem_len); /* fill the buffer with silence */
//LOG_F(9, "Inserted silence, len = %d", rem_len);
// LOG_F(9, "Inserted silence, len = %d", rem_len);
break;
}
}
}
uint32_t AWACDevice::convert_data(const uint8_t *data, int len)
{
uint32_t AWACDevice::convert_data(const uint8_t* data, int len) {
int i;
uint16_t *p_in, *p_out;
@ -151,30 +142,29 @@ uint32_t AWACDevice::convert_data(const uint8_t *data, int len)
this->buf_len = len;
}
p_in = (uint16_t *)data;
p_out = (uint16_t *)this->snd_buf;
p_in = (uint16_t*)data;
p_out = (uint16_t*)this->snd_buf;
for (i = 0; i < len; i += 8) {
p_out[i] = p_in[i];
p_out[i+1] = p_in[i+2];
p_out[i+2] = p_in[i+1];
p_out[i+3] = p_in[i+3];
p_out[i] = p_in[i];
p_out[i + 1] = p_in[i + 2];
p_out[i + 2] = p_in[i + 1];
p_out[i + 3] = p_in[i + 3];
}
return i;
}
void AWACDevice::dma_start()
{
void AWACDevice::dma_start() {
SDL_AudioSpec snd_spec, snd_settings;
SDL_zero(snd_spec);
snd_spec.freq = awac_freqs[(this->snd_ctrl_reg >> 8) & 7];
snd_spec.format = AUDIO_S16MSB; /* yes, AWAC accepts big-endian data */
snd_spec.freq = awac_freqs[(this->snd_ctrl_reg >> 8) & 7];
snd_spec.format = AUDIO_S16MSB; /* yes, AWAC accepts big-endian data */
snd_spec.channels = 2;
snd_spec.samples = 4096; /* buffer size, chosen empirically */
snd_spec.samples = 4096; /* buffer size, chosen empirically */
snd_spec.callback = audio_out_callback;
snd_spec.userdata = (void *)this->dma_out_ch;
snd_spec.userdata = (void*)this->dma_out_ch;
this->snd_out_dev = SDL_OpenAudioDevice(NULL, 0, &snd_spec, &snd_settings, 0);
@ -188,16 +178,14 @@ void AWACDevice::dma_start()
SDL_PauseAudioDevice(this->snd_out_dev, 0); /* start audio playing */
}
void AWACDevice::dma_end()
{
void AWACDevice::dma_end() {
if (this->snd_out_dev) {
SDL_CloseAudioDevice(this->snd_out_dev);
this->snd_out_dev = 0;
}
}
void AWACDevice::dma_push(uint8_t *buf, int size)
{
void AWACDevice::dma_push(uint8_t* buf, int size) {
uint32_t dst_len;
dst_len = this->convert_data(buf, size);
@ -213,6 +201,4 @@ void AWACDevice::dma_push(uint8_t *buf, int size)
}
}
void AWACDevice::dma_pull(uint8_t *buf, int size)
{
}
void AWACDevice::dma_pull(uint8_t* buf, int size) {}

View File

@ -28,9 +28,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#ifndef AWAC_H
#define AWAC_H
#include <cinttypes>
#include "i2c.h"
#include "dbdma.h"
#include "i2c.h"
#include <cinttypes>
#include <thirdparty/SDL2/include/SDL.h>
/** AWAC registers offsets. */
@ -42,7 +42,7 @@ enum {
/** AWAC manufacturer and revision. */
#define AWAC_MAKER_CRYSTAL 1
#define AWAC_REV_SCREAMER 3
#define AWAC_REV_SCREAMER 3
/** Apple source calls this kValidData but doesn't explain
what it actually means. It seems like it's used to check
@ -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;
};
@ -76,7 +77,7 @@ public:
return send_subaddress(data);
} else if (this->sub_addr <= 6) {
LOG_F(INFO, "TDA7433 byte 0x%X received", data);
this->regs[this->sub_addr] = data;
this->regs[this->sub_addr] = data;
if (this->auto_inc) {
this->sub_addr++;
}
@ -86,17 +87,17 @@ public:
}
};
bool receive_byte(uint8_t *p_data) {
bool receive_byte(uint8_t* p_data) {
*p_data = this->regs[this->sub_addr];
LOG_F(INFO, "TDA7433 byte 0x%X sent", *p_data);
return true;
};
private:
uint8_t regs[7]; /* control registers, see TDA7433 datasheet */
uint8_t regs[7]; /* control registers, see TDA7433 datasheet */
uint8_t sub_addr;
int pos;
int auto_inc;
int pos;
int auto_inc;
};
@ -105,33 +106,33 @@ public:
AWACDevice();
~AWACDevice();
void set_dma_out(DMAChannel *dma_out_ch);
void set_dma_out(DMAChannel* dma_out_ch);
uint32_t snd_ctrl_read(uint32_t offset, int size);
void snd_ctrl_write(uint32_t offset, uint32_t value, int size);
void snd_ctrl_write(uint32_t offset, uint32_t value, int size);
/* DMACallback methods */
void dma_start();
void dma_end();
void dma_push(uint8_t *buf, int size);
void dma_pull(uint8_t *buf, int size);
void dma_push(uint8_t* buf, int size);
void dma_pull(uint8_t* buf, int size);
protected:
uint32_t convert_data(const uint8_t *data, int len);
uint32_t convert_data(const uint8_t* data, int len);
private:
uint32_t snd_ctrl_reg = {0};
uint32_t snd_ctrl_reg = {0};
uint16_t control_regs[8] = {0}; /* control registers, each 12-bits wide */
uint8_t is_busy = 0;
AudioProcessor *audio_proc;
uint8_t is_busy = 0;
AudioProcessor* audio_proc;
SDL_AudioDeviceID snd_out_dev = 0;
bool wake_up = false;
bool wake_up = false;
DMAChannel *dma_out_ch;
DMAChannel* dma_out_ch;
uint8_t* snd_buf = 0;
uint32_t buf_len = 0;
uint8_t* snd_buf = 0;
uint32_t buf_len = 0;
};

View File

@ -21,27 +21,25 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
/** @file Descriptor-based direct memory access emulation. */
#include "dbdma.h"
#include "cpu/ppc/ppcmmu.h"
#include "endianswap.h"
#include <cinttypes>
#include <thirdparty/loguru/loguru.hpp>
#include "dbdma.h"
#include "endianswap.h"
#include "cpu/ppc/ppcmmu.h"
void DMAChannel::get_next_cmd(uint32_t cmd_addr, DMACmd *p_cmd)
{
void DMAChannel::get_next_cmd(uint32_t cmd_addr, DMACmd* p_cmd) {
/* load DMACmd from physical memory */
memcpy((uint8_t *)p_cmd, mmu_get_dma_mem(cmd_addr, 16), 16);
memcpy((uint8_t*)p_cmd, mmu_get_dma_mem(cmd_addr, 16), 16);
}
uint8_t DMAChannel::interpret_cmd()
{
uint8_t DMAChannel::interpret_cmd() {
DMACmd cmd_struct;
get_next_cmd(this->cmd_ptr, &cmd_struct);
this->ch_stat &= ~CH_STAT_WAKE; /* clear wake bit (DMA spec, 5.5.3.4) */
switch(cmd_struct.cmd_key >> 4) {
switch (cmd_struct.cmd_key >> 4) {
case 0:
LOG_F(9, "Executing DMA Command OUTPUT_MORE");
if (cmd_struct.cmd_key & 7) {
@ -52,11 +50,11 @@ uint8_t DMAChannel::interpret_cmd()
LOG_F(ERROR, "non-zero i/b/w not implemented");
break;
}
//this->dma_cb->dma_push(
// this->dma_cb->dma_push(
// mmu_get_dma_mem(cmd_struct.address, cmd_struct.req_count),
// cmd_struct.req_count);
this->queue_data = mmu_get_dma_mem(cmd_struct.address, cmd_struct.req_count);
this->queue_len = cmd_struct.req_count;
this->queue_len = cmd_struct.req_count;
this->cmd_ptr += 16;
break;
case 1:
@ -69,11 +67,11 @@ uint8_t DMAChannel::interpret_cmd()
LOG_F(ERROR, "non-zero i/b/w not implemented");
break;
}
//this->dma_cb->dma_push(
// this->dma_cb->dma_push(
// mmu_get_dma_mem(cmd_struct.address, cmd_struct.req_count),
// cmd_struct.req_count);
this->queue_data = mmu_get_dma_mem(cmd_struct.address, cmd_struct.req_count);
this->queue_len = cmd_struct.req_count;
this->queue_len = cmd_struct.req_count;
this->cmd_ptr += 16;
break;
case 2:
@ -105,8 +103,7 @@ uint8_t DMAChannel::interpret_cmd()
}
uint32_t DMAChannel::reg_read(uint32_t offset, int size)
{
uint32_t DMAChannel::reg_read(uint32_t offset, int size) {
uint32_t res = 0;
if (size != 4) {
@ -114,7 +111,7 @@ uint32_t DMAChannel::reg_read(uint32_t offset, int size)
return 0;
}
switch(offset) {
switch (offset) {
case DMAReg::CH_CTRL:
res = 0; /* ChannelControl reads as 0 (DBDMA spec 5.5.1, table 74) */
break;
@ -128,8 +125,7 @@ uint32_t DMAChannel::reg_read(uint32_t offset, int size)
return res;
}
void DMAChannel::reg_write(uint32_t offset, uint32_t value, int size)
{
void DMAChannel::reg_write(uint32_t offset, uint32_t value, int size) {
uint16_t mask, old_stat, new_stat;
if (size != 4) {
@ -137,12 +133,12 @@ void DMAChannel::reg_write(uint32_t offset, uint32_t value, int size)
return;
}
value = BYTESWAP_32(value);
value = BYTESWAP_32(value);
old_stat = this->ch_stat;
switch(offset) {
switch (offset) {
case DMAReg::CH_CTRL:
mask = value >> 16;
mask = value >> 16;
new_stat = (value & mask & 0xF0FFU) | (old_stat & ~mask);
LOG_F(INFO, "New ChannelStatus value = 0x%X", new_stat);
@ -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;
@ -204,14 +199,14 @@ int DMAChannel::get_data(uint32_t req_len, uint32_t *avail_len, uint8_t **p_data
if (this->queue_len) {
if (this->queue_len >= req_len) {
LOG_F(9, "Return req_len = %d data", req_len);
*p_data = this->queue_data;
*p_data = this->queue_data;
*avail_len = req_len;
this->queue_len -= req_len;
this->queue_len -= req_len;
this->queue_data += req_len;
} else { /* return less data than req_len */
LOG_F(9, "Return queue_len = %d data", this->queue_len);
*p_data = this->queue_data;
*avail_len = this->queue_len;
*p_data = this->queue_data;
*avail_len = this->queue_len;
this->queue_len = 0;
}
return 0; /* tell the caller there is more data */
@ -220,8 +215,7 @@ int DMAChannel::get_data(uint32_t req_len, uint32_t *avail_len, uint8_t **p_data
return -1; /* tell the caller there is no more data */
}
void DMAChannel::start()
{
void DMAChannel::start() {
if (this->ch_stat & CH_STAT_PAUSE) {
LOG_F(WARNING, "Cannot start DMA channel, PAUSE bit is set");
return;
@ -233,12 +227,11 @@ void DMAChannel::start()
this->dma_cb->dma_start();
//while (this->interpret_cmd() != 7) {
// while (this->interpret_cmd() != 7) {
//}
}
void DMAChannel::resume()
{
void DMAChannel::resume() {
if (this->ch_stat & CH_STAT_PAUSE) {
LOG_F(WARNING, "Cannot resume DMA channel, PAUSE bit is set");
return;
@ -247,13 +240,11 @@ void DMAChannel::resume()
LOG_F(INFO, "Resuming DMA channel");
}
void DMAChannel::abort()
{
void DMAChannel::abort() {
LOG_F(INFO, "Aborting DMA channel");
}
void DMAChannel::pause()
{
void DMAChannel::pause() {
LOG_F(INFO, "Pausing DMA channel");
this->dma_cb->dma_end();
}

View File

@ -33,52 +33,54 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
/** DBDMA Channel registers offsets */
enum DMAReg : uint32_t {
CH_CTRL = 0,
CH_STAT = 4,
CMD_PTR_LO = 12,
CH_CTRL = 0,
CH_STAT = 4,
CMD_PTR_LO = 12,
};
/** Channel Status bits (DBDMA spec, 5.5.3) */
enum {
CH_STAT_ACTIVE = 0x400,
CH_STAT_DEAD = 0x800,
CH_STAT_WAKE = 0x1000,
CH_STAT_FLUSH = 0x2000,
CH_STAT_PAUSE = 0x4000,
CH_STAT_RUN = 0x8000
CH_STAT_ACTIVE = 0x400,
CH_STAT_DEAD = 0x800,
CH_STAT_WAKE = 0x1000,
CH_STAT_FLUSH = 0x2000,
CH_STAT_PAUSE = 0x4000,
CH_STAT_RUN = 0x8000
};
/** DBDMA command (DBDMA spec, 5.6.1) - all fields are little-endian! */
typedef struct DMACmd {
uint16_t req_count;
uint8_t cmd_bits;
uint8_t cmd_key;
uint32_t address;
uint32_t cmd_arg;
uint16_t res_count;
uint16_t xfer_stat;
uint16_t req_count;
uint8_t cmd_bits;
uint8_t cmd_key;
uint32_t address;
uint32_t cmd_arg;
uint16_t res_count;
uint16_t xfer_stat;
} DMACmd;
class DMACallback {
public:
virtual void dma_start(void) = 0;
virtual void dma_end(void) = 0;
virtual void dma_push(uint8_t *buf, int size) = 0;
virtual void dma_pull(uint8_t *buf, int size) = 0;
virtual void dma_start(void) = 0;
virtual void dma_end(void) = 0;
virtual void dma_push(uint8_t* buf, int size) = 0;
virtual void dma_pull(uint8_t* buf, int size) = 0;
};
class DMAChannel {
public:
DMAChannel(DMACallback *cb) { this->dma_cb = cb; };
DMAChannel(DMACallback* cb) {
this->dma_cb = cb;
};
~DMAChannel() = default;
uint32_t reg_read(uint32_t offset, int size);
void reg_write(uint32_t offset, uint32_t value, int size);
int get_data(uint32_t req_len, uint32_t *avail_len, uint8_t **p_data);
int get_data(uint32_t req_len, uint32_t* avail_len, uint8_t** p_data);
protected:
void get_next_cmd(uint32_t cmd_addr, DMACmd *p_cmd);
void get_next_cmd(uint32_t cmd_addr, DMACmd* p_cmd);
uint8_t interpret_cmd(void);
void start(void);
@ -87,12 +89,12 @@ protected:
void pause(void);
private:
DMACallback *dma_cb = 0;
uint16_t ch_stat = 0;
uint32_t cmd_ptr = 0;
DMACallback* dma_cb = 0;
uint16_t ch_stat = 0;
uint32_t cmd_ptr = 0;
uint32_t queue_len;
uint8_t* queue_data;
uint32_t queue_len;
uint8_t* queue_data;
};
#endif /* DB_DMA_H */

View File

@ -19,11 +19,10 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <thirdparty/loguru/loguru.hpp>
#include "displayid.h"
#include <thirdparty/loguru/loguru.hpp>
DisplayID::DisplayID()
{
DisplayID::DisplayID() {
/* Initialize Apple monitor codes */
this->std_sense_code = 6;
this->ext_sense_code = 0x2B;
@ -41,22 +40,19 @@ DisplayID::DisplayID()
}
uint16_t DisplayID::set_result(uint8_t sda, uint8_t scl)
{
uint16_t DisplayID::set_result(uint8_t sda, uint8_t scl) {
this->last_sda = sda;
this->last_scl = scl;
if (scl) {
this->data_out |= 0x1000;
}
else {
} else {
this->data_out &= ~0x1000U;
}
if (sda) {
this->data_out |= 0x2000;
}
else {
} else {
this->data_out &= ~0x2000U;
}
@ -64,9 +60,8 @@ uint16_t DisplayID::set_result(uint8_t sda, uint8_t scl)
}
uint16_t DisplayID::read_monitor_sense(uint16_t data, uint16_t dirs)
{
uint8_t scl, sda;
uint16_t DisplayID::read_monitor_sense(uint16_t data, uint16_t dirs) {
uint8_t scl, sda;
uint16_t result;
if ((dirs & 0x3100) == 0 && (data & 0x3100) == 0x3100) {
@ -81,24 +76,19 @@ uint16_t DisplayID::read_monitor_sense(uint16_t data, uint16_t dirs)
sda = (dirs & 0x2000) ? !!(data & 0x2000) : 1;
return update_ddc_i2c(sda, scl);
}
else { /* Apple legacy monitor codes (see Technical Note HW30) */
} else { /* Apple legacy monitor codes (see Technical Note HW30) */
switch (dirs & 0x3100) {
case 0:
result = ((this->std_sense_code & 6) << 11) |
((this->std_sense_code & 1) << 8);
result = ((this->std_sense_code & 6) << 11) | ((this->std_sense_code & 1) << 8);
break;
case 0x2000: /* Sense line 2 is low */
result = ((this->ext_sense_code & 0x20) << 7) |
((this->ext_sense_code & 0x10) << 4);
result = ((this->ext_sense_code & 0x20) << 7) | ((this->ext_sense_code & 0x10) << 4);
break;
case 0x1000: /* Sense line 1 is low */
result = ((this->ext_sense_code & 8) << 10) |
((this->ext_sense_code & 4) << 6);
result = ((this->ext_sense_code & 8) << 10) | ((this->ext_sense_code & 4) << 6);
break;
case 0x100: /* Sense line 0 is low */
result = ((this->ext_sense_code & 2) << 12) |
((this->ext_sense_code & 1) << 12);
result = ((this->ext_sense_code & 2) << 12) | ((this->ext_sense_code & 1) << 12);
break;
default:
result = 0x3100U;
@ -109,7 +99,7 @@ uint16_t DisplayID::read_monitor_sense(uint16_t data, uint16_t dirs)
}
uint16_t DisplayID::update_ddc_i2c(uint8_t sda, uint8_t scl)//(uint16_t data, uint16_t dirs)
uint16_t DisplayID::update_ddc_i2c(uint8_t sda, uint8_t scl) //(uint16_t data, uint16_t dirs)
{
bool clk_gone_high = false;
@ -127,9 +117,8 @@ uint16_t DisplayID::update_ddc_i2c(uint8_t sda, uint8_t scl)//(uint16_t data, ui
if (!sda) {
LOG_F(9, "DDC-I2C: START condition detected!");
this->next_state = I2CState::DEV_ADDR;
this->bit_count = 0;
}
else {
this->bit_count = 0;
} else {
LOG_F(9, "DDC-I2C: STOP condition detected!");
this->next_state = I2CState::STOP;
}
@ -147,22 +136,20 @@ uint16_t DisplayID::update_ddc_i2c(uint8_t sda, uint8_t scl)//(uint16_t data, ui
case I2CState::ACK:
this->bit_count = 0;
this->byte = 0;
this->byte = 0;
switch (this->prev_state) {
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 */
}
if (this->dev_addr & 1) {
this->next_state = I2CState::DATA;
this->data_ptr = this->edid;
this->byte = *(this->data_ptr++);
}
else {
this->data_ptr = this->edid;
this->byte = *(this->data_ptr++);
} 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;
@ -198,14 +182,13 @@ uint16_t DisplayID::update_ddc_i2c(uint8_t sda, uint8_t scl)//(uint16_t data, ui
case I2CState::REG_ADDR:
this->byte = (this->byte << 1) | this->last_sda;
if (this->bit_count++ >= 7) {
this->bit_count = 0;
this->bit_count = 0;
this->prev_state = this->next_state;
this->next_state = I2CState::ACK;
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;
}
@ -215,7 +198,7 @@ uint16_t DisplayID::update_ddc_i2c(uint8_t sda, uint8_t scl)//(uint16_t data, ui
case I2CState::DATA:
sda = (this->byte >> (7 - this->bit_count)) & 1;
if (this->bit_count++ >= 7) {
this->bit_count = 0;
this->bit_count = 0;
this->prev_state = this->next_state;
this->next_state = I2CState::ACK;
}

View File

@ -61,39 +61,31 @@ protected:
private:
bool i2c_on;
uint8_t std_sense_code;
uint8_t ext_sense_code;
uint8_t std_sense_code;
uint8_t ext_sense_code;
/* DDC I2C variables. */
uint8_t next_state;
uint8_t prev_state;
uint8_t last_sda;
uint8_t last_scl;
uint8_t next_state;
uint8_t prev_state;
uint8_t last_sda;
uint8_t last_scl;
uint16_t data_out;
int bit_count; /* number of bits processed so far */
uint8_t byte; /* byte value being currently transferred */
uint8_t dev_addr; /* current device address */
uint8_t reg_addr; /* current register address */
uint8_t *data_ptr; /* ptr to data byte to be transferred next */
int bit_count; /* number of bits processed so far */
uint8_t byte; /* byte value being currently transferred */
uint8_t dev_addr; /* current device address */
uint8_t reg_addr; /* current register address */
uint8_t* data_ptr; /* ptr to data byte to be transferred next */
uint8_t 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
};
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};
/* More EDID:
00ff ffff ffff ff00 5a63 5151 0341 0000

View File

@ -19,14 +19,14 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <thirdparty/loguru/loguru.hpp>
#include <cinttypes>
#include <iostream>
#include "macio.h"
#include "viacuda.h"
#include "awacs.h"
#include "dbdma.h"
#include "machines/machinebase.h"
#include "macio.h"
#include "viacuda.h"
#include <cinttypes>
#include <iostream>
#include <thirdparty/loguru/loguru.hpp>
/** Heathrow Mac I/O device emulation.
@ -35,49 +35,45 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
using namespace std;
HeathrowIC::HeathrowIC() : PCIDevice("mac-io/heathrow")
{
this->nvram = new NVram();
HeathrowIC::HeathrowIC() : PCIDevice("mac-io/heathrow") {
this->nvram = new NVram();
this->viacuda = new ViaCuda();
this->viacuda = new ViaCuda();
gMachineObj->add_subdevice("ViaCuda", this->viacuda);
this->screamer = new AWACDevice();
this->screamer = new AWACDevice();
this->snd_out_dma = new DMAChannel(this->screamer);
this->screamer->set_dma_out(this->snd_out_dma);
}
HeathrowIC::~HeathrowIC()
{
HeathrowIC::~HeathrowIC() {
if (this->nvram)
delete(this->nvram);
delete (this->nvram);
if (this->viacuda)
delete(this->viacuda);
delete (this->viacuda);
}
uint32_t HeathrowIC::pci_cfg_read(uint32_t reg_offs, uint32_t size)
{
uint32_t HeathrowIC::pci_cfg_read(uint32_t reg_offs, uint32_t size) {
return this->pci_cfg_hdr[reg_offs & 0xFF];
}
void HeathrowIC::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
{
void HeathrowIC::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) {
switch (reg_offs) {
case CFG_REG_BAR0: // base address register
case CFG_REG_BAR0: // base address register
value = LE2BE(value);
if (value == 0xFFFFFFFF) {
LOG_F(ERROR, "%s err: BAR0 block size determination not \
implemented yet \n", this->name.c_str());
}
else if (value & 1) {
LOG_F(
ERROR,
"%s err: BAR0 block size determination not \
implemented yet \n",
this->name.c_str());
} else if (value & 1) {
LOG_F(ERROR, "%s err: BAR0 I/O space not supported! \n", this->name.c_str());
}
else if (value & 0x06) {
} else if (value & 0x06) {
LOG_F(ERROR, "%s err: BAR0 64-bit I/O space not supported! \n", this->name.c_str());
}
else {
} else {
this->base_addr = value & 0xFFF80000;
this->host_instance->pci_register_mmio_region(this->base_addr, 0x80000, this);
LOG_F(INFO, "%s base address set to %x \n", this->name.c_str(), this->base_addr);
@ -86,11 +82,10 @@ void HeathrowIC::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
}
}
uint32_t HeathrowIC::dma_read(uint32_t offset, int size)
{
uint32_t HeathrowIC::dma_read(uint32_t offset, int size) {
uint32_t res = 0;
switch(offset >> 8) {
switch (offset >> 8) {
case 8:
res = this->snd_out_dma->reg_read(offset & 0xFF, size);
break;
@ -101,9 +96,8 @@ uint32_t HeathrowIC::dma_read(uint32_t offset, int size)
return res;
}
void HeathrowIC::dma_write(uint32_t offset, uint32_t value, int size)
{
switch(offset >> 8) {
void HeathrowIC::dma_write(uint32_t offset, uint32_t value, int size) {
switch (offset >> 8) {
case 8:
this->snd_out_dma->reg_write(offset & 0xFF, value, size);
break;
@ -113,8 +107,7 @@ void HeathrowIC::dma_write(uint32_t offset, uint32_t value, int size)
}
uint32_t HeathrowIC::read(uint32_t reg_start, uint32_t offset, int size)
{
uint32_t HeathrowIC::read(uint32_t reg_start, uint32_t offset, int size) {
uint32_t res = 0;
LOG_F(9, "%s: reading from offset %x \n", this->name.c_str(), offset);
@ -138,8 +131,7 @@ uint32_t HeathrowIC::read(uint32_t reg_start, uint32_t offset, int size)
default:
if (sub_addr >= 0x60) {
res = this->nvram->read_byte((offset - 0x60000) >> 4);
}
else {
} else {
LOG_F(WARNING, "Attempting to read unmapped I/O space: %x \n", offset);
}
}
@ -147,8 +139,7 @@ uint32_t HeathrowIC::read(uint32_t reg_start, uint32_t offset, int size)
return res;
}
void HeathrowIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
{
void HeathrowIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) {
LOG_F(9, "%s: writing to offset %x \n", this->name.c_str(), offset);
unsigned sub_addr = (offset >> 12) & 0x7F;
@ -170,15 +161,13 @@ void HeathrowIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int
default:
if (sub_addr >= 0x60) {
this->nvram->write_byte((offset - 0x60000) >> 4, value);
}
else {
} else {
LOG_F(WARNING, "Attempting to write to unmapped I/O space: %x \n", offset);
}
}
}
uint32_t HeathrowIC::mio_ctrl_read(uint32_t offset, int size)
{
uint32_t HeathrowIC::mio_ctrl_read(uint32_t offset, int size) {
uint32_t res = 0;
switch (offset & 0xFF) {
@ -221,8 +210,7 @@ uint32_t HeathrowIC::mio_ctrl_read(uint32_t offset, int size)
return res;
}
void HeathrowIC::mio_ctrl_write(uint32_t offset, uint32_t value, int size)
{
void HeathrowIC::mio_ctrl_write(uint32_t offset, uint32_t value, int size) {
switch (offset & 0xFF) {
case 0x14:
LOG_F(9, "read from MIO:Int_Mask2 register \n");

View File

@ -26,17 +26,17 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
/** types of different HW components */
enum HWCompType : int {
UNKNOWN = 0, /* unknown component type */
MEM_CTRL = 10, /* memory controller */
ROM = 20, /* read-only memory */
RAM = 30, /* random access memory */
MMIO_DEV = 40, /* memory mapped I/O device */
PCI_HOST = 50, /* PCI host */
PCI_DEV = 51, /* PCI device */
I2C_HOST = 60, /* I2C host */
I2C_DEV = 61, /* I2C device */
ADB_HOST = 70, /* ADB host */
ADB_DEV = 71, /* ADB device */
UNKNOWN = 0, /* unknown component type */
MEM_CTRL = 10, /* memory controller */
ROM = 20, /* read-only memory */
RAM = 30, /* random access memory */
MMIO_DEV = 40, /* memory mapped I/O device */
PCI_HOST = 50, /* PCI host */
PCI_DEV = 51, /* PCI device */
I2C_HOST = 60, /* I2C host */
I2C_DEV = 61, /* I2C device */
ADB_HOST = 70, /* ADB host */
ADB_DEV = 71, /* ADB device */
};
@ -45,8 +45,12 @@ class HWComponent {
public:
virtual ~HWComponent() = default;
virtual std::string get_name(void) { return this->name; };
virtual void set_name(std::string name) { this->name = name; };
virtual std::string get_name(void) {
return this->name;
};
virtual void set_name(std::string name) {
this->name = name;
};
virtual bool supports_type(HWCompType type) = 0;

View File

@ -27,26 +27,30 @@ 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 {
public:
virtual void start_transaction() = 0;
virtual void start_transaction() = 0;
virtual bool send_subaddress(uint8_t sub_addr) = 0;
virtual bool send_byte(uint8_t data) = 0;
virtual bool receive_byte(uint8_t *p_data) = 0;
virtual bool send_byte(uint8_t data) = 0;
virtual bool receive_byte(uint8_t* p_data) = 0;
};
/** Base class for I2C hosts */
class I2CBus {
public:
I2CBus() { std::memset(this->dev_list, 0, sizeof(this->dev_list)); };
~I2CBus() { std::memset(this->dev_list, 0, sizeof(this->dev_list)); };
I2CBus() {
std::memset(this->dev_list, 0, sizeof(this->dev_list));
};
~I2CBus() {
std::memset(this->dev_list, 0, sizeof(this->dev_list));
};
virtual void register_device(uint8_t dev_addr, I2CDevice *dev_obj) {
virtual void register_device(uint8_t dev_addr, I2CDevice* dev_obj) {
if (this->dev_list[dev_addr]) {
throw std::invalid_argument(std::string("I2C address already taken!"));
}
@ -77,7 +81,7 @@ public:
return this->dev_list[dev_addr]->send_byte(data);
};
virtual bool receive_byte(uint8_t dev_addr, uint8_t *p_data) {
virtual bool receive_byte(uint8_t dev_addr, uint8_t* p_data) {
if (!this->dev_list[dev_addr]) {
return false; /* no device -> no acknowledge */
}
@ -85,7 +89,7 @@ public:
};
protected:
I2CDevice *dev_list[128]; /* list of registered I2C devices */
I2CDevice* dev_list[128]; /* list of registered I2C devices */
};
#endif /* I2C_H */

View File

@ -22,9 +22,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#ifndef MACHINE_ID_H
#define MACHINE_ID_H
#include <cinttypes>
#include "hwcomponent.h"
#include "mmiodevice.h"
#include <cinttypes>
/**
@file Contains definitions for PowerMacintosh machine ID registers.
@ -44,7 +44,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
class GossamerID : public MMIODevice {
public:
GossamerID(const uint16_t id) { this->id = id, this->name = "Machine-id"; };
GossamerID(const uint16_t id) {
this->id = id, this->name = "Machine-id";
};
~GossamerID() = default;
bool supports_type(HWCompType type) {
@ -52,10 +54,10 @@ public:
};
uint32_t read(uint32_t reg_start, uint32_t offset, int size) {
return ((!offset && size == 2) ? this->id : 0); };
return ((!offset && size == 2) ? this->id : 0);
};
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
{}; /* not writable */
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size){}; /* not writable */
private:
uint16_t id;

View File

@ -51,16 +51,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#ifndef MACIO_H
#define MACIO_H
#include <cinttypes>
#include "hwcomponent.h"
#include "pcidevice.h"
#include "memctrlbase.h"
#include "mmiodevice.h"
#include "pcihost.h"
#include "viacuda.h"
#include "nvram.h"
#include "awacs.h"
#include "dbdma.h"
#include "hwcomponent.h"
#include "memctrlbase.h"
#include "mmiodevice.h"
#include "nvram.h"
#include "pcidevice.h"
#include "pcihost.h"
#include "viacuda.h"
#include <cinttypes>
/**
Heathrow ASIC emulation
@ -86,19 +86,22 @@ 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);
void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size);
/* MMIO device methods */
uint32_t read(uint32_t reg_start, uint32_t offset, int 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?)
0x01, // revision ID
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, // standard programming
0x00, // subclass code
0xFF, // class code: unassigned
0x00,
0x00, // unknown defaults
0x00,
0x00 // unknown defaults
};
uint32_t int_mask2;
@ -132,14 +141,14 @@ private:
uint32_t int_mask1;
uint32_t int_clear1;
uint32_t int_levels1;
uint32_t feat_ctrl; // features control register
uint32_t feat_ctrl; // features control register
/* device cells */
ViaCuda *viacuda; /* VIA cell with Cuda MCU attached to it */
NVram *nvram; /* NVRAM cell */
AWACDevice *screamer; /* Screamer audio codec instance */
ViaCuda* viacuda; /* VIA cell with Cuda MCU attached to it */
NVram* nvram; /* NVRAM cell */
AWACDevice* screamer; /* Screamer audio codec instance */
DMAChannel *snd_out_dma;
DMAChannel* snd_out_dma;
};
#endif /* MACIO_H */

View File

@ -19,28 +19,26 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <string>
#include <algorithm> // to shut up MSVC errors (:
#include <cstring>
#include <string>
#include <vector>
#include <algorithm> // to shut up MSVC errors (:
#include "memctrlbase.h"
MemCtrlBase::~MemCtrlBase()
{
for (auto &reg : mem_regions) {
MemCtrlBase::~MemCtrlBase() {
for (auto& reg : mem_regions) {
if (reg)
delete(reg);
delete (reg);
}
this->mem_regions.clear();
this->address_map.clear();
}
AddressMapEntry *MemCtrlBase::find_range(uint32_t addr)
{
for (auto &entry : address_map) {
AddressMapEntry* MemCtrlBase::find_range(uint32_t addr) {
for (auto& entry : address_map) {
if (addr >= entry.start && addr <= entry.end)
return &entry;
}
@ -49,16 +47,15 @@ AddressMapEntry *MemCtrlBase::find_range(uint32_t addr)
}
bool MemCtrlBase::add_mem_region(uint32_t start_addr, uint32_t size,
uint32_t dest_addr, uint32_t type, uint8_t init_val = 0)
{
bool MemCtrlBase::add_mem_region(
uint32_t start_addr, uint32_t size, uint32_t dest_addr, uint32_t type, uint8_t init_val = 0) {
AddressMapEntry entry;
/* error if a memory region for the given range already exists */
if (find_range(start_addr) || find_range(start_addr + size))
return false;
uint8_t *reg_content = new uint8_t[size];
uint8_t* reg_content = new uint8_t[size];
this->mem_regions.push_back(reg_content);
@ -75,20 +72,17 @@ bool MemCtrlBase::add_mem_region(uint32_t start_addr, uint32_t size,
}
bool MemCtrlBase::add_rom_region(uint32_t start_addr, uint32_t size)
{
bool MemCtrlBase::add_rom_region(uint32_t start_addr, uint32_t size) {
return add_mem_region(start_addr, size, 0, RT_ROM);
}
bool MemCtrlBase::add_ram_region(uint32_t start_addr, uint32_t size)
{
bool MemCtrlBase::add_ram_region(uint32_t start_addr, uint32_t size) {
return add_mem_region(start_addr, size, 0, RT_RAM);
}
bool MemCtrlBase::add_mem_mirror(uint32_t start_addr, uint32_t dest_addr)
{
bool MemCtrlBase::add_mem_mirror(uint32_t start_addr, uint32_t dest_addr) {
AddressMapEntry entry, *ref_entry;
ref_entry = find_range(dest_addr);
@ -108,9 +102,8 @@ bool MemCtrlBase::add_mem_mirror(uint32_t start_addr, uint32_t dest_addr)
}
bool MemCtrlBase::set_data(uint32_t reg_addr, const uint8_t *data, uint32_t size)
{
AddressMapEntry *ref_entry;
bool MemCtrlBase::set_data(uint32_t reg_addr, const uint8_t* data, uint32_t size) {
AddressMapEntry* ref_entry;
uint32_t cpy_size;
ref_entry = find_range(reg_addr);
@ -124,9 +117,7 @@ bool MemCtrlBase::set_data(uint32_t reg_addr, const uint8_t *data, uint32_t size
}
bool MemCtrlBase::add_mmio_region(uint32_t start_addr, uint32_t size,
MMIODevice *dev_instance)
{
bool MemCtrlBase::add_mmio_region(uint32_t start_addr, uint32_t size, MMIODevice* dev_instance) {
AddressMapEntry entry;
/* error if another region for the given range already exists */

View File

@ -22,27 +22,27 @@ 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 */
RT_RAM = 2, /* random access memory */
RT_MMIO = 4, /* memory mapped I/O */
RT_MIRROR = 8 /* region mirror (content of another region is acessible
at some other address) */
RT_ROM = 1, /* read-only memory */
RT_RAM = 2, /* random access memory */
RT_MMIO = 4, /* memory mapped I/O */
RT_MIRROR = 8 /* region mirror (content of another region is acessible
at some other address) */
};
/** Defines the format for the address map entry. */
typedef struct AddressMapEntry {
uint32_t start; /* first address of the corresponding range */
uint32_t end; /* last address of the corresponding range */
uint32_t mirror; /* mirror address for RT_MIRROR */
uint32_t type; /* range type */
MMIODevice* devobj; /* pointer to device object */
unsigned char* mem_ptr; /* direct pointer to data for memory objects */
uint32_t start; /* first address of the corresponding range */
uint32_t end; /* last address of the corresponding range */
uint32_t mirror; /* mirror address for RT_MIRROR */
uint32_t type; /* range type */
MMIODevice* devobj; /* pointer to device object */
unsigned char* mem_ptr; /* direct pointer to data for memory objects */
} AddressMapEntry;
@ -55,18 +55,18 @@ public:
virtual bool add_ram_region(uint32_t start_addr, uint32_t size);
virtual bool add_mem_mirror(uint32_t start_addr, uint32_t dest_addr);
virtual bool add_mmio_region(uint32_t start_addr, uint32_t size, MMIODevice *dev_instance);
virtual bool add_mmio_region(uint32_t start_addr, uint32_t size, MMIODevice* dev_instance);
virtual bool set_data(uint32_t reg_addr, const uint8_t *data, uint32_t size);
virtual bool set_data(uint32_t reg_addr, const uint8_t* data, uint32_t size);
AddressMapEntry *find_range(uint32_t addr);
AddressMapEntry* find_range(uint32_t addr);
protected:
bool add_mem_region(uint32_t start_addr, uint32_t size, uint32_t dest_addr,
uint32_t type, uint8_t init_val);
bool add_mem_region(
uint32_t start_addr, uint32_t size, uint32_t dest_addr, uint32_t type, uint8_t init_val);
private:
std::vector<uint8_t *> mem_regions;
std::vector<uint8_t*> mem_regions;
std::vector<AddressMapEntry> address_map;
};

View File

@ -22,16 +22,16 @@ 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 {
public:
virtual uint32_t read(uint32_t reg_start, uint32_t offset, int size) = 0;
virtual uint32_t read(uint32_t reg_start, uint32_t offset, int size) = 0;
virtual void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size) = 0;
virtual ~MMIODevice() = default;
virtual ~MMIODevice() = default;
};
#endif /* MMIO_DEVICE_H */

View File

@ -24,20 +24,19 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
Author: Max Poliakovski
*/
#include <thirdparty/loguru/loguru.hpp>
#include <iostream>
#include <cstring>
#include <cinttypes>
#include <cstring>
#include <iostream>
#include <thirdparty/loguru/loguru.hpp>
#include "memreadwrite.h"
#include "memctrlbase.h"
#include "mmiodevice.h"
#include "hwcomponent.h"
#include "memctrlbase.h"
#include "memreadwrite.h"
#include "mmiodevice.h"
#include "mpc106.h"
MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle PCI host bridge")
{
MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle PCI host bridge") {
this->name = "Grackle";
/* add PCI/ISA I/O space, 64K for now */
@ -50,13 +49,11 @@ MPC106::MPC106() : MemCtrlBase(), PCIDevice("Grackle PCI host bridge")
this->io_space_devs.clear();
}
MPC106::~MPC106()
{
MPC106::~MPC106() {
this->pci_0_bus.clear();
}
bool MPC106::supports_type(HWCompType type)
{
bool MPC106::supports_type(HWCompType type) {
if (type == HWCompType::MEM_CTRL || type == HWCompType::MMIO_DEV ||
type == HWCompType::PCI_HOST || type == HWCompType::PCI_DEV) {
return true;
@ -65,8 +62,7 @@ bool MPC106::supports_type(HWCompType type)
}
}
uint32_t MPC106::read(uint32_t reg_start, uint32_t offset, int size)
{
uint32_t MPC106::read(uint32_t reg_start, uint32_t offset, int size) {
uint32_t result;
if (reg_start == 0xFE000000) {
@ -78,10 +74,9 @@ 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
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 {
if (this->config_addr & 0x80) // process only if bit E (enable) is set
} 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;
}
@ -129,13 +123,17 @@ uint32_t MPC106::pci_read(uint32_t size)
fun_num = (this->config_addr >> 16) & 0x07;
reg_offs = (this->config_addr >> 24) & 0xFC;
if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself
if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself
return this->pci_cfg_read(reg_offs, size);
} else {
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;
}
@ -158,25 +158,27 @@ void MPC106::pci_write(uint32_t value, uint32_t size)
fun_num = (this->config_addr >> 16) & 0x07;
reg_offs = (this->config_addr >> 24) & 0xFC;
if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself
if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself
this->pci_cfg_write(reg_offs, value, size);
} else {
if (this->pci_0_bus.count(dev_num)) {
this->pci_0_bus[dev_num]->pci_cfg_write(reg_offs, value, size);
} else {
LOG_F(ERROR, "%s err: write attempt to non-existing PCI device %d \n", \
this->name.c_str(), dev_num);
LOG_F(
ERROR,
"%s err: write attempt to non-existing PCI device %d \n",
this->name.c_str(),
dev_num);
}
}
}
uint32_t MPC106::pci_cfg_read(uint32_t reg_offs, uint32_t size)
{
uint32_t MPC106::pci_cfg_read(uint32_t reg_offs, uint32_t size) {
#ifdef MPC106_DEBUG
LOG_F(9, "read from Grackle register %08X\n", reg_offs);
#endif
switch(size) {
switch (size) {
case 1:
return this->my_pci_cfg_hdr[reg_offs];
break;
@ -193,26 +195,25 @@ uint32_t MPC106::pci_cfg_read(uint32_t reg_offs, uint32_t size)
return 0;
}
void MPC106::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size)
{
void MPC106::pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) {
#ifdef MPC106_DEBUG
LOG_F(9, "write %08X to Grackle register %08X\n", value, reg_offs);
#endif
// FIXME: implement write-protection for read-only registers
switch(size) {
switch (size) {
case 1:
this->my_pci_cfg_hdr[reg_offs] = value & 0xFF;
this->my_pci_cfg_hdr[reg_offs] = value & 0xFF;
break;
case 2:
this->my_pci_cfg_hdr[reg_offs] = (value >> 8) & 0xFF;
this->my_pci_cfg_hdr[reg_offs+1] = value & 0xFF;
this->my_pci_cfg_hdr[reg_offs] = (value >> 8) & 0xFF;
this->my_pci_cfg_hdr[reg_offs + 1] = value & 0xFF;
break;
case 4:
this->my_pci_cfg_hdr[reg_offs] = (value >> 24) & 0xFF;
this->my_pci_cfg_hdr[reg_offs+1] = (value >> 16) & 0xFF;
this->my_pci_cfg_hdr[reg_offs+2] = (value >> 8) & 0xFF;
this->my_pci_cfg_hdr[reg_offs+3] = value & 0xFF;
this->my_pci_cfg_hdr[reg_offs] = (value >> 24) & 0xFF;
this->my_pci_cfg_hdr[reg_offs + 1] = (value >> 16) & 0xFF;
this->my_pci_cfg_hdr[reg_offs + 2] = (value >> 8) & 0xFF;
this->my_pci_cfg_hdr[reg_offs + 3] = value & 0xFF;
break;
default:
LOG_F(ERROR, "MPC106 read error: invalid size parameter %d \n", size);
@ -226,9 +227,8 @@ 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)
{
if (this->pci_0_bus.count(dev_num)) // is dev_num already registered?
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;
this->pci_0_bus[dev_num] = dev_instance;
@ -242,31 +242,29 @@ 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;
uint8_t bank_en = this->my_pci_cfg_hdr[0xA0];
uint8_t bank_en = this->my_pci_cfg_hdr[0xA0];
for (int bank = 0; bank < 8; bank++) {
if (bank_en & (1 << bank)) {
if (bank < 4) {
mem_start = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x80]);
mem_start = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x80]);
ext_mem_start = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x88]);
mem_end = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x90]);
ext_mem_end = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x98]);
mem_end = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x90]);
ext_mem_end = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x98]);
} else {
mem_start = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x84]);
mem_start = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x84]);
ext_mem_start = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x8C]);
mem_end = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x94]);
ext_mem_end = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x9C]);
mem_end = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x94]);
ext_mem_end = READ_DWORD_LE_A(&this->my_pci_cfg_hdr[0x9C]);
}
bank_start = (((ext_mem_start >> bank * 8) & 3) << 30) |
(((mem_start >> bank * 8) & 0xFF) << 20);

View File

@ -35,17 +35,16 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#ifndef MPC106_H_
#define MPC106_H_
#include <cinttypes>
#include <unordered_map>
#include "hwcomponent.h"
#include "memctrlbase.h"
#include "mmiodevice.h"
#include "pcidevice.h"
#include "pcihost.h"
#include <cinttypes>
#include <unordered_map>
class MPC106 : public MemCtrlBase, public PCIDevice, public PCIHost
{
class MPC106 : public MemCtrlBase, public PCIDevice, public PCIHost {
public:
MPC106();
~MPC106();
@ -56,7 +55,7 @@ public:
void write(uint32_t reg_start, uint32_t offset, uint32_t value, int size);
/* PCI host bridge API */
bool pci_register_device(int dev_num, PCIDevice *dev_instance);
bool pci_register_device(int dev_num, PCIDevice* dev_instance);
protected:
/* PCI access */
@ -67,110 +66,102 @@ protected:
uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size);
void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size);
bool supports_io_space(void) { return true; };
bool supports_io_space(void) {
return true;
};
bool pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice *obj);
bool pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice* obj);
void setup_ram(void);
private:
uint8_t my_pci_cfg_hdr[256] = {
0x57, 0x10, // vendor ID: Motorola
0x02, 0x00, // device ID: MPC106
0x06, 0x00, // PCI command
0x80, 0x00, // PCI status
0x40, // revision ID: 4.0
0x00, // standard programming
0x00, // subclass code: host bridge
0x06, // class code: bridge device
0x08, // cache line size
0x00, // latency timer
0x00, // header type
0x00, // BIST Control
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0x00, //Interrupt line
0x00, //Interrupt pin
0x00, //MIN GNT
0x00, //MAX LAT
0x00, //Bus number
0x00, //Subordinate bus number
0x00, //Discount counter
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, //Performance monitor command
0x00, 0x00, //Performance monitor mode control
0x57, 0x10, // vendor ID: Motorola
0x02, 0x00, // device ID: MPC106
0x06, 0x00, // PCI command
0x80, 0x00, // PCI status
0x40, // revision ID: 4.0
0x00, // standard programming
0x00, // subclass code: host bridge
0x06, // class code: bridge device
0x08, // cache line size
0x00, // latency timer
0x00, // header type
0x00, // BIST Control
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, // Interrupt line
0x00, // Interrupt pin
0x00, // MIN GNT
0x00, // MAX LAT
0x00, // Bus number
0x00, // Subordinate bus number
0x00, // Discount counter
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // Performance monitor command
0x00, 0x00, // Performance monitor mode control
0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, //Performance monitor counter 0
0x00, 0x00, 0x00, 0x00, //Performance monitor counter 1
0x00, 0x00, 0x00, 0x00, //Performance monitor counter 2
0x00, 0x00, 0x00, 0x00, //Performance monitor counter 3
0x00, 0x00, 0x00, 0x00, // Performance monitor counter 0
0x00, 0x00, 0x00, 0x00, // Performance monitor counter 1
0x00, 0x00, 0x00, 0x00, // Performance monitor counter 2
0x00, 0x00, 0x00, 0x00, // Performance monitor counter 3
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF,
0x00, 0x00, //Power mgt config 1
0x00, //Power mgt config 2
0xCD, //default value for ODCR
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //Memory Starting Address
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //Extended Memory Starting Address
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //Memory Ending Address
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //Extended Memory Ending Address
0x00, 0x00, // Power mgt config 1
0x00, // Power mgt config 2
0xCD, // default value for ODCR
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, // Memory Starting Address
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Extended Memory Starting Address
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Memory Ending Address
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Extended Memory Ending Address
0x00, //Memory bank enable
0x00, // Memory bank enable
0xFF, 0xFF,
0x00, //Memory page mode
0x00, // Memory page mode
0xFF, 0xFF, 0xFF, 0xFF,
0x10, 0x00, 0x00, 0xFF, // PICR1
0x0C, 0x06, 0x0C, 0x00, // PICR2
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0x00, //ECC single-bit error counter
0x00, //ECC single-bit error trigger
0x04, //Alternate OS visible paramaters 1
0x01, //Alternate OS visible paramaters 2
0x10, 0x00, 0x00, 0xFF, // PICR1
0x0C, 0x06, 0x0C, 0x00, // PICR2
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, // ECC single-bit error counter
0x00, // ECC single-bit error trigger
0x04, // Alternate OS visible paramaters 1
0x01, // Alternate OS visible paramaters 2
0xFF, 0xFF, 0xFF, 0xFF,
0x01, //Error enabling 1
0x00, //Error detection 1
0x01, // Error enabling 1
0x00, // Error detection 1
0xFF,
0x00, //60x bus error status
0x00, //Error enabling 2
0x00, //Error detection 2
0x00, // 60x bus error status
0x00, // Error enabling 2
0x00, // Error detection 2
0xFF,
0x00, //PCI bus error status
0x00, 0x00, 0x00, 0x00, //60x/PCI ERROR address
0x00, // PCI bus error status
0x00, 0x00, 0x00, 0x00, // 60x/PCI ERROR address
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF,
0x42, 0x00, 0xFF, 0x0F, //Emulation support config 1
0x00, 0x00, 0x00, 0x00, //Modified memory status (no clear)
0x20, 0x00, 0x00, 0x00, //Emulation support config 2
0x00, 0x00, 0x00, 0x00, //Modified memory status (clear)
0x42, 0x00, 0xFF, 0x0F, // Emulation support config 1
0x00, 0x00, 0x00, 0x00, // Modified memory status (no clear)
0x20, 0x00, 0x00, 0x00, // Emulation support config 2
0x00, 0x00, 0x00, 0x00, // Modified memory status (clear)
0x00, 0x00, 0x02, 0xFF, //Memory ctrl config 1
0x03, 0x00, 0x00, 0x00, //Memory ctrl config 2
0x00, 0x00, 0x00, 0x00, //Memory ctrl config 3
0x00, 0x00, 0x10, 0x00 //Memory ctrl config 4
0x00, 0x00, 0x02, 0xFF, // Memory ctrl config 1
0x03, 0x00, 0x00, 0x00, // Memory ctrl config 2
0x00, 0x00, 0x00, 0x00, // Memory ctrl config 3
0x00, 0x00, 0x10, 0x00 // Memory ctrl config 4
};
uint32_t config_addr;
//uint32_t config_data;
// uint32_t config_data;
std::unordered_map<int, PCIDevice*> pci_0_bus;
std::vector<PCIDevice*> io_space_devs;

View File

@ -19,12 +19,12 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <thirdparty/loguru/loguru.hpp>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cinttypes>
#include "nvram.h"
#include <cinttypes>
#include <cstring>
#include <fstream>
#include <iostream>
#include <thirdparty/loguru/loguru.hpp>
/** @file Non-volatile RAM implementation.
*/
@ -34,8 +34,7 @@ using namespace std;
/** the signature for NVRAM backing file identification. */
static char NVRAM_FILE_ID[] = "DINGUSPPCNVRAM";
NVram::NVram(std::string file_name, uint32_t ram_size)
{
NVram::NVram(std::string file_name, uint32_t ram_size) {
this->file_name = file_name;
this->ram_size = ram_size;
@ -44,35 +43,30 @@ 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;
}
void NVram::init() {
char sig[sizeof(NVRAM_FILE_ID)];
char sig[sizeof(NVRAM_FILE_ID)];
uint16_t data_size;
ifstream f(this->file_name, ios::in | ios::binary);
if (f.fail() || !f.read(sig, sizeof(NVRAM_FILE_ID)) || \
!f.read((char *)&data_size, sizeof(data_size)) || \
memcmp(sig, NVRAM_FILE_ID, sizeof(NVRAM_FILE_ID)) || \
data_size != this->ram_size || \
!f.read((char *)this->storage, this->ram_size))
{
if (f.fail() || !f.read(sig, sizeof(NVRAM_FILE_ID)) ||
!f.read((char*)&data_size, sizeof(data_size)) ||
memcmp(sig, NVRAM_FILE_ID, sizeof(NVRAM_FILE_ID)) || data_size != this->ram_size ||
!f.read((char*)this->storage, this->ram_size)) {
LOG_F(WARNING, "Could not restore NVRAM content from the given file. \n");
memset(this->storage, 0, sizeof(this->ram_size));
}
@ -80,16 +74,15 @@ void NVram::init() {
f.close();
}
void NVram::save()
{
void NVram::save() {
ofstream f(this->file_name, ios::out | ios::binary);
/* write file identification */
f.write(NVRAM_FILE_ID, sizeof(NVRAM_FILE_ID));
f.write((char *)&this->ram_size, sizeof(this->ram_size));
f.write((char*)&this->ram_size, sizeof(this->ram_size));
/* write NVRAM content */
f.write((char *)this->storage, this->ram_size);
f.write((char*)this->storage, this->ram_size);
f.close();
}

View File

@ -22,8 +22,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#ifndef NVRAM_H
#define NVRAM_H
#include <string>
#include <cinttypes>
#include <string>
/** @file Non-volatile RAM emulation.
@ -31,22 +31,21 @@ 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();
uint8_t read_byte(uint32_t offset);
void write_byte(uint32_t offset, uint8_t value);
void write_byte(uint32_t offset, uint8_t value);
private:
std::string file_name; /* file name for the backing file. */
uint16_t ram_size; /* NVRAM size. */
uint8_t* storage;
uint16_t ram_size; /* NVRAM size. */
uint8_t* storage;
void init();
void save();
void init();
void save();
};
#endif /* NVRAM_H */

View File

@ -22,51 +22,57 @@ 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)
/** PCI configuration space registers offsets */
enum {
CFG_REG_CMD = 0x04, // command/status register
CFG_REG_BAR0 = 0x10, // base address register 0
CFG_REG_BAR1 = 0x14, // base address register 1
CFG_REG_BAR2 = 0x18, // base address register 2
CFG_REG_BAR3 = 0x1C, // base address register 3
CFG_REG_BAR4 = 0x20, // base address register 4
CFG_REG_BAR5 = 0x24, // base address register 5
CFG_EXP_BASE = 0x30, // expansion ROM base
CFG_REG_CMD = 0x04, // command/status register
CFG_REG_BAR0 = 0x10, // base address register 0
CFG_REG_BAR1 = 0x14, // base address register 1
CFG_REG_BAR2 = 0x18, // base address register 2
CFG_REG_BAR3 = 0x1C, // base address register 3
CFG_REG_BAR4 = 0x20, // base address register 4
CFG_REG_BAR5 = 0x24, // base address register 5
CFG_EXP_BASE = 0x30, // expansion ROM base
};
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 uint32_t pci_cfg_read(uint32_t reg_offs, uint32_t size) = 0;
virtual void pci_cfg_write(uint32_t reg_offs, uint32_t value, uint32_t size) = 0;
virtual void set_host(PCIHost* host_instance) { this->host_instance = host_instance; };
virtual void set_host(PCIHost* host_instance) {
this->host_instance = host_instance;
};
protected:
std::string pci_name; // human-readable device name
PCIHost *host_instance; // host bridge instance to call back
uint32_t base_addr; // base address register 0
std::string pci_name; // human-readable device name
PCIHost* host_instance; // host bridge instance to call back
uint32_t base_addr; // base address register 0
};
#endif /* PCI_DEVICE_H */

View File

@ -3,13 +3,12 @@
#include <cinttypes>
class PCIDevice; // forward declaration to prevent errors
class PCIDevice; // forward declaration to prevent errors
class PCIHost {
public:
virtual bool pci_register_device(int dev_num, PCIDevice *dev_instance) = 0;
virtual bool pci_register_mmio_region(uint32_t start_addr, uint32_t size,
PCIDevice *obj) = 0;
virtual bool pci_register_device(int dev_num, PCIDevice* dev_instance) = 0;
virtual bool pci_register_mmio_region(uint32_t start_addr, uint32_t size, PCIDevice* obj) = 0;
};
#endif /* PCI_HOST_H */

View File

@ -47,31 +47,31 @@ 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 {
public:
SpdSdram168(uint8_t addr) {
this->dev_addr = addr;
this->pos = 0;
this->pos = 0;
};
~SpdSdram168() = default;
bool supports_type(HWCompType type) { return type == HWCompType::RAM; };
bool supports_type(HWCompType type) {
return type == HWCompType::RAM;
};
void set_capacity(int capacity_megs) {
switch(capacity_megs) {
switch (capacity_megs) {
case 32:
this->eeprom_data[3] = 0xC; /* 12 rows */
this->eeprom_data[4] = 0x8; /* 8 columns */
@ -95,11 +95,12 @@ public:
default:
throw std::invalid_argument(std::string("Unsupported capacity!"));
}
LOG_F(INFO, "SDRAM capacity set to %dMB, I2C addr = 0x%X",
capacity_megs, this->dev_addr);
LOG_F(INFO, "SDRAM capacity set to %dMB, I2C addr = 0x%X", capacity_megs, this->dev_addr);
};
void start_transaction() { this->pos = 0; };
void start_transaction() {
this->pos = 0;
};
bool send_subaddress(uint8_t sub_addr) {
this->pos = sub_addr;
@ -112,7 +113,7 @@ public:
return true;
};
bool receive_byte(uint8_t *p_data) {
bool receive_byte(uint8_t* p_data) {
if (this->pos >= this->eeprom_data[0]) {
this->pos = 0; /* attempt to read past SPD data should wrap around */
}
@ -123,18 +124,18 @@ public:
private:
uint8_t dev_addr; /* I2C address */
int pos; /* actual read position */
int pos; /* actual read position */
/* EEPROM content */
uint8_t eeprom_data[256] = {
128, /* number of bytes present */
8, /* log2(EEPROM size) */
128, /* number of bytes present */
8, /* log2(EEPROM size) */
RAMType::SDRAM, /* memory type */
/* the following fields will be set up in set_capacity() */
0, /* number of row addresses */
0, /* number of column addresses */
0 /* number of banks */
0 /* number of banks */
};
};

View File

@ -24,15 +24,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
Author: Max Poliakovski 2019
*/
#include <thirdparty/loguru/loguru.hpp>
#include <cinttypes>
#include "viacuda.h"
#include "adb.h"
#include <cinttypes>
#include <thirdparty/loguru/loguru.hpp>
using namespace std;
ViaCuda::ViaCuda()
{
ViaCuda::ViaCuda() {
this->name = "ViaCuda";
/* FIXME: is this the correct
@ -44,7 +43,7 @@ ViaCuda::ViaCuda()
this->via_regs[VIA_T1LH] = 0xFF;
this->via_regs[VIA_IER] = 0x7F;
//PRAM Pre-Initialization
// PRAM Pre-Initialization
this->pram_obj = new NVram("pram.bin", 256);
this->adb_obj = new ADB_Bus();
@ -52,14 +51,12 @@ ViaCuda::ViaCuda()
this->init();
}
ViaCuda::~ViaCuda()
{
ViaCuda::~ViaCuda() {
if (this->pram_obj)
delete (this->pram_obj);
}
void ViaCuda::init()
{
void ViaCuda::init() {
this->old_tip = 0;
this->old_byteack = 0;
this->treq = 1;
@ -68,8 +65,7 @@ void ViaCuda::init()
this->poll_rate = 11;
}
uint8_t ViaCuda::read(int reg)
{
uint8_t ViaCuda::read(int reg) {
uint8_t res;
LOG_F(9, "Read VIA reg %x \n", (uint32_t)reg);
@ -92,8 +88,7 @@ uint8_t ViaCuda::read(int reg)
return res;
}
void ViaCuda::write(int reg, uint8_t value)
{
void ViaCuda::write(int reg, uint8_t value) {
switch (reg & 0xF) {
case VIA_B:
this->via_regs[VIA_B] = value;
@ -120,8 +115,7 @@ void ViaCuda::write(int reg, uint8_t value)
this->via_regs[VIA_ACR] = value;
break;
case VIA_IER:
this->via_regs[VIA_IER] = (value & 0x80) ? value & 0x7F
: this->via_regs[VIA_IER] & ~value;
this->via_regs[VIA_IER] = (value & 0x80) ? value & 0x7F : this->via_regs[VIA_IER] & ~value;
LOG_F(INFO, "VIA_IER updated to %d \n", (uint32_t)this->via_regs[VIA_IER]);
print_enabled_ints();
break;
@ -130,9 +124,8 @@ void ViaCuda::write(int reg, uint8_t value)
}
}
void ViaCuda::print_enabled_ints()
{
const char *via_int_src[] = { "CA2", "CA1", "SR", "CB2", "CB1", "T2", "T1" };
void ViaCuda::print_enabled_ints() {
const char* via_int_src[] = {"CA2", "CA1", "SR", "CB2", "CB1", "T2", "T1"};
for (int i = 0; i < 7; i++) {
if (this->via_regs[VIA_IER] & (1 << i))
@ -140,24 +133,21 @@ 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;
}
int new_tip = !!(new_state & CUDA_TIP);
int new_tip = !!(new_state & CUDA_TIP);
int new_byteack = !!(new_state & CUDA_BYTEACK);
/* return if there is no state change */
@ -166,7 +156,7 @@ void ViaCuda::write(uint8_t new_state)
LOG_F(9, "Cuda state changed! \n");
this->old_tip = new_tip;
this->old_tip = new_tip;
this->old_byteack = new_byteack;
if (new_tip) {
@ -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->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,33 +220,30 @@ void ViaCuda::out_buf_handler()
}
}
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 */
this->out_count = 3;
this->out_pos = 0;
this->out_handler = &ViaCuda::out_buf_handler;
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 */
this->out_count = 3;
this->out_pos = 0;
this->out_handler = &ViaCuda::out_buf_handler;
this->next_out_handler = &ViaCuda::null_out_handler;
this->is_open_ended = false;
this->is_open_ended = false;
}
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];
this->out_buf[3] = this->in_buf[1]; /* copy original cmd */
this->out_count = 4;
this->out_pos = 0;
this->out_handler = &ViaCuda::out_buf_handler;
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];
this->out_buf[3] = this->in_buf[1]; /* copy original cmd */
this->out_count = 4;
this->out_pos = 0;
this->out_handler = &ViaCuda::out_buf_handler;
this->next_out_handler = &ViaCuda::null_out_handler;
this->is_open_ended = false;
this->is_open_ended = false;
}
void ViaCuda::process_packet()
{
void ViaCuda::process_packet() {
if (this->in_count < 2) {
LOG_F(ERROR, "Cuda: invalid packet (too few data)!\n");
error_response(CUDA_ERR_BAD_SIZE);
@ -291,57 +270,48 @@ void ViaCuda::process_packet()
}
}
void ViaCuda::process_adb_command(uint8_t cmd_byte, int data_count)
{
int adb_dev = cmd_byte >> 4; //2 for keyboard, 3 for mouse
int cmd = cmd_byte & 0xF;
void ViaCuda::process_adb_command(uint8_t cmd_byte, int data_count) {
int adb_dev = cmd_byte >> 4; // 2 for keyboard, 3 for mouse
int cmd = cmd_byte & 0xF;
if(!cmd) {
if (!cmd) {
LOG_F(9, "Cuda: ADB SendReset command requested\n");
response_header(CUDA_PKT_ADB, 0);
}
else if (cmd == 1) {
} else if (cmd == 1) {
LOG_F(9, "Cuda: ADB Flush command requested\n");
response_header(CUDA_PKT_ADB, 0);
}
else if ((cmd & 0xC) == 8) {
} else if ((cmd & 0xC) == 8) {
LOG_F(9, "Cuda: ADB Listen command requested\n");
int adb_reg = cmd_byte & 0x3;
if (adb_obj->listen(adb_dev, adb_reg)){
if (adb_obj->listen(adb_dev, adb_reg)) {
response_header(CUDA_PKT_ADB, 0);
for (int data_ptr = 0; data_ptr < adb_obj->get_output_len(); data_ptr++) {
this->in_buf[(2 + data_ptr)] = adb_obj->get_output_byte(data_ptr);
}
}
else {
} else {
response_header(CUDA_PKT_ADB, 2);
}
}
else if ((cmd & 0xC) == 0xC) {
} else if ((cmd & 0xC) == 0xC) {
LOG_F(9, "Cuda: ADB Talk command requested\n");
response_header(CUDA_PKT_ADB, 0);
int adb_reg = cmd_byte & 0x3;
if (adb_obj->talk(adb_dev, adb_reg, this->in_buf[2])) {
response_header(CUDA_PKT_ADB, 0);
}
else {
} else {
response_header(CUDA_PKT_ADB, 2);
}
}
else {
} else {
LOG_F(ERROR, "Cuda: unsupported ADB command 0x%x \n", cmd);
error_response(CUDA_ERR_BAD_CMD);
}
}
void ViaCuda::pseudo_command(int cmd, int data_count)
{
void ViaCuda::pseudo_command(int cmd, int data_count) {
switch (cmd) {
case CUDA_START_STOP_AUTOPOLL:
if (this->in_buf[2]) {
LOG_F(INFO, "Cuda: autopoll started, rate: %dms", this->poll_rate);
}
else {
} else {
LOG_F(INFO, "Cuda: autopoll stopped");
}
response_header(CUDA_PKT_PSEUDO, 0);
@ -371,8 +341,8 @@ void ViaCuda::pseudo_command(int cmd, int data_count)
case CUDA_COMB_FMT_I2C:
response_header(CUDA_PKT_PSEUDO, 0);
if (this->in_count >= 5) {
i2c_comb_transaction(this->in_buf[2], this->in_buf[3], this->in_buf[4],
&this->in_buf[5], this->in_count - 5);
i2c_comb_transaction(
this->in_buf[2], this->in_buf[3], this->in_buf[4], &this->in_buf[5], this->in_count - 5);
}
break;
case CUDA_OUT_PB0: /* undocumented call! */
@ -386,14 +356,11 @@ void ViaCuda::pseudo_command(int cmd, int data_count)
}
/* sends data from the current I2C to host ad infinitum */
void ViaCuda::i2c_handler()
{
void ViaCuda::i2c_handler() {
this->receive_byte(this->curr_i2c_addr, &this->via_regs[VIA_SR]);
}
void ViaCuda::i2c_simple_transaction(uint8_t dev_addr, const uint8_t* in_buf,
int in_bytes)
{
void ViaCuda::i2c_simple_transaction(uint8_t dev_addr, const uint8_t* in_buf, int in_bytes) {
int op_type = dev_addr & 1; /* 0 - write to device, 1 - read from device */
dev_addr >>= 1; /* strip RD/WR bit */
@ -415,16 +382,15 @@ void ViaCuda::i2c_simple_transaction(uint8_t dev_addr, const uint8_t* in_buf,
}
if (op_type) { /* read request initiate an open ended transaction */
this->curr_i2c_addr = dev_addr;
this->out_handler = &ViaCuda::out_buf_handler;
this->curr_i2c_addr = dev_addr;
this->out_handler = &ViaCuda::out_buf_handler;
this->next_out_handler = &ViaCuda::i2c_handler;
this->is_open_ended = true;
this->is_open_ended = true;
}
}
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)) {
@ -460,9 +426,9 @@ void ViaCuda::i2c_comb_transaction(uint8_t dev_addr, uint8_t sub_addr,
if (!op_type) { /* return dummy response for writes */
LOG_F(WARNING, "Combined I2C - write request!");
} else {
this->curr_i2c_addr = dev_addr;
this->out_handler = &ViaCuda::out_buf_handler;
this->curr_i2c_addr = dev_addr;
this->out_handler = &ViaCuda::out_buf_handler;
this->next_out_handler = &ViaCuda::i2c_handler;
this->is_open_ended = true;
this->is_open_ended = true;
}
}

View File

@ -45,10 +45,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#ifndef VIACUDA_H
#define VIACUDA_H
#include "hwcomponent.h"
#include "nvram.h"
#include "adb.h"
#include "hwcomponent.h"
#include "i2c.h"
#include "nvram.h"
/** VIA register offsets. */
enum {
@ -88,14 +88,14 @@ enum {
/** Cuda pseudo commands. */
enum {
CUDA_START_STOP_AUTOPOLL = 0x01, /* start/stop device auto-polling */
CUDA_READ_PRAM = 0x07, /* read parameter RAM */
CUDA_WRITE_PRAM = 0x0C, /* write parameter RAM */
CUDA_SET_AUTOPOLL_RATE = 0x14, /* set auto-polling rate */
CUDA_GET_AUTOPOLL_RATE = 0x16, /* get auto-polling rate */
CUDA_READ_WRITE_I2C = 0x22, /* read/write I2C device */
CUDA_COMB_FMT_I2C = 0x25, /* combined format I2C transaction */
CUDA_OUT_PB0 = 0x26, /* output one bit to Cuda's PB0 line */
CUDA_START_STOP_AUTOPOLL = 0x01, /* start/stop device auto-polling */
CUDA_READ_PRAM = 0x07, /* read parameter RAM */
CUDA_WRITE_PRAM = 0x0C, /* write parameter RAM */
CUDA_SET_AUTOPOLL_RATE = 0x14, /* set auto-polling rate */
CUDA_GET_AUTOPOLL_RATE = 0x16, /* get auto-polling rate */
CUDA_READ_WRITE_I2C = 0x22, /* read/write I2C device */
CUDA_COMB_FMT_I2C = 0x25, /* combined format I2C transaction */
CUDA_OUT_PB0 = 0x26, /* output one bit to Cuda's PB0 line */
};
/** Cuda error codes. */
@ -107,8 +107,7 @@ enum {
};
class ViaCuda : public HWComponent, public I2CBus
{
class ViaCuda : public HWComponent, public I2CBus {
public:
ViaCuda();
~ViaCuda();
@ -134,7 +133,7 @@ private:
int32_t out_pos;
uint8_t poll_rate;
bool is_open_ended;
bool is_open_ended;
uint8_t curr_i2c_addr;
void (ViaCuda::*out_handler)(void);
@ -150,7 +149,7 @@ private:
void assert_sr_int();
void write(uint8_t new_state);
void response_header(uint32_t pkt_type, uint32_t pkt_flag);
//void cuda_response_packet();
// void cuda_response_packet();
void error_response(uint32_t error);
void process_packet();
void process_adb_command(uint8_t cmd_byte, int data_count);
@ -162,8 +161,8 @@ private:
/* I2C related methods */
void i2c_simple_transaction(uint8_t dev_addr, const uint8_t* in_buf, int in_bytes);
void i2c_comb_transaction(uint8_t dev_addr, uint8_t sub_addr, uint8_t dev_addr1,
const uint8_t* in_buf, int in_bytes);
void i2c_comb_transaction(
uint8_t dev_addr, uint8_t sub_addr, uint8_t dev_addr1, const uint8_t* in_buf, int in_bytes);
};
#endif /* VIACUDA_H */

View File

@ -1,14 +1,13 @@
#include "machinebase.h"
#include "devices/hwcomponent.h"
#include <memory>
#include <string>
#include <thirdparty/loguru/loguru.hpp>
#include "machinebase.h"
#include "devices/hwcomponent.h"
std::unique_ptr<MachineBase> gMachineObj = 0;
MachineBase::MachineBase(std::string name)
{
MachineBase::MachineBase(std::string name) {
this->name = name;
/* initialize internal maps */
@ -17,9 +16,8 @@ MachineBase::MachineBase(std::string name)
this->aliases.clear();
}
MachineBase::~MachineBase()
{
for(auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) {
MachineBase::~MachineBase() {
for (auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) {
delete it->second;
}
this->comp_map.clear();
@ -27,8 +25,7 @@ MachineBase::~MachineBase()
this->subdev_map.clear();
}
bool MachineBase::add_component(std::string name, HWComponent *dev_obj)
{
bool MachineBase::add_component(std::string name, HWComponent* dev_obj) {
if (this->comp_map.count(name)) {
LOG_F(ERROR, "Component %s already exists!", name.c_str());
return false;
@ -39,8 +36,7 @@ bool MachineBase::add_component(std::string name, HWComponent *dev_obj)
return true;
}
bool MachineBase::add_subdevice(std::string name, HWComponent *dev_obj)
{
bool MachineBase::add_subdevice(std::string name, HWComponent* dev_obj) {
if (this->subdev_map.count(name)) {
LOG_F(ERROR, "Subdevice %s already exists!", name.c_str());
return false;
@ -51,13 +47,11 @@ bool MachineBase::add_subdevice(std::string name, HWComponent *dev_obj)
return true;
}
void MachineBase::add_alias(std::string name, std::string alias)
{
void MachineBase::add_alias(std::string name, std::string alias) {
this->aliases[alias] = name;
}
HWComponent *MachineBase::get_comp_by_name(std::string name)
{
HWComponent* MachineBase::get_comp_by_name(std::string name) {
if (this->aliases.count(name)) {
name = this->aliases[name];
}
@ -73,15 +67,14 @@ HWComponent *MachineBase::get_comp_by_name(std::string name)
}
}
HWComponent *MachineBase::get_comp_by_type(HWCompType type)
{
HWComponent* MachineBase::get_comp_by_type(HWCompType type) {
std::string comp_name;
bool found = false;
for(auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) {
for (auto it = this->comp_map.begin(); it != this->comp_map.end(); it++) {
if (it->second->supports_type(type)) {
comp_name = it->first;
found = true;
found = true;
break;
}
}
@ -90,10 +83,10 @@ HWComponent *MachineBase::get_comp_by_type(HWCompType type)
return this->get_comp_by_name(comp_name);
}
for(auto it = this->subdev_map.begin(); it != this->subdev_map.end(); it++) {
for (auto it = this->subdev_map.begin(); it != this->subdev_map.end(); it++) {
if (it->second->supports_type(type)) {
comp_name = it->first;
found = true;
found = true;
break;
}
}

View File

@ -27,27 +27,26 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#ifndef MACHINE_BASE_H
#define MACHINE_BASE_H
#include "devices/hwcomponent.h"
#include <map>
#include <memory>
#include <string>
#include <map>
#include "devices/hwcomponent.h"
class MachineBase
{
class MachineBase {
public:
MachineBase(std::string name);
~MachineBase();
bool add_component(std::string name, HWComponent *dev_obj);
bool add_subdevice(std::string name, HWComponent *dev_obj);
bool add_component(std::string name, HWComponent* dev_obj);
bool add_subdevice(std::string name, HWComponent* dev_obj);
void add_alias(std::string name, std::string alias);
HWComponent *get_comp_by_name(std::string name);
HWComponent *get_comp_by_type(HWCompType type);
HWComponent* get_comp_by_name(std::string name);
HWComponent* get_comp_by_type(HWCompType type);
private:
std::string name;
std::map<std::string, HWComponent *>comp_map;
std::map<std::string, HWComponent *>subdev_map;
std::map<std::string, HWComponent*> comp_map;
std::map<std::string, HWComponent*> subdev_map;
std::map<std::string, std::string> aliases;
};

View File

@ -24,15 +24,15 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
Author: Max Poliakovski
*/
#include <map>
#include <cinttypes>
#include <cstring>
#include <iostream>
#include <fstream>
#include <thirdparty/loguru/loguru.hpp>
#include "memreadwrite.h"
#include "machinefactory.h"
#include "devices/memctrlbase.h"
#include "memreadwrite.h"
#include <cinttypes>
#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
#include <thirdparty/loguru/loguru.hpp>
using namespace std;
@ -43,61 +43,58 @@ using namespace std;
or 0x30C064 (Nubus Macs).
*/
static const map<uint32_t, string> rom_identity = {
{0x416C6368, "Performa 6400"}, //Alchemy
{0x416C6368, "Performa 6400"}, // Alchemy
//{"Come", "PowerBook 2400"}, //Comet
{0x436F7264, "Power Mac 5200/6200 series"}, //Cordyceps
{0x47617A65, "Power Mac 6500"}, //Gazelle
{0x476F7373, "Power Mac G3 Beige"}, //Gossamer
{0x436F7264, "Power Mac 5200/6200 series"}, // Cordyceps
{0x47617A65, "Power Mac 6500"}, // Gazelle
{0x476F7373, "Power Mac G3 Beige"}, // Gossamer
{0x47525820, "PowerBook G3 Wallstreet"},
//{"Hoop", "PowerBook 3400"}, //Hooper
{0x50425820, "PowerBook Pre-G3"},
{0x50444D20, "Nubus Power Mac or WGS"}, //Piltdown Man (6100/7100/8100)
{0x50697020, "Bandai Pippin"}, //Pippin
{0x50444D20, "Nubus Power Mac or WGS"}, // Piltdown Man (6100/7100/8100)
{0x50697020, "Bandai Pippin"}, // Pippin
//{"Powe", "Generic Power Mac"}, //PowerMac?
//{"Spar", "20th Anniversay Mac"}, //Spartacus
{0x544E5420, "Power Mac 7xxxx/8xxx series"}, //Trinitrotoluene :-)
{0x5A616E7A, "Power Mac 4400/7220"}, //Zanzibar
{0x544E5420, "Power Mac 7xxxx/8xxx series"}, // Trinitrotoluene :-)
{0x5A616E7A, "Power Mac 4400/7220"}, // Zanzibar
//{"????", "A clone, perhaps?"} //N/A (Placeholder ID)
};
int create_machine_for_id(uint32_t id)
{
switch(id) {
case 0x476F7373:
create_gossamer();
break;
default:
LOG_F(ERROR, "Unknown machine ID: %X", id);
return -1;
int create_machine_for_id(uint32_t id) {
switch (id) {
case 0x476F7373:
create_gossamer();
break;
default:
LOG_F(ERROR, "Unknown machine ID: %X", id);
return -1;
}
return 0;
}
/* Read ROM file content and transfer it to the dedicated ROM region */
void load_rom(ifstream& rom_file, uint32_t file_size)
{
unsigned char *sysrom_mem = new unsigned char[file_size];
void load_rom(ifstream& rom_file, uint32_t file_size) {
unsigned char* sysrom_mem = new unsigned char[file_size];
rom_file.seekg(0, ios::beg);
rom_file.read((char *)sysrom_mem, file_size);
rom_file.read((char*)sysrom_mem, file_size);
MemCtrlBase *mem_ctrl = dynamic_cast<MemCtrlBase *>
(gMachineObj->get_comp_by_type(HWCompType::MEM_CTRL));
MemCtrlBase* mem_ctrl = dynamic_cast<MemCtrlBase*>(
gMachineObj->get_comp_by_type(HWCompType::MEM_CTRL));
mem_ctrl->set_data(0xFFC00000, sysrom_mem, file_size);
delete[] sysrom_mem;
}
int create_machine_for_rom(const char* rom_filepath)
{
int create_machine_for_rom(const char* rom_filepath) {
ifstream rom_file;
uint32_t file_size, config_info_offset, rom_id;
char rom_id_str[17];
rom_file.open(rom_filepath, ios::in|ios::binary);
rom_file.open(rom_filepath, ios::in | ios::binary);
if (rom_file.fail()) {
LOG_F(ERROR, "Cound not open the specified ROM file.");
rom_file.close();
@ -108,7 +105,7 @@ int create_machine_for_rom(const char* rom_filepath)
file_size = rom_file.tellg();
rom_file.seekg(0, rom_file.beg);
if (file_size != 0x400000UL){
if (file_size != 0x400000UL) {
LOG_F(ERROR, "Unxpected ROM File size. Expected size is 4 megabytes.");
rom_file.close();
return -1;
@ -117,7 +114,7 @@ int create_machine_for_rom(const char* rom_filepath)
/* read config info offset from file */
config_info_offset = 0;
rom_file.seekg(0x300080, ios::beg);
rom_file.read((char *)&config_info_offset, 4);
rom_file.read((char*)&config_info_offset, 4);
config_info_offset = READ_DWORD_BE_A(&config_info_offset);
/* rewind to ConfigInfo.BootstrapVersion field */
@ -135,8 +132,7 @@ int create_machine_for_rom(const char* rom_filepath)
}
/* convert BootstrapVersion string to ROM ID */
rom_id = (rom_id_str[5] << 24) | (rom_id_str[6] << 16) |
(rom_id_str[7] << 8) | rom_id_str[8];
rom_id = (rom_id_str[5] << 24) | (rom_id_str[6] << 16) | (rom_id_str[7] << 8) | rom_id_str[8];
LOG_F(INFO, "The machine is identified as... %s\n", rom_identity.at(rom_id).c_str());

View File

@ -24,33 +24,31 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
Author: Max Poliakovski
*/
#include <thirdparty/loguru/loguru.hpp>
#include "machinebase.h"
#include "cpu/ppc/ppcemu.h"
#include "devices/mpc106.h"
#include "devices/atirage.h"
#include "devices/machineid.h"
#include "devices/macio.h"
#include "devices/viacuda.h"
#include "devices/mpc106.h"
#include "devices/spdram.h"
#include "devices/atirage.h"
#include "devices/viacuda.h"
#include "machinebase.h"
#include <thirdparty/loguru/loguru.hpp>
static void setup_ram_slot(std::string name, int i2c_addr, int capacity_megs)
{
static void setup_ram_slot(std::string name, int i2c_addr, int capacity_megs) {
if (!capacity_megs)
return;
gMachineObj->add_component(name, new SpdSdram168(i2c_addr));
SpdSdram168 *ram_dimm = dynamic_cast<SpdSdram168 *>(gMachineObj->get_comp_by_name(name));
SpdSdram168* ram_dimm = dynamic_cast<SpdSdram168*>(gMachineObj->get_comp_by_name(name));
ram_dimm->set_capacity(capacity_megs);
/* register RAM DIMM with the I2C bus */
I2CBus *i2c_bus = dynamic_cast<I2CBus *>(gMachineObj->get_comp_by_type(HWCompType::I2C_HOST));
I2CBus* i2c_bus = dynamic_cast<I2CBus*>(gMachineObj->get_comp_by_type(HWCompType::I2C_HOST));
i2c_bus->register_device(i2c_addr, ram_dimm);
}
int create_gossamer()
{
int create_gossamer() {
if (gMachineObj) {
LOG_F(ERROR, "Global machine object not empty!");
return -1;
@ -66,17 +64,17 @@ int create_gossamer()
gMachineObj->add_alias("Grackle", "PCI_Host");
/* get raw pointer to MPC106 object */
MPC106 *grackle_obj = dynamic_cast<MPC106 *>(gMachineObj->get_comp_by_name("Grackle"));
MPC106* grackle_obj = dynamic_cast<MPC106*>(gMachineObj->get_comp_by_name("Grackle"));
/* add the machine ID register */
gMachineObj->add_component("MachineID", new GossamerID(0x3d8c));
grackle_obj->add_mmio_region(0xFF000004, 4096,
dynamic_cast<MMIODevice *>(gMachineObj->get_comp_by_name("MachineID")));
grackle_obj->add_mmio_region(
0xFF000004, 4096, dynamic_cast<MMIODevice*>(gMachineObj->get_comp_by_name("MachineID")));
/* add the Heathrow I/O controller */
gMachineObj->add_component("Heathrow", new HeathrowIC);
grackle_obj->pci_register_device(16,
dynamic_cast<PCIDevice *>(gMachineObj->get_comp_by_name("Heathrow")));
grackle_obj->pci_register_device(
16, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("Heathrow")));
/* allocate ROM region */
if (!grackle_obj->add_rom_region(0xFFC00000, 0x400000)) {
@ -85,14 +83,14 @@ int create_gossamer()
}
/* configure RAM slots */
setup_ram_slot("RAM_DIMM_1", 0x57, 64); /* RAM slot 1 -> 64MB by default */
setup_ram_slot("RAM_DIMM_2", 0x56, 0); /* RAM slot 2 -> empty by default */
setup_ram_slot("RAM_DIMM_3", 0x55, 0); /* RAM slot 3 -> empty by default */
setup_ram_slot("RAM_DIMM_1", 0x57, 64); /* RAM slot 1 -> 64MB by default */
setup_ram_slot("RAM_DIMM_2", 0x56, 0); /* RAM slot 2 -> empty by default */
setup_ram_slot("RAM_DIMM_3", 0x55, 0); /* RAM slot 3 -> empty by default */
/* register ATI 3D Rage Pro video card with the PCI host bridge */
gMachineObj->add_component("ATIRage", new ATIRage(ATI_RAGE_PRO_DEV_ID));
grackle_obj->pci_register_device(18,
dynamic_cast<PCIDevice *>(gMachineObj->get_comp_by_name("ATIRage")));
grackle_obj->pci_register_device(
18, dynamic_cast<PCIDevice*>(gMachineObj->get_comp_by_name("ATIRage")));
/* Init virtual CPU and request MPC750 CPU aka G3 */
ppc_cpu_init(grackle_obj, PPC_VER::MPC750);

View File

@ -19,26 +19,24 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
//The main runfile - main.cpp
//This is where the magic begins
// The main runfile - main.cpp
// This is where the magic begins
#include <thirdparty/loguru/loguru.hpp>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
#include <cinttypes>
#include <stdio.h>
#include "ppcemu.h"
#include "debugger/debugger.h"
#include "machines/machinefactory.h"
#include "ppcemu.h"
#include <cinttypes>
#include <cstring>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <thirdparty/SDL2/include/SDL.h>
#include <thirdparty/loguru/loguru.hpp>
using namespace std;
int main(int argc, char **argv)
{
int main(int argc, char** argv) {
std::cout << "DingusPPC - Prototype 5bf4 (7/14/2019) " << endl;
std::cout << "Written by divingkatae, (c) 2019. " << endl;
std::cout << "This is not intended for general use. " << endl;
@ -48,19 +46,17 @@ int main(int argc, char **argv)
string checker = argv[1];
cout << checker << endl;
if ((checker == "1") || (checker == "realtime") || \
(checker == "-realtime") || (checker == "/realtime")) {
if ((checker == "1") || (checker == "realtime") || (checker == "-realtime") ||
(checker == "/realtime")) {
loguru::g_stderr_verbosity = loguru::Verbosity_OFF;
loguru::g_preamble_date = false;
loguru::g_preamble_time = false;
loguru::g_preamble_thread = false;
loguru::init(argc, argv);
loguru::add_file("dingusppc.log", loguru::Append, 0);
//Replace the above line with this for maximum debugging detail:
//loguru::add_file("dingusppc.log", loguru::Append, loguru::Verbosity_MAX);
}
else if ((checker == "debugger") || (checker == "/debugger") ||
(checker == "-debugger")) {
// Replace the above line with this for maximum debugging detail:
// loguru::add_file("dingusppc.log", loguru::Append, loguru::Verbosity_MAX);
} else if ((checker == "debugger") || (checker == "/debugger") || (checker == "-debugger")) {
loguru::g_stderr_verbosity = 0;
loguru::g_preamble_date = false;
loguru::g_preamble_time = false;
@ -87,26 +83,20 @@ int main(int argc, char **argv)
config_output.write("video_card=0x4750\n", 19);
config_output.close();
}
else {
} else {
while (std::getline(config_input, line)) {
sin.str(line.substr(line.find("=") + 1));
if (line.find("rompath") != std::string::npos) {
sin >> rom_file;
}
else if (line.find("diskpath") != std::string::npos) {
} else if (line.find("diskpath") != std::string::npos) {
sin >> disk_file;
}
else if (line.find("ramsize") != std::string::npos) {
} else if (line.find("ramsize") != std::string::npos) {
sin >> ram_size;
}
else if (line.find("machine_gestalt") != std::string::npos) {
} else if (line.find("machine_gestalt") != std::string::npos) {
sin >> machine_gestalt;
}
else if (line.find("video_vendor") != std::string::npos) {
} else if (line.find("video_vendor") != std::string::npos) {
sin >> video_card_vendor;
}
else if (line.find("video_card") != std::string::npos) {
} else if (line.find("video_card") != std::string::npos) {
sin >> video_card_id;
}
sin.clear();
@ -117,20 +107,18 @@ int main(int argc, char **argv)
goto bail;
}
if (SDL_Init(SDL_INIT_AUDIO)){
if (SDL_Init(SDL_INIT_AUDIO)) {
LOG_F(ERROR, "SDL_Init error: %s", SDL_GetError());
goto bail;
}
if ((checker == "1") || (checker == "realtime") || \
(checker == "-realtime") || (checker == "/realtime")) {
if ((checker == "1") || (checker == "realtime") || (checker == "-realtime") ||
(checker == "/realtime")) {
ppc_exec();
} else if ((checker == "debugger") || (checker == "/debugger") ||
(checker == "-debugger")) {
} else if ((checker == "debugger") || (checker == "/debugger") || (checker == "-debugger")) {
enter_debugger();
}
}
else {
} else {
std::cout << " " << endl;
std::cout << "Please enter one of the following commands when " << endl;
std::cout << "booting up DingusPPC... " << endl;

View File

@ -5,102 +5,98 @@
#ifndef MEM_READ_WRITE_H
#define MEM_READ_WRITE_H
#include <cinttypes>
#include "endianswap.h"
#include <cinttypes>
/* read an aligned big-endian WORD (16bit) */
#define READ_WORD_BE_A(addr) (BYTESWAP_16(*((uint16_t *)((addr)))))
#define READ_WORD_BE_A(addr) (BYTESWAP_16(*((uint16_t*)((addr)))))
/* read an aligned big-endian DWORD (32bit) */
#define READ_DWORD_BE_A(addr) (BYTESWAP_32(*((uint32_t *)((addr)))))
#define READ_DWORD_BE_A(addr) (BYTESWAP_32(*((uint32_t*)((addr)))))
/* read an aligned big-endian QWORD (64bit) */
#define READ_QWORD_BE_A(addr) (BYTESWAP_64(*((uint64_t *)((addr)))))
#define READ_QWORD_BE_A(addr) (BYTESWAP_64(*((uint64_t*)((addr)))))
/* read an aligned little-endian WORD (16bit) */
#define READ_WORD_LE_A(addr) (*(uint16_t *)((addr)))
#define READ_WORD_LE_A(addr) (*(uint16_t*)((addr)))
/* read an aligned little-endian DWORD (32bit) */
#define READ_DWORD_LE_A(addr) (*(uint32_t *)((addr)))
#define READ_DWORD_LE_A(addr) (*(uint32_t*)((addr)))
/* read an aligned little-endian QWORD (64bit) */
#define READ_QWORD_LE_A(addr) (*(uint64_t *)((addr)))
#define READ_QWORD_LE_A(addr) (*(uint64_t*)((addr)))
/* read an unaligned big-endian WORD (16bit) */
#define READ_WORD_BE_U(addr) (((addr)[0] << 8) | (addr)[1])
#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])
#define READ_WORD_LE_U(addr) (((addr)[1] << 8) | (addr)[0])
/* read an unaligned little-endian DWORD (32bit) */
#define READ_DWORD_LE_U(addr) (((addr)[3] << 24) | ((addr)[2] << 16) | \
((addr)[1] << 8) | (addr)[0])
#define READ_DWORD_LE_U(addr) (((addr)[3] << 24) | ((addr)[2] << 16) | ((addr)[1] << 8) | (addr)[0])
/* read an unaligned little-endian DWORD (32bit) */
#define READ_QWORD_LE_U(addr) (((addr)[7] << 56) | ((addr)[6] << 48) | \
((addr)[5] << 40) | ((addr)[4] << 32) | \
((addr)[3] << 24) | ((addr)[2] << 16) | \
((addr)[1] << 8) | (addr)[0])
#define READ_QWORD_LE_U(addr) \
(((addr)[7] << 56) | ((addr)[6] << 48) | ((addr)[5] << 40) | ((addr)[4] << 32) | \
((addr)[3] << 24) | ((addr)[2] << 16) | ((addr)[1] << 8) | (addr)[0])
/* write an aligned big-endian WORD (16bit) */
#define WRITE_WORD_BE_A(addr,val) (*((uint16_t *)((addr))) = BYTESWAP_16(val))
#define WRITE_WORD_BE_A(addr, val) (*((uint16_t*)((addr))) = BYTESWAP_16(val))
/* write an aligned big-endian DWORD (32bit) */
#define WRITE_DWORD_BE_A(addr,val) (*((uint32_t *)((addr))) = BYTESWAP_32(val))
#define WRITE_DWORD_BE_A(addr, val) (*((uint32_t*)((addr))) = BYTESWAP_32(val))
/* write an aligned big-endian QWORD (64bit) */
#define WRITE_QWORD_BE_A(addr,val) (*((uint64_t *)((addr))) = BYTESWAP_64(val))
#define WRITE_QWORD_BE_A(addr, val) (*((uint64_t*)((addr))) = BYTESWAP_64(val))
/* write an unaligned big-endian WORD (16bit) */
#define WRITE_WORD_BE_U(addr, val) \
do { \
(addr)[0] = ((val) >> 8) & 0xFF; \
(addr)[1] = (val) & 0xFF; \
} while(0)
#define WRITE_WORD_BE_U(addr, val) \
do { \
(addr)[0] = ((val) >> 8) & 0xFF; \
(addr)[1] = (val)&0xFF; \
} while (0)
/* write an unaligned big-endian DWORD (32bit) */
#define WRITE_DWORD_BE_U(addr, val) \
do { \
(addr)[0] = ((val) >> 24) & 0xFF; \
(addr)[1] = ((val) >> 16) & 0xFF; \
(addr)[2] = ((val) >> 8) & 0xFF; \
(addr)[3] = (val) & 0xFF; \
} while(0)
#define WRITE_DWORD_BE_U(addr, val) \
do { \
(addr)[0] = ((val) >> 24) & 0xFF; \
(addr)[1] = ((val) >> 16) & 0xFF; \
(addr)[2] = ((val) >> 8) & 0xFF; \
(addr)[3] = (val)&0xFF; \
} while (0)
/* write an aligned little-endian WORD (16bit) */
#define WRITE_WORD_LE_A(addr,val) (*((uint16_t *)((addr))) = (val))
#define WRITE_WORD_LE_A(addr, val) (*((uint16_t*)((addr))) = (val))
/* write an aligned little-endian DWORD (32bit) */
#define WRITE_DWORD_LE_A(addr,val) (*((uint32_t *)((addr))) = (val))
#define WRITE_DWORD_LE_A(addr, val) (*((uint32_t*)((addr))) = (val))
/* write an aligned little-endian QWORD (64bit) */
#define WRITE_QWORD_LE_A(addr,val) (*((uint64_t *)((addr))) = (val))
#define WRITE_QWORD_LE_A(addr, val) (*((uint64_t*)((addr))) = (val))
/* write an unaligned little-endian WORD (16bit) */
#define WRITE_WORD_LE_U(addr, val) \
do { \
(addr)[0] = (val) & 0xFF; \
(addr)[1] = ((val) >> 8) & 0xFF; \
} while(0)
#define WRITE_WORD_LE_U(addr, val) \
do { \
(addr)[0] = (val)&0xFF; \
(addr)[1] = ((val) >> 8) & 0xFF; \
} while (0)
/* write an unaligned little-endian DWORD (32bit) */
#define WRITE_DWORD_LE_U(addr, val) \
do { \
(addr)[0] = (val) & 0xFF; \
(addr)[1] = ((val) >> 8) & 0xFF; \
(addr)[2] = ((val) >> 16) & 0xFF; \
(addr)[3] = ((val) >> 24) & 0xFF; \
} while(0)
#define WRITE_DWORD_LE_U(addr, val) \
do { \
(addr)[0] = (val)&0xFF; \
(addr)[1] = ((val) >> 8) & 0xFF; \
(addr)[2] = ((val) >> 16) & 0xFF; \
(addr)[3] = ((val) >> 24) & 0xFF; \
} while (0)
#endif /* MEM_READ_WRITE_H */