--- /dev/null
+---
+Language: Cpp
+AlignAfterOpenBracket: true
+AccessModifierOffset: -2
+AlignArrayOfStructures: None
+AlignConsecutiveAssignments:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionDeclarations: false
+ AlignFunctionPointers: false
+ PadOperators: true
+AlignConsecutiveBitFields:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionDeclarations: false
+ AlignFunctionPointers: false
+ PadOperators: false
+AlignConsecutiveDeclarations:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionDeclarations: true
+ AlignFunctionPointers: false
+ PadOperators: false
+AlignConsecutiveMacros:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionDeclarations: false
+ AlignFunctionPointers: false
+ PadOperators: false
+AlignConsecutiveShortCaseStatements:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCaseArrows: false
+ AlignCaseColons: false
+AlignConsecutiveTableGenBreakingDAGArgColons:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionDeclarations: false
+ AlignFunctionPointers: false
+ PadOperators: false
+AlignConsecutiveTableGenCondOperatorColons:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionDeclarations: false
+ AlignFunctionPointers: false
+ PadOperators: false
+AlignConsecutiveTableGenDefinitionColons:
+ Enabled: false
+ AcrossEmptyLines: false
+ AcrossComments: false
+ AlignCompound: false
+ AlignFunctionDeclarations: false
+ AlignFunctionPointers: false
+ PadOperators: false
+AlignEscapedNewlines: Right
+AlignOperands: Align
+AlignTrailingComments:
+ AlignPPAndNotPP: true
+ Kind: Always
+ OverEmptyLines: 0
+AllowAllArgumentsOnNextLine: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowBreakBeforeNoexceptSpecifier: Never
+AllowBreakBeforeQtProperty: false
+AllowShortBlocksOnASingleLine: Never
+AllowShortCaseExpressionOnASingleLine: true
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortCompoundRequirementOnASingleLine: true
+AllowShortEnumsOnASingleLine: true
+AllowShortFunctionsOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: Never
+AllowShortLambdasOnASingleLine: All
+AllowShortLoopsOnASingleLine: false
+AllowShortNamespacesOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AttributeMacros:
+ - __capability
+BinPackArguments: true
+BinPackLongBracedList: true
+BinPackParameters: BinPack
+BitFieldColonSpacing: Both
+BracedInitializerIndentWidth: -1
+BraceWrapping:
+ AfterCaseLabel: false
+ AfterClass: false
+ AfterControlStatement: Never
+ AfterEnum: false
+ AfterExternBlock: false
+ AfterFunction: false
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ BeforeCatch: false
+ BeforeElse: false
+ BeforeLambdaBody: false
+ BeforeWhile: false
+ IndentBraces: false
+ SplitEmptyFunction: true
+ SplitEmptyRecord: true
+ SplitEmptyNamespace: true
+BreakAdjacentStringLiterals: true
+BreakAfterAttributes: Leave
+BreakAfterJavaFieldAnnotations: false
+BreakAfterOpenBracketBracedList: false
+BreakAfterOpenBracketFunction: false
+BreakAfterOpenBracketIf: false
+BreakAfterOpenBracketLoop: false
+BreakAfterOpenBracketSwitch: false
+BreakAfterReturnType: None
+BreakArrays: true
+BreakBeforeBinaryOperators: None
+BreakBeforeCloseBracketBracedList: false
+BreakBeforeCloseBracketFunction: false
+BreakBeforeCloseBracketIf: false
+BreakBeforeCloseBracketLoop: false
+BreakBeforeCloseBracketSwitch: false
+BreakBeforeConceptDeclarations: Always
+BreakBeforeBraces: Attach
+BreakBeforeInlineASMColon: OnlyMultiline
+BreakBeforeTemplateCloser: false
+BreakBeforeTernaryOperators: true
+BreakBinaryOperations: Never
+BreakConstructorInitializers: BeforeColon
+BreakFunctionDefinitionParameters: false
+BreakInheritanceList: BeforeColon
+BreakStringLiterals: true
+BreakTemplateDeclarations: MultiLine
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: AlignFirstComment
+DerivePointerAlignment: false
+DisableFormat: false
+EmptyLineAfterAccessModifier: Never
+EmptyLineBeforeAccessModifier: LogicalBlock
+EnumTrailingComma: Leave
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IfMacros:
+ - KJ_IF_MAYBE
+IncludeBlocks: Preserve
+IncludeCategories:
+ - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+ Priority: 2
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '^(<|"(gtest|gmock|isl|json)/)'
+ Priority: 3
+ SortPriority: 0
+ CaseSensitive: false
+ - Regex: '.*'
+ Priority: 1
+ SortPriority: 0
+ CaseSensitive: false
+IncludeIsMainRegex: '(Test)?$'
+IncludeIsMainSourceRegex: ''
+IndentAccessModifiers: false
+IndentCaseBlocks: false
+IndentCaseLabels: false
+IndentExportBlock: true
+IndentExternBlock: AfterExternBlock
+IndentGotoLabels: true
+IndentPPDirectives: None
+IndentRequiresClause: true
+IndentWidth: 2
+IndentWrappedFunctionNames: false
+InsertBraces: false
+InsertNewlineAtEOF: false
+InsertTrailingCommas: None
+IntegerLiteralSeparator:
+ Binary: 0
+ BinaryMinDigitsInsert: 0
+ BinaryMaxDigitsRemove: 0
+ Decimal: 0
+ DecimalMinDigitsInsert: 0
+ DecimalMaxDigitsRemove: 0
+ Hex: 0
+ HexMinDigitsInsert: 0
+ HexMaxDigitsRemove: 0
+ BinaryMinDigits: 0
+ DecimalMinDigits: 0
+ HexMinDigits: 0
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLines:
+ AtEndOfFile: false
+ AtStartOfBlock: true
+ AtStartOfFile: true
+KeepFormFeed: false
+LambdaBodyIndentation: Signature
+LineEnding: DeriveLF
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MainIncludeChar: Quote
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+NumericLiteralCase:
+ ExponentLetter: Leave
+ HexDigit: Leave
+ Prefix: Leave
+ Suffix: Leave
+ObjCBinPackProtocolList: Auto
+ObjCBlockIndentWidth: 2
+ObjCBreakBeforeNestedBlockParam: true
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+OneLineFormatOffRegex: ''
+PackConstructorInitializers: BinPack
+PenaltyBreakAssignment: 2
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakBeforeMemberAccess: 150
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakOpenParenthesis: 0
+PenaltyBreakScopeResolution: 500
+PenaltyBreakString: 1000
+PenaltyBreakTemplateDeclaration: 10
+PenaltyExcessCharacter: 1000000
+PenaltyIndentedWhitespace: 0
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Left
+PPIndentWidth: -1
+QualifierAlignment: Leave
+ReferenceAlignment: Pointer
+ReflowComments: Always
+RemoveBracesLLVM: false
+RemoveEmptyLinesInUnwrappedLines: false
+RemoveParentheses: Leave
+RemoveSemicolon: false
+RequiresClausePosition: OwnLine
+RequiresExpressionIndentation: OuterScope
+SeparateDefinitionBlocks: Leave
+ShortNamespaceLines: 1
+SkipMacroDefinitionBody: false
+SortIncludes:
+ Enabled: true
+ IgnoreCase: false
+ IgnoreExtension: false
+SortJavaStaticImport: Before
+SortUsingDeclarations: LexicographicNumeric
+SpaceAfterCStyleCast: false
+SpaceAfterLogicalNot: false
+SpaceAfterOperatorKeyword: false
+SpaceAfterTemplateKeyword: true
+SpaceAroundPointerQualifiers: Default
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCaseColon: false
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeJsonColon: false
+SpaceBeforeParens: ControlStatements
+SpaceBeforeParensOptions:
+ AfterControlStatements: true
+ AfterForeachMacros: true
+ AfterFunctionDefinitionName: false
+ AfterFunctionDeclarationName: false
+ AfterIfMacros: true
+ AfterNot: false
+ AfterOverloadedOperator: false
+ AfterPlacementOperator: true
+ AfterRequiresInClause: false
+ AfterRequiresInExpression: false
+ BeforeNonEmptyParentheses: false
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceBeforeSquareBrackets: false
+SpaceInEmptyBraces: Never
+SpacesBeforeTrailingComments: 1
+SpacesInAngles: Never
+SpacesInContainerLiterals: true
+SpacesInLineCommentPrefix:
+ Minimum: 1
+ Maximum: -1
+SpacesInParens: Never
+SpacesInParensOptions:
+ ExceptDoubleParentheses: false
+ InCStyleCasts: false
+ InConditionalStatements: false
+ InEmptyParentheses: false
+ Other: false
+SpacesInSquareBrackets: false
+Standard: Latest
+StatementAttributeLikeMacros:
+ - Q_EMIT
+StatementMacros:
+ - Q_UNUSED
+ - QT_REQUIRE_VERSION
+TableGenBreakInsideDAGArg: DontBreak
+TabWidth: 8
+UseTab: Never
+VerilogBreakBetweenInstancePorts: true
+WhitespaceSensitiveMacros:
+ - BOOST_PP_STRINGIZE
+ - CF_SWIFT_NAME
+ - NS_SWIFT_NAME
+ - PP_STRINGIZE
+ - STRINGIZE
+WrapNamespaceBodyWithEmptyLines: Leave
+...
+
#include "common.h"
// this will need changing if this code ever compiles on big-endian procs
-inline uint32_t read32LE(uint8_t *p) {
- return *((uint32_t *)p);
-}
-inline void write32LE(uint8_t *p, uint32_t v) {
- *((uint32_t *)p) = v;
-}
-
+inline uint32_t read32LE(uint8_t* p) { return *((uint32_t*)p); }
+inline void write32LE(uint8_t* p, uint32_t v) { *((uint32_t*)p) = v; }
void ARM710::switchBank(BankIndex newBank) {
- if (newBank != bank) {
- // R13 and R14 need saving/loading for all banks
- allModesBankedRegisters[bank][0] = GPRs[13];
- allModesBankedRegisters[bank][1] = GPRs[14];
- GPRs[13] = allModesBankedRegisters[newBank][0];
- GPRs[14] = allModesBankedRegisters[newBank][1];
-
- // R8 to R12 are only banked in FIQ mode
- auto oldBankR8to12 = (bank == FiqBank) ? 1 : 0;
- auto newBankR8to12 = (newBank == FiqBank) ? 1 : 0;
- if (oldBankR8to12 != newBankR8to12) {
- // swap these sets around
- for (int i = 0; i < 5; i++)
- fiqBankedRegisters[oldBankR8to12][i] = GPRs[8 + i];
- for (int i = 0; i < 5; i++)
- GPRs[8 + i] = fiqBankedRegisters[newBankR8to12][i];
- }
-
- bank = newBank;
- }
+ if (newBank != bank) {
+ // R13 and R14 need saving/loading for all banks
+ allModesBankedRegisters[bank][0] = GPRs[13];
+ allModesBankedRegisters[bank][1] = GPRs[14];
+ GPRs[13] = allModesBankedRegisters[newBank][0];
+ GPRs[14] = allModesBankedRegisters[newBank][1];
+
+ // R8 to R12 are only banked in FIQ mode
+ auto oldBankR8to12 = (bank == FiqBank) ? 1 : 0;
+ auto newBankR8to12 = (newBank == FiqBank) ? 1 : 0;
+ if (oldBankR8to12 != newBankR8to12) {
+ // swap these sets around
+ for (int i = 0; i < 5; i++)
+ fiqBankedRegisters[oldBankR8to12][i] = GPRs[8 + i];
+ for (int i = 0; i < 5; i++)
+ GPRs[8 + i] = fiqBankedRegisters[newBankR8to12][i];
+ }
+
+ bank = newBank;
+ }
}
-
void ARM710::switchMode(Mode newMode) {
- auto oldMode = currentMode();
- if (newMode != oldMode) {
-// log("Switching mode! %x", newMode);
- switchBank(modeToBank[newMode & 0xF]);
-
- CPSR &= ~CPSR_ModeMask;
- CPSR |= newMode;
- }
+ auto oldMode = currentMode();
+ if (newMode != oldMode) {
+ // log("Switching mode! %x", newMode);
+ switchBank(modeToBank[newMode & 0xF]);
+
+ CPSR &= ~CPSR_ModeMask;
+ CPSR |= newMode;
+ }
}
void ARM710::raiseException(Mode mode, uint32_t savedPC, uint32_t newPC) {
- auto bankIndex = modeToBank[mode & 0xF];
-// log("Raising exception mode %x, saving PC %08x, CPSR %08x", mode, savedPC, CPSR);
- SPSRs[bankIndex] = CPSR;
+ auto bankIndex = modeToBank[mode & 0xF];
+ // log("Raising exception mode %x, saving PC %08x, CPSR %08x", mode,
+ // savedPC, CPSR);
+ SPSRs[bankIndex] = CPSR;
- switchMode(mode);
+ switchMode(mode);
- prefetchCount = 0;
- GPRs[14] = savedPC;
- GPRs[15] = newPC;
+ prefetchCount = 0;
+ GPRs[14] = savedPC;
+ GPRs[15] = newPC;
}
void ARM710::requestFIQ() {
- raiseException(FIQ32, getRealPC() + 4, 0x1C);
- CPSR |= CPSR_FIQDisable;
- CPSR |= CPSR_IRQDisable;
+ raiseException(FIQ32, getRealPC() + 4, 0x1C);
+ CPSR |= CPSR_FIQDisable;
+ CPSR |= CPSR_IRQDisable;
}
void ARM710::requestIRQ() {
-// log("Requesting IRQ: Last exec = %08x, setting LR = %08x", lastPcExecuted(), getRealPC() + 4);
- raiseException(IRQ32, getRealPC() + 4, 0x18);
- CPSR |= CPSR_IRQDisable;
+ // log("Requesting IRQ: Last exec = %08x, setting LR = %08x",
+ // lastPcExecuted(), getRealPC() + 4);
+ raiseException(IRQ32, getRealPC() + 4, 0x18);
+ CPSR |= CPSR_IRQDisable;
}
void ARM710::reset() {
#ifdef ARM710T_CACHE
- clearCache();
+ clearCache();
#endif
- raiseException(Supervisor32, 0, 0);
+ raiseException(Supervisor32, 0, 0);
}
-
-
uint32_t ARM710::tick() {
- // pop an instruction off the end of the pipeline
- bool haveInsn = false;
- uint32_t insn;
- MMUFault insnFault;
- if (prefetchCount == 2) {
- haveInsn = true;
- insn = prefetch[1];
- insnFault = prefetchFaults[1];
- }
-
- // move the instruction we fetched last tick once along
- if (prefetchCount >= 1) {
- prefetch[1] = prefetch[0];
- prefetchFaults[1] = prefetchFaults[0];
- }
-
- // fetch a new instruction
- auto newInsn = readVirtual(GPRs[15], V32);
- GPRs[15] += 4;
- prefetch[0] = newInsn.first.value_or(0);
- prefetchFaults[0] = newInsn.second;
- if (prefetchCount < 2)
- prefetchCount++;
-
- // now deal with the one we popped
- uint32_t clocks = 1;
- if (haveInsn) {
- pcHistory[pcHistoryIndex] = {GPRs[15] - 0xC, insn};
- pcHistoryIndex = (pcHistoryIndex + 1) % PcHistoryCount;
- if (insnFault != NoFault) {
- // Raise a prefetch error
- // These do not set FSR or FAR
- log("prefetch error! %08x", insnFault >> MMUFaultAddressShift);
- logPcHistory();
- raiseException(Abort32, GPRs[15] - 8, 0xC);
- } else {
- clocks += executeInstruction(insn);
- }
- }
-
- if (faultTriggeredThisCycle) {
- // data abort time!
- faultTriggeredThisCycle = false;
- raiseException(Abort32, GPRs[15] - 4, 0x10);
- }
-
- return clocks;
+ // pop an instruction off the end of the pipeline
+ bool haveInsn = false;
+ uint32_t insn;
+ MMUFault insnFault;
+ if (prefetchCount == 2) {
+ haveInsn = true;
+ insn = prefetch[1];
+ insnFault = prefetchFaults[1];
+ }
+
+ // move the instruction we fetched last tick once along
+ if (prefetchCount >= 1) {
+ prefetch[1] = prefetch[0];
+ prefetchFaults[1] = prefetchFaults[0];
+ }
+
+ // fetch a new instruction
+ auto newInsn = readVirtual(GPRs[15], V32);
+ GPRs[15] += 4;
+ prefetch[0] = newInsn.first.value_or(0);
+ prefetchFaults[0] = newInsn.second;
+ if (prefetchCount < 2)
+ prefetchCount++;
+
+ // now deal with the one we popped
+ uint32_t clocks = 1;
+ if (haveInsn) {
+ pcHistory[pcHistoryIndex] = {GPRs[15] - 0xC, insn};
+ pcHistoryIndex = (pcHistoryIndex + 1) % PcHistoryCount;
+ if (insnFault != NoFault) {
+ // Raise a prefetch error
+ // These do not set FSR or FAR
+ log("prefetch error! %08x", insnFault >> MMUFaultAddressShift);
+ logPcHistory();
+ raiseException(Abort32, GPRs[15] - 8, 0xC);
+ } else {
+ clocks += executeInstruction(insn);
+ }
+ }
+
+ if (faultTriggeredThisCycle) {
+ // data abort time!
+ faultTriggeredThisCycle = false;
+ raiseException(Abort32, GPRs[15] - 4, 0x10);
+ }
+
+ return clocks;
}
-
static inline uint32_t extract(uint32_t value, uint32_t hiBit, uint32_t loBit) {
- return (value >> loBit) & ((1 << (hiBit - loBit + 1)) - 1);
-// return (value >> (32 - offset - length)) & ((1 << length) - 1);
+ return (value >> loBit) & ((1 << (hiBit - loBit + 1)) - 1);
+ // return (value >> (32 - offset - length)) & ((1 << length) - 1);
}
static inline bool extract1(uint32_t value, uint32_t bit) {
- return (value >> bit) & 1;
+ return (value >> bit) & 1;
}
-
uint32_t ARM710::executeInstruction(uint32_t i) {
- uint32_t cycles = 1;
-// log("executing insn %08x @ %08x", i, GPRs[15] - 0xC);
-
- // a big old dispatch thing here
- // but first, conditions!
- if (!checkCondition(extract(i, 31, 28)))
- return cycles;
-
- if ((i & 0x0F000000) == 0x0F000000)
- raiseException(Supervisor32, GPRs[15] - 8, 0x08);
- else if ((i & 0x0F000F10) == 0x0E000F10)
- cycles += execCP15RegisterTransfer(extract(i,23,21), extract1(i,20), extract(i,19,16), extract(i,15,12), extract(i,7,5), extract(i,3,0));
- else if ((i & 0x0E000000) == 0x0A000000)
- cycles += execBranch(extract1(i,24), extract(i,23,0));
- else if ((i & 0x0E000000) == 0x08000000)
- cycles += execBlockDataTransfer(extract(i,24,20), extract(i,19,16), extract(i,15,0));
- else if ((i & 0x0C000000) == 0x04000000)
- cycles += execSingleDataTransfer(extract(i,25,20), extract(i,19,16), extract(i,15,12), extract(i,11,0));
- else if ((i & 0x0FB00FF0) == 0x01000090)
- cycles += execSingleDataSwap(extract1(i,22), extract(i,19,16), extract(i,15,12), extract(i,3,0));
- else if ((i & 0x0F8000F0) == 0x00000090)
- cycles += execMultiply(extract(i,21,20), extract(i,19,16), extract(i,15,12), extract(i,11,8), extract(i,3,0));
- else if ((i & 0x0F8000F0) == 0x00800090 && isTVersion)
- cycles += execMultiplyLong(extract(i,22,20), extract(i,19,16), extract(i,15,12), extract(i,11,8), extract(i,3,0));
- else if ((i & 0x0E000090) == 0x00000090) {
- cycles += execSingleHalfWordDataTransfer(extract(i, 24, 20), extract(i, 19, 16), extract(i, 15, 12), extract(i, 11, 8), extract(i, 6, 5), extract(i, 3, 0));
- } else if ((i & 0x0C000000) == 0x00000000)
- cycles += execDataProcessing(extract1(i,25), extract(i,24,21), extract1(i,20), extract(i,19,16), extract(i,15,12), extract(i,11,0));
- else
- raiseException(Undefined32, GPRs[15] - 8, 0x04);
-
- return cycles;
+ uint32_t cycles = 1;
+ // log("executing insn %08x @ %08x", i, GPRs[15] - 0xC);
+
+ // a big old dispatch thing here
+ // but first, conditions!
+ if (!checkCondition(extract(i, 31, 28)))
+ return cycles;
+
+ if ((i & 0x0F000000) == 0x0F000000)
+ raiseException(Supervisor32, GPRs[15] - 8, 0x08);
+ else if ((i & 0x0F000F10) == 0x0E000F10)
+ cycles += execCP15RegisterTransfer(extract(i, 23, 21), extract1(i, 20),
+ extract(i, 19, 16), extract(i, 15, 12),
+ extract(i, 7, 5), extract(i, 3, 0));
+ else if ((i & 0x0E000000) == 0x0A000000)
+ cycles += execBranch(extract1(i, 24), extract(i, 23, 0));
+ else if ((i & 0x0E000000) == 0x08000000)
+ cycles += execBlockDataTransfer(extract(i, 24, 20), extract(i, 19, 16),
+ extract(i, 15, 0));
+ else if ((i & 0x0C000000) == 0x04000000)
+ cycles += execSingleDataTransfer(extract(i, 25, 20), extract(i, 19, 16),
+ extract(i, 15, 12), extract(i, 11, 0));
+ else if ((i & 0x0FB00FF0) == 0x01000090)
+ cycles += execSingleDataSwap(extract1(i, 22), extract(i, 19, 16),
+ extract(i, 15, 12), extract(i, 3, 0));
+ else if ((i & 0x0F8000F0) == 0x00000090)
+ cycles +=
+ execMultiply(extract(i, 21, 20), extract(i, 19, 16), extract(i, 15, 12),
+ extract(i, 11, 8), extract(i, 3, 0));
+ else if ((i & 0x0F8000F0) == 0x00800090 && isTVersion)
+ cycles += execMultiplyLong(extract(i, 22, 20), extract(i, 19, 16),
+ extract(i, 15, 12), extract(i, 11, 8),
+ extract(i, 3, 0));
+ else if ((i & 0x0E000090) == 0x00000090) {
+ cycles += execSingleHalfWordDataTransfer(
+ extract(i, 24, 20), extract(i, 19, 16), extract(i, 15, 12),
+ extract(i, 11, 8), extract(i, 6, 5), extract(i, 3, 0));
+ } else if ((i & 0x0C000000) == 0x00000000)
+ cycles += execDataProcessing(extract1(i, 25), extract(i, 24, 21),
+ extract1(i, 20), extract(i, 19, 16),
+ extract(i, 15, 12), extract(i, 11, 0));
+ else
+ raiseException(Undefined32, GPRs[15] - 8, 0x04);
+
+ return cycles;
}
-uint32_t ARM710::execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t Rn, uint32_t Rd, uint32_t Operand2)
-{
- uint32_t cycles = 0; // TODO increment me semi-accurately
- bool shifterCarryOutput;
-
- // compute our Op1 (may be unnecessary but that's ok)
- uint32_t op1 = GPRs[Rn];
-
- // compute our Op2
- uint32_t op2;
- if (!I) {
- // REGISTER
- uint32_t Rm = extract(Operand2, 3, 0);
- op2 = GPRs[Rm];
-
- uint8_t shiftBy;
-
- // this is the real painful one, honestly
- if (extract(Operand2, 4, 4)) {
- // Shift by Register
- uint32_t Rs = extract(Operand2, 11, 8);
- shiftBy = GPRs[Rs] & 0xFF;
- } else {
- // Shift by Immediate
- shiftBy = extract(Operand2, 11, 7);
-
- if (Rn == 15) // if PC is fetched...
- op1 -= 4; // compensate for prefetching
- if (Rm == 15)
- op2 -= 4;
- }
-
- if (extract(Operand2, 4, 4) && (shiftBy == 0)) {
- // register shift by 0 never does anything
- shifterCarryOutput = flagC();
- } else {
- switch (extract(Operand2, 6, 5)) {
- case 0: // Logical Left (LSL)
- if (shiftBy == 0) {
- shifterCarryOutput = flagC();
- // no change to op2!
- } else if (shiftBy <= 31) {
- shifterCarryOutput = extract1(op2, 31 - shiftBy);
- op2 <<= shiftBy;
- } else if (shiftBy == 32) {
- shifterCarryOutput = extract1(op2, 0);
- op2 = 0;
- } else /*if (shiftBy >= 33)*/ {
- shifterCarryOutput = false;
- op2 = 0;
- }
- break;
- case 1: // Logical Right (LSR)
- if (shiftBy == 0 || shiftBy == 32) {
- shifterCarryOutput = extract1(op2, 31);
- op2 = 0;
- } else if (shiftBy <= 31) {
- shifterCarryOutput = extract1(op2, shiftBy - 1);
- op2 >>= shiftBy;
- } else /*if (shiftBy >= 33)*/ {
- shifterCarryOutput = false;
- op2 = 0;
- }
- break;
- case 2: // Arithmetic Right (ASR)
- if (shiftBy == 0 || shiftBy >= 32) {
- shifterCarryOutput = extract1(op2, 31);
- op2 = (int32_t)op2 >> 31;
- } else /*if (shiftBy <= 31)*/ {
- shifterCarryOutput = extract1(op2, shiftBy - 1);
- op2 = (int32_t)op2 >> shiftBy;
- }
- break;
- case 3: // Rotate Right (ROR)
- if (shiftBy == 0) { // treated as RRX
- shifterCarryOutput = op2 & 1;
- op2 >>= 1;
- op2 |= flagC() ? 0x80000000 : 0;
- } else {
- shiftBy %= 32;
- if (shiftBy == 0) { // like 32
- shifterCarryOutput = extract1(op2, 31);
- // no change to op2
- } else {
- shifterCarryOutput = extract1(op2, shiftBy - 1);
- op2 = ROR(op2, shiftBy);
- }
- }
- break;
- }
- }
- } else {
- // IMMEDIATE
- if (Rn == 15) // if PC is fetched...
- op1 -= 4; // compensate for prefetching
-
- uint32_t Rotate = extract(Operand2, 11, 8);
- uint32_t Imm = extract(Operand2, 7, 0);
- op2 = ROR(Imm, Rotate * 2);
- shifterCarryOutput = flagC(); // correct? unsure...
- }
-
- // we have our operands, what next
- uint64_t result = 0;
- uint32_t flags = 0;
-
-#define LOGICAL_OP(v) \
- result = v; \
- flags |= (result & 0xFFFFFFFF) ? 0 : CPSR_Z; \
- flags |= (result & 0x80000000) ? CPSR_N : 0; \
- flags |= shifterCarryOutput ? CPSR_C : 0; \
- flags |= (CPSR & CPSR_V);
-
-#define ADD_OP(a, b, c) \
- result = (uint64_t)(a) + (uint64_t)(b) + (uint64_t)(c); \
- flags |= (result & 0xFFFFFFFF) ? 0 : CPSR_Z; \
- flags |= (result & 0x80000000) ? CPSR_N : 0; \
- flags |= (result & 0x100000000) ? CPSR_C : 0; \
- flags |= ((((a) & 0x80000000) == ((b) & 0x80000000)) && (((a) & 0x80000000) != (result & 0x80000000))) ? CPSR_V : 0;
+uint32_t ARM710::execDataProcessing(bool I, uint32_t Opcode, bool S,
+ uint32_t Rn, uint32_t Rd,
+ uint32_t Operand2) {
+ uint32_t cycles = 0; // TODO increment me semi-accurately
+ bool shifterCarryOutput;
+
+ // compute our Op1 (may be unnecessary but that's ok)
+ uint32_t op1 = GPRs[Rn];
+
+ // compute our Op2
+ uint32_t op2;
+ if (!I) {
+ // REGISTER
+ uint32_t Rm = extract(Operand2, 3, 0);
+ op2 = GPRs[Rm];
+
+ uint8_t shiftBy;
+
+ // this is the real painful one, honestly
+ if (extract(Operand2, 4, 4)) {
+ // Shift by Register
+ uint32_t Rs = extract(Operand2, 11, 8);
+ shiftBy = GPRs[Rs] & 0xFF;
+ } else {
+ // Shift by Immediate
+ shiftBy = extract(Operand2, 11, 7);
+
+ if (Rn == 15) // if PC is fetched...
+ op1 -= 4; // compensate for prefetching
+ if (Rm == 15)
+ op2 -= 4;
+ }
+
+ if (extract(Operand2, 4, 4) && (shiftBy == 0)) {
+ // register shift by 0 never does anything
+ shifterCarryOutput = flagC();
+ } else {
+ switch (extract(Operand2, 6, 5)) {
+ case 0: // Logical Left (LSL)
+ if (shiftBy == 0) {
+ shifterCarryOutput = flagC();
+ // no change to op2!
+ } else if (shiftBy <= 31) {
+ shifterCarryOutput = extract1(op2, 31 - shiftBy);
+ op2 <<= shiftBy;
+ } else if (shiftBy == 32) {
+ shifterCarryOutput = extract1(op2, 0);
+ op2 = 0;
+ } else /*if (shiftBy >= 33)*/ {
+ shifterCarryOutput = false;
+ op2 = 0;
+ }
+ break;
+ case 1: // Logical Right (LSR)
+ if (shiftBy == 0 || shiftBy == 32) {
+ shifterCarryOutput = extract1(op2, 31);
+ op2 = 0;
+ } else if (shiftBy <= 31) {
+ shifterCarryOutput = extract1(op2, shiftBy - 1);
+ op2 >>= shiftBy;
+ } else /*if (shiftBy >= 33)*/ {
+ shifterCarryOutput = false;
+ op2 = 0;
+ }
+ break;
+ case 2: // Arithmetic Right (ASR)
+ if (shiftBy == 0 || shiftBy >= 32) {
+ shifterCarryOutput = extract1(op2, 31);
+ op2 = (int32_t)op2 >> 31;
+ } else /*if (shiftBy <= 31)*/ {
+ shifterCarryOutput = extract1(op2, shiftBy - 1);
+ op2 = (int32_t)op2 >> shiftBy;
+ }
+ break;
+ case 3: // Rotate Right (ROR)
+ if (shiftBy == 0) { // treated as RRX
+ shifterCarryOutput = op2 & 1;
+ op2 >>= 1;
+ op2 |= flagC() ? 0x80000000 : 0;
+ } else {
+ shiftBy %= 32;
+ if (shiftBy == 0) { // like 32
+ shifterCarryOutput = extract1(op2, 31);
+ // no change to op2
+ } else {
+ shifterCarryOutput = extract1(op2, shiftBy - 1);
+ op2 = ROR(op2, shiftBy);
+ }
+ }
+ break;
+ }
+ }
+ } else {
+ // IMMEDIATE
+ if (Rn == 15) // if PC is fetched...
+ op1 -= 4; // compensate for prefetching
+
+ uint32_t Rotate = extract(Operand2, 11, 8);
+ uint32_t Imm = extract(Operand2, 7, 0);
+ op2 = ROR(Imm, Rotate * 2);
+ shifterCarryOutput = flagC(); // correct? unsure...
+ }
+
+ // we have our operands, what next
+ uint64_t result = 0;
+ uint32_t flags = 0;
+
+#define LOGICAL_OP(v) \
+ result = v; \
+ flags |= (result & 0xFFFFFFFF) ? 0 : CPSR_Z; \
+ flags |= (result & 0x80000000) ? CPSR_N : 0; \
+ flags |= shifterCarryOutput ? CPSR_C : 0; \
+ flags |= (CPSR & CPSR_V);
+
+#define ADD_OP(a, b, c) \
+ result = (uint64_t)(a) + (uint64_t)(b) + (uint64_t)(c); \
+ flags |= (result & 0xFFFFFFFF) ? 0 : CPSR_Z; \
+ flags |= (result & 0x80000000) ? CPSR_N : 0; \
+ flags |= (result & 0x100000000) ? CPSR_C : 0; \
+ flags |= ((((a) & 0x80000000) == ((b) & 0x80000000)) && \
+ (((a) & 0x80000000) != (result & 0x80000000))) \
+ ? CPSR_V \
+ : 0;
#define SUB_OP(a, b, c) ADD_OP(a, ~b, c)
-
- switch (Opcode) {
- case 0: LOGICAL_OP(op1 & op2); break; // AND
- case 1: LOGICAL_OP(op1 ^ op2); break; // EOR
- case 2: SUB_OP(op1, op2, 1); break; // SUB
- case 3: SUB_OP(op2, op1, 1); break; // RSB
- case 4: ADD_OP(op1, op2, 0); break; // ADD
- case 5: ADD_OP(op1, op2, flagC()); break; // ADC
- case 6: SUB_OP(op1, op2, flagC()); break; // SBC
- case 7: SUB_OP(op2, op1, flagC()); break; // RSC
- case 8: LOGICAL_OP(op1 & op2); break; // TST
- case 9: LOGICAL_OP(op1 ^ op2); break; // TEQ
- case 0xA: SUB_OP(op1, op2, 1); break; // CMP
- case 0xB: ADD_OP(op1, op2, 0); break; // CMN
- case 0xC: LOGICAL_OP(op1 | op2); break; // ORR
- case 0xD: LOGICAL_OP(op2); break; // MOV
- case 0xE: LOGICAL_OP(op1 & ~op2); break; // BIC
- case 0xF: LOGICAL_OP(~op2); break; // MVN
- }
-
- if (Opcode >= 8 && Opcode <= 0xB) {
- // Output-less opcodes: special behaviour
- if (S) {
- CPSR = (CPSR & ~CPSR_FlagMask) | flags;
-// log("CPSR setflags=%08x results in CPSR=%08x", flags, CPSR);
- } else if (Opcode == 8) {
- // MRS, CPSR -> Reg
- GPRs[Rd] = CPSR;
-// log("r%d <- CPSR(%08x)", Rd, GPRs[Rd]);
- } else if (Opcode == 9) {
- // MSR, Reg -> CPSR
- bool canChangeMode = extract1(Rn, 0);
- if (canChangeMode && isPrivileged()) {
- auto newCPSR = GPRs[extract(Operand2, 3, 0)];
- switchMode(modeFromCPSR(newCPSR));
- CPSR = newCPSR;
-// log("CPSR change privileged: %08x", CPSR);
- } else {
- // for the flag-only version, immediates are allowed
- // so we just re-use what was calculated earlier...
- auto newFlag = I ? op2 : GPRs[extract(Operand2, 3, 0)];
- CPSR &= ~CPSR_FlagMask;
- CPSR |= (newFlag & CPSR_FlagMask);
-// log("CPSR change unprivileged: new=%08x result=%08x", newFlag, CPSR);
- }
- } else if (Opcode == 0xA) {
- // MRS, SPSR -> Reg
- if (isPrivileged()) {
- GPRs[Rd] = SPSRs[currentBank()];
-// log("r%d <- SPSR(%08x)", Rd, GPRs[Rd]);
- }
- } else /*if (Opcode == 0xB)*/ {
- bool canChangeMode = extract1(Rn, 0);
- if (isPrivileged()) {
- if (canChangeMode) {
- SPSRs[currentBank()] = GPRs[extract(Operand2, 3, 0)];
-// log("SPSR change privileged: %08x", SPSRs[currentBank()]);
- } else {
- // same hat
- auto newFlag = I ? op2 : GPRs[extract(Operand2, 3, 0)];
- SPSRs[currentBank()] &= ~CPSR_FlagMask;
- SPSRs[currentBank()] |= (newFlag & CPSR_FlagMask);
-// log("SPSR change unprivileged: new=%08x result=%08x", newFlag, SPSRs[currentBank()]);
- }
- }
- }
- } else {
- GPRs[Rd] = result & 0xFFFFFFFF;
-
- if (Rd == 15) {
- // Writing to PC
- // Special things occur here!
- GPRs[Rd] &= ~3; // TODO is this really necessary??
- prefetchCount = 0;
- if (S && isPrivileged()) {
- // We SHOULD be privileged
- // (Raise an error otherwise...?)
- auto saved = SPSRs[currentBank()];
- switchMode(modeFromCPSR(saved));
- CPSR = saved;
-// log("dataproc restore CPSR: %08x", saved);
- }
- } else if (S) {
- CPSR = (CPSR & ~CPSR_FlagMask) | flags;
-// log("dataproc flag change: flags=%08x CPSR=%08x", flags, CPSR);
- }
- }
-
- return cycles;
+ switch (Opcode) {
+ case 0:
+ LOGICAL_OP(op1 & op2);
+ break; // AND
+ case 1:
+ LOGICAL_OP(op1 ^ op2);
+ break; // EOR
+ case 2:
+ SUB_OP(op1, op2, 1);
+ break; // SUB
+ case 3:
+ SUB_OP(op2, op1, 1);
+ break; // RSB
+ case 4:
+ ADD_OP(op1, op2, 0);
+ break; // ADD
+ case 5:
+ ADD_OP(op1, op2, flagC());
+ break; // ADC
+ case 6:
+ SUB_OP(op1, op2, flagC());
+ break; // SBC
+ case 7:
+ SUB_OP(op2, op1, flagC());
+ break; // RSC
+ case 8:
+ LOGICAL_OP(op1 & op2);
+ break; // TST
+ case 9:
+ LOGICAL_OP(op1 ^ op2);
+ break; // TEQ
+ case 0xA:
+ SUB_OP(op1, op2, 1);
+ break; // CMP
+ case 0xB:
+ ADD_OP(op1, op2, 0);
+ break; // CMN
+ case 0xC:
+ LOGICAL_OP(op1 | op2);
+ break; // ORR
+ case 0xD:
+ LOGICAL_OP(op2);
+ break; // MOV
+ case 0xE:
+ LOGICAL_OP(op1 & ~op2);
+ break; // BIC
+ case 0xF:
+ LOGICAL_OP(~op2);
+ break; // MVN
+ }
+
+ if (Opcode >= 8 && Opcode <= 0xB) {
+ // Output-less opcodes: special behaviour
+ if (S) {
+ CPSR = (CPSR & ~CPSR_FlagMask) | flags;
+ // log("CPSR setflags=%08x results in CPSR=%08x",
+ // flags, CPSR);
+ } else if (Opcode == 8) {
+ // MRS, CPSR -> Reg
+ GPRs[Rd] = CPSR;
+ // log("r%d <- CPSR(%08x)", Rd, GPRs[Rd]);
+ } else if (Opcode == 9) {
+ // MSR, Reg -> CPSR
+ bool canChangeMode = extract1(Rn, 0);
+ if (canChangeMode && isPrivileged()) {
+ auto newCPSR = GPRs[extract(Operand2, 3, 0)];
+ switchMode(modeFromCPSR(newCPSR));
+ CPSR = newCPSR;
+ // log("CPSR change privileged: %08x",
+ // CPSR);
+ } else {
+ // for the flag-only version, immediates are allowed
+ // so we just re-use what was calculated earlier...
+ auto newFlag = I ? op2 : GPRs[extract(Operand2, 3, 0)];
+ CPSR &= ~CPSR_FlagMask;
+ CPSR |= (newFlag & CPSR_FlagMask);
+ // log("CPSR change unprivileged: new=%08x
+ // result=%08x", newFlag, CPSR);
+ }
+ } else if (Opcode == 0xA) {
+ // MRS, SPSR -> Reg
+ if (isPrivileged()) {
+ GPRs[Rd] = SPSRs[currentBank()];
+ // log("r%d <- SPSR(%08x)", Rd, GPRs[Rd]);
+ }
+ } else /*if (Opcode == 0xB)*/ {
+ bool canChangeMode = extract1(Rn, 0);
+ if (isPrivileged()) {
+ if (canChangeMode) {
+ SPSRs[currentBank()] = GPRs[extract(Operand2, 3, 0)];
+ // log("SPSR change privileged:
+ //%08x", SPSRs[currentBank()]);
+ } else {
+ // same hat
+ auto newFlag = I ? op2 : GPRs[extract(Operand2, 3, 0)];
+ SPSRs[currentBank()] &= ~CPSR_FlagMask;
+ SPSRs[currentBank()] |= (newFlag & CPSR_FlagMask);
+ // log("SPSR change unprivileged:
+ // new=%08x result=%08x", newFlag, SPSRs[currentBank()]);
+ }
+ }
+ }
+ } else {
+ GPRs[Rd] = result & 0xFFFFFFFF;
+
+ if (Rd == 15) {
+ // Writing to PC
+ // Special things occur here!
+ GPRs[Rd] &= ~3; // TODO is this really necessary??
+ prefetchCount = 0;
+ if (S && isPrivileged()) {
+ // We SHOULD be privileged
+ // (Raise an error otherwise...?)
+ auto saved = SPSRs[currentBank()];
+ switchMode(modeFromCPSR(saved));
+ CPSR = saved;
+ // log("dataproc restore CPSR: %08x",
+ // saved);
+ }
+ } else if (S) {
+ CPSR = (CPSR & ~CPSR_FlagMask) | flags;
+ // log("dataproc flag change: flags=%08x
+ // CPSR=%08x", flags, CPSR);
+ }
+ }
+
+ return cycles;
}
-uint32_t ARM710::execMultiply(uint32_t AS, uint32_t Rd, uint32_t Rn, uint32_t Rs, uint32_t Rm)
-{
- // no need for R15 fuckery
- // datasheet says it's not allowed here
- if (AS & 2)
- GPRs[Rd] = GPRs[Rm] * GPRs[Rs] + GPRs[Rn];
- else
- GPRs[Rd] = GPRs[Rm] * GPRs[Rs];
-
- if (AS & 1) {
- CPSR &= ~(CPSR_N | CPSR_Z);
- CPSR |= GPRs[Rd] ? 0 : CPSR_Z;
- CPSR |= (GPRs[Rd] & 0x80000000) ? CPSR_N : 0;
- }
-
- return 0;
+uint32_t ARM710::execMultiply(uint32_t AS, uint32_t Rd, uint32_t Rn,
+ uint32_t Rs, uint32_t Rm) {
+ // no need for R15 fuckery
+ // datasheet says it's not allowed here
+ if (AS & 2)
+ GPRs[Rd] = GPRs[Rm] * GPRs[Rs] + GPRs[Rn];
+ else
+ GPRs[Rd] = GPRs[Rm] * GPRs[Rs];
+
+ if (AS & 1) {
+ CPSR &= ~(CPSR_N | CPSR_Z);
+ CPSR |= GPRs[Rd] ? 0 : CPSR_Z;
+ CPSR |= (GPRs[Rd] & 0x80000000) ? CPSR_N : 0;
+ }
+
+ return 0;
}
// ARM710T only!
-uint32_t ARM710::execMultiplyLong(uint32_t UAS, uint32_t RdHi, uint32_t RdLo, uint32_t Rs, uint32_t Rm)
-{
- // no need for R15 fuckery
- // datasheet says it's not allowed here
- uint64_t result;
- if (UAS & 4) // unsigned
- result = (uint64_t)GPRs[Rm] * (uint64_t)GPRs[Rs];
- else // signed
- result = (uint64_t)((int64_t)GPRs[Rm] * (int64_t)GPRs[Rs]);
-
- if (UAS & 2) {
- // accumulate
- uint64_t addend = (uint64_t)GPRs[RdLo] | ((uint64_t)GPRs[RdHi] << 32);
- result += addend;
- }
-
- if (UAS & 1) {
- CPSR &= ~(CPSR_N | CPSR_Z);
- CPSR |= result ? 0 : CPSR_Z;
- CPSR |= (result & 0x8000000000000000) ? CPSR_N : 0;
- }
-
- GPRs[RdLo] = result & 0xFFFFFFFF;
- GPRs[RdHi] = result >> 32;
-
- return 0;
+uint32_t ARM710::execMultiplyLong(uint32_t UAS, uint32_t RdHi, uint32_t RdLo,
+ uint32_t Rs, uint32_t Rm) {
+ // no need for R15 fuckery
+ // datasheet says it's not allowed here
+ uint64_t result;
+ if (UAS & 4) // unsigned
+ result = (uint64_t)GPRs[Rm] * (uint64_t)GPRs[Rs];
+ else // signed
+ result = (uint64_t)((int64_t)GPRs[Rm] * (int64_t)GPRs[Rs]);
+
+ if (UAS & 2) {
+ // accumulate
+ uint64_t addend = (uint64_t)GPRs[RdLo] | ((uint64_t)GPRs[RdHi] << 32);
+ result += addend;
+ }
+
+ if (UAS & 1) {
+ CPSR &= ~(CPSR_N | CPSR_Z);
+ CPSR |= result ? 0 : CPSR_Z;
+ CPSR |= (result & 0x8000000000000000) ? CPSR_N : 0;
+ }
+
+ GPRs[RdLo] = result & 0xFFFFFFFF;
+ GPRs[RdHi] = result >> 32;
+
+ return 0;
}
-uint32_t ARM710::execSingleDataSwap(bool B, uint32_t Rn, uint32_t Rd, uint32_t Rm)
-{
- auto valueSize = B ? V8 : V32;
- auto readResult = readVirtual(GPRs[Rn], valueSize);
- auto fault = readResult.second;
+uint32_t ARM710::execSingleDataSwap(bool B, uint32_t Rn, uint32_t Rd,
+ uint32_t Rm) {
+ auto valueSize = B ? V8 : V32;
+ auto readResult = readVirtual(GPRs[Rn], valueSize);
+ auto fault = readResult.second;
- if (fault == NoFault) {
- fault = writeVirtual(GPRs[Rm], GPRs[Rn], valueSize);
- if (fault == NoFault)
- GPRs[Rd] = readResult.first.value();
- }
+ if (fault == NoFault) {
+ fault = writeVirtual(GPRs[Rm], GPRs[Rn], valueSize);
+ if (fault == NoFault)
+ GPRs[Rd] = readResult.first.value();
+ }
- if (fault != NoFault)
- reportFault(fault);
+ if (fault != NoFault)
+ reportFault(fault);
- return 1;
+ return 1;
}
-uint32_t ARM710::execSingleDataTransfer(uint32_t IPUBWL, uint32_t Rn, uint32_t Rd, uint32_t offset)
-{
- bool load = extract1(IPUBWL, 0);
- bool writeback = extract1(IPUBWL, 1);
- auto valueSize = extract1(IPUBWL, 2) ? V8 : V32;
- bool up = extract1(IPUBWL, 3);
- bool preIndex = extract1(IPUBWL, 4);
- bool immediate = !extract1(IPUBWL, 5);
-
- // calculate the offset
- uint32_t calcOffset;
- if (!immediate) {
- // REGISTER
- uint32_t Rm = extract(offset, 3, 0);
- calcOffset = GPRs[Rm];
-
- uint8_t shiftBy = extract(offset, 11, 7);
-
- switch (extract(offset, 6, 5)) {
- case 0: // Logical Left (LSL)
- if (shiftBy > 0)
- calcOffset <<= shiftBy;
- break;
- case 1: // Logical Right (LSR)
- if (shiftBy == 0)
- calcOffset = 0;
- else
- calcOffset >>= shiftBy;
- break;
- case 2: // Arithmetic Right (ASR)
- if (shiftBy == 0)
- calcOffset = (int32_t)calcOffset >> 31;
- else
- calcOffset = (int32_t)calcOffset >> shiftBy;
- break;
- case 3: // Rotate Right (ROR)
- if (shiftBy == 0) { // treated as RRX
- calcOffset >>= 1;
- calcOffset |= flagC() ? 0x80000000 : 0;
- } else
- calcOffset = ROR(calcOffset, shiftBy);
- break;
- }
- } else {
- // IMMEDIATE
- // No rotation or anything here
- calcOffset = offset;
- }
-
- uint32_t base = GPRs[Rn];
- if (Rn == 15) base -= 4; // prefetch adjustment
- uint32_t modifiedBase = up ? (base + calcOffset) : (base - calcOffset);
- uint32_t transferAddr = preIndex ? modifiedBase : base;
-
- bool changeModes = !preIndex && writeback && isPrivileged();
- auto saveMode = currentMode();
-
- MMUFault fault;
-
- if (load) {
- if (changeModes) switchMode(User32);
- auto readResult = readVirtual(transferAddr, valueSize);
- if (changeModes) switchMode(saveMode);
- if (readResult.first.has_value()) {
- GPRs[Rd] = readResult.first.value();
- if (Rd == 15) prefetchCount = 0;
- }
- fault = readResult.second;
- } else {
- uint32_t value = GPRs[Rd];
- if (changeModes) switchMode(User32);
- fault = writeVirtual(value, transferAddr, valueSize);
- if (changeModes) switchMode(saveMode);
- }
-
- if ((preIndex && writeback) || !preIndex)
- GPRs[Rn] = modifiedBase;
-
- if (fault != NoFault)
- reportFault(fault);
-
- return 2;
+uint32_t ARM710::execSingleDataTransfer(uint32_t IPUBWL, uint32_t Rn,
+ uint32_t Rd, uint32_t offset) {
+ bool load = extract1(IPUBWL, 0);
+ bool writeback = extract1(IPUBWL, 1);
+ auto valueSize = extract1(IPUBWL, 2) ? V8 : V32;
+ bool up = extract1(IPUBWL, 3);
+ bool preIndex = extract1(IPUBWL, 4);
+ bool immediate = !extract1(IPUBWL, 5);
+
+ // calculate the offset
+ uint32_t calcOffset;
+ if (!immediate) {
+ // REGISTER
+ uint32_t Rm = extract(offset, 3, 0);
+ calcOffset = GPRs[Rm];
+
+ uint8_t shiftBy = extract(offset, 11, 7);
+
+ switch (extract(offset, 6, 5)) {
+ case 0: // Logical Left (LSL)
+ if (shiftBy > 0)
+ calcOffset <<= shiftBy;
+ break;
+ case 1: // Logical Right (LSR)
+ if (shiftBy == 0)
+ calcOffset = 0;
+ else
+ calcOffset >>= shiftBy;
+ break;
+ case 2: // Arithmetic Right (ASR)
+ if (shiftBy == 0)
+ calcOffset = (int32_t)calcOffset >> 31;
+ else
+ calcOffset = (int32_t)calcOffset >> shiftBy;
+ break;
+ case 3: // Rotate Right (ROR)
+ if (shiftBy == 0) { // treated as RRX
+ calcOffset >>= 1;
+ calcOffset |= flagC() ? 0x80000000 : 0;
+ } else
+ calcOffset = ROR(calcOffset, shiftBy);
+ break;
+ }
+ } else {
+ // IMMEDIATE
+ // No rotation or anything here
+ calcOffset = offset;
+ }
+
+ uint32_t base = GPRs[Rn];
+ if (Rn == 15)
+ base -= 4; // prefetch adjustment
+ uint32_t modifiedBase = up ? (base + calcOffset) : (base - calcOffset);
+ uint32_t transferAddr = preIndex ? modifiedBase : base;
+
+ bool changeModes = !preIndex && writeback && isPrivileged();
+ auto saveMode = currentMode();
+
+ MMUFault fault;
+
+ if (load) {
+ if (changeModes)
+ switchMode(User32);
+ auto readResult = readVirtual(transferAddr, valueSize);
+ if (changeModes)
+ switchMode(saveMode);
+ if (readResult.first.has_value()) {
+ GPRs[Rd] = readResult.first.value();
+ if (Rd == 15)
+ prefetchCount = 0;
+ }
+ fault = readResult.second;
+ } else {
+ uint32_t value = GPRs[Rd];
+ if (changeModes)
+ switchMode(User32);
+ fault = writeVirtual(value, transferAddr, valueSize);
+ if (changeModes)
+ switchMode(saveMode);
+ }
+
+ if ((preIndex && writeback) || !preIndex)
+ GPRs[Rn] = modifiedBase;
+
+ if (fault != NoFault)
+ reportFault(fault);
+
+ return 2;
}
-uint32_t ARM710::execSingleHalfWordDataTransfer(uint32_t PUIWL, uint32_t Rn, uint32_t Rd, uint32_t addrMode1, uint32_t SH, uint32_t addrMode2)
-{
- bool load = extract1(PUIWL, 0);
- bool writeback = extract1(PUIWL, 1);
- bool immediate = extract1(PUIWL, 2);
- bool up = extract1(PUIWL, 3);
- bool preIndex = extract1(PUIWL, 4);
-
- uint32_t LSH = ((PUIWL << 2) | SH) & 0x7;
- ValueSize valueSize;
- bool isSigned;
-
- switch (LSH) {
- case 0x1:
- valueSize = V16;
- isSigned = false;
- break;
- case 0x5:
- valueSize = V16;
- isSigned = false;
- break;
- case 0x6:
- valueSize = V8;
- isSigned = true;
- break;
- case 0x7:
- valueSize = V16;
- isSigned = true;
- break;
- default:
- // Invalid instruction on ARMv4 as it doesn't support double word ldr/str
- return 2;
- }
-
- // calculate the offset
- uint32_t calcOffset;
- if (!immediate) {
- // addrMode1 should be zero (SBZ)
- // addrMode2 is Rm
- calcOffset = GPRs[addrMode2];
- } else {
- // IMMEDIATE
- // No rotation or anything here
- // addrMode1 is the high 4 bits
- // addrMode2 is the low 4 bits
- calcOffset = (addrMode1 << 4) | addrMode2;
- }
-
- uint32_t base = GPRs[Rn];
- if (Rn == 15) base -= 4; // prefetch adjustment
- uint32_t modifiedBase = up ? (base + calcOffset) : (base - calcOffset);
- uint32_t transferAddr = preIndex ? modifiedBase : base;
-
- bool changeModes = !preIndex && writeback && isPrivileged();
- auto saveMode = currentMode();
-
- MMUFault fault;
-
- if (load) {
- if (changeModes) switchMode(User32);
- auto readResult = readVirtual(transferAddr, valueSize);
- if (changeModes) switchMode(saveMode);
- if (readResult.first.has_value()) {
- GPRs[Rd] = readResult.first.value();
- if (Rd == 15) prefetchCount = 0;
- }
- fault = readResult.second;
- } else {
- uint32_t value = GPRs[Rd];
- if (changeModes) switchMode(User32);
- fault = writeVirtual(value, transferAddr, valueSize);
- if (changeModes) switchMode(saveMode);
- }
-
- if ((preIndex && writeback) || !preIndex)
- GPRs[Rn] = modifiedBase;
-
- if (fault != NoFault)
- reportFault(fault);
-
- return 2;
+uint32_t ARM710::execSingleHalfWordDataTransfer(uint32_t PUIWL, uint32_t Rn,
+ uint32_t Rd, uint32_t addrMode1,
+ uint32_t SH,
+ uint32_t addrMode2) {
+ bool load = extract1(PUIWL, 0);
+ bool writeback = extract1(PUIWL, 1);
+ bool immediate = extract1(PUIWL, 2);
+ bool up = extract1(PUIWL, 3);
+ bool preIndex = extract1(PUIWL, 4);
+
+ uint32_t LSH = ((PUIWL << 2) | SH) & 0x7;
+ ValueSize valueSize;
+ bool isSigned;
+
+ switch (LSH) {
+ case 0x1:
+ valueSize = V16;
+ isSigned = false;
+ break;
+ case 0x5:
+ valueSize = V16;
+ isSigned = false;
+ break;
+ case 0x6:
+ valueSize = V8;
+ isSigned = true;
+ break;
+ case 0x7:
+ valueSize = V16;
+ isSigned = true;
+ break;
+ default:
+ // Invalid instruction on ARMv4 as it doesn't support double word ldr/str
+ return 2;
+ }
+
+ // calculate the offset
+ uint32_t calcOffset;
+ if (!immediate) {
+ // addrMode1 should be zero (SBZ)
+ // addrMode2 is Rm
+ calcOffset = GPRs[addrMode2];
+ } else {
+ // IMMEDIATE
+ // No rotation or anything here
+ // addrMode1 is the high 4 bits
+ // addrMode2 is the low 4 bits
+ calcOffset = (addrMode1 << 4) | addrMode2;
+ }
+
+ uint32_t base = GPRs[Rn];
+ if (Rn == 15)
+ base -= 4; // prefetch adjustment
+ uint32_t modifiedBase = up ? (base + calcOffset) : (base - calcOffset);
+ uint32_t transferAddr = preIndex ? modifiedBase : base;
+
+ bool changeModes = !preIndex && writeback && isPrivileged();
+ auto saveMode = currentMode();
+
+ MMUFault fault;
+
+ if (load) {
+ if (changeModes)
+ switchMode(User32);
+ auto readResult = readVirtual(transferAddr, valueSize);
+ if (changeModes)
+ switchMode(saveMode);
+ if (readResult.first.has_value()) {
+ GPRs[Rd] = readResult.first.value();
+ if (Rd == 15)
+ prefetchCount = 0;
+ }
+ fault = readResult.second;
+ } else {
+ uint32_t value = GPRs[Rd];
+ if (changeModes)
+ switchMode(User32);
+ fault = writeVirtual(value, transferAddr, valueSize);
+ if (changeModes)
+ switchMode(saveMode);
+ }
+
+ if ((preIndex && writeback) || !preIndex)
+ GPRs[Rn] = modifiedBase;
+
+ if (fault != NoFault)
+ reportFault(fault);
+
+ return 2;
}
-uint32_t ARM710::execBlockDataTransfer(uint32_t PUSWL, uint32_t Rn, uint32_t registerList)
-{
- bool load = extract1(PUSWL, 0);
- bool store = !load;
- bool writeback = extract1(PUSWL, 1);
- bool psrForceUser = extract1(PUSWL, 2);
- bool up = extract1(PUSWL, 3);
- bool preIndex = extract1(PUSWL, 4);
-
- MMUFault fault = NoFault;
- uint32_t base = GPRs[Rn] & ~3;
- uint32_t blockSize = popcount32(registerList) * 4;
-
- uint32_t lowAddr, updatedBase;
- if (up) {
- updatedBase = base + blockSize;
- lowAddr = base + (preIndex ? 4 : 0);
- } else {
- updatedBase = base - blockSize;
- lowAddr = updatedBase + (preIndex ? 0 : 4);
- }
-
- auto saveBank = bank;
- if (psrForceUser && (store || !(registerList & 0x8000)))
- switchBank(MainBank);
-
- bool doneWriteback = false;
- if (load && writeback) {
- doneWriteback = true;
- GPRs[Rn] = updatedBase;
- }
-
- uint32_t addr = lowAddr;
- for (int i = 0; i < 16; i++) {
- if (registerList & (1 << i)) {
- // work on this one
- if (load) {
- // handling for LDM faults may be kinda iffy...
- // wording on datasheet is a bit unclear
- auto readResult = readVirtual(addr, V32);
- if (readResult.first.has_value())
- GPRs[i] = readResult.first.value();
- if (readResult.second != NoFault) {
- fault = readResult.second;
- break;
- }
- } else {
- auto newFault = writeVirtual(GPRs[i], addr, V32);
- if (newFault != NoFault)
- fault = newFault;
- }
-
- addr += 4;
-
- if (writeback && !doneWriteback) {
- doneWriteback = true;
- GPRs[Rn] = updatedBase;
- }
- }
- }
-
- // datasheet specifies that base register must be
- // restored if an error occurs during LDM
- if (load && fault != NoFault)
- GPRs[Rn] = writeback ? updatedBase : base;
-
- if (psrForceUser && (store || !(registerList & 0x8000)))
- switchBank(saveBank);
-
- if (load && (registerList & 0x8000)) {
- prefetchCount = 0;
- if (psrForceUser && isPrivileged() && fault == NoFault) {
- auto saved = SPSRs[currentBank()];
- switchMode(modeFromCPSR(saved));
- CPSR = saved;
-// log("reloading saved SPSR: %08x", saved);
- }
- }
-
- if (fault != NoFault)
- reportFault(fault);
-
- return 0; // fixme
+uint32_t ARM710::execBlockDataTransfer(uint32_t PUSWL, uint32_t Rn,
+ uint32_t registerList) {
+ bool load = extract1(PUSWL, 0);
+ bool store = !load;
+ bool writeback = extract1(PUSWL, 1);
+ bool psrForceUser = extract1(PUSWL, 2);
+ bool up = extract1(PUSWL, 3);
+ bool preIndex = extract1(PUSWL, 4);
+
+ MMUFault fault = NoFault;
+ uint32_t base = GPRs[Rn] & ~3;
+ uint32_t blockSize = popcount32(registerList) * 4;
+
+ uint32_t lowAddr, updatedBase;
+ if (up) {
+ updatedBase = base + blockSize;
+ lowAddr = base + (preIndex ? 4 : 0);
+ } else {
+ updatedBase = base - blockSize;
+ lowAddr = updatedBase + (preIndex ? 0 : 4);
+ }
+
+ auto saveBank = bank;
+ if (psrForceUser && (store || !(registerList & 0x8000)))
+ switchBank(MainBank);
+
+ bool doneWriteback = false;
+ if (load && writeback) {
+ doneWriteback = true;
+ GPRs[Rn] = updatedBase;
+ }
+
+ uint32_t addr = lowAddr;
+ for (int i = 0; i < 16; i++) {
+ if (registerList & (1 << i)) {
+ // work on this one
+ if (load) {
+ // handling for LDM faults may be kinda iffy...
+ // wording on datasheet is a bit unclear
+ auto readResult = readVirtual(addr, V32);
+ if (readResult.first.has_value())
+ GPRs[i] = readResult.first.value();
+ if (readResult.second != NoFault) {
+ fault = readResult.second;
+ break;
+ }
+ } else {
+ auto newFault = writeVirtual(GPRs[i], addr, V32);
+ if (newFault != NoFault)
+ fault = newFault;
+ }
+
+ addr += 4;
+
+ if (writeback && !doneWriteback) {
+ doneWriteback = true;
+ GPRs[Rn] = updatedBase;
+ }
+ }
+ }
+
+ // datasheet specifies that base register must be
+ // restored if an error occurs during LDM
+ if (load && fault != NoFault)
+ GPRs[Rn] = writeback ? updatedBase : base;
+
+ if (psrForceUser && (store || !(registerList & 0x8000)))
+ switchBank(saveBank);
+
+ if (load && (registerList & 0x8000)) {
+ prefetchCount = 0;
+ if (psrForceUser && isPrivileged() && fault == NoFault) {
+ auto saved = SPSRs[currentBank()];
+ switchMode(modeFromCPSR(saved));
+ CPSR = saved;
+ // log("reloading saved SPSR: %08x", saved);
+ }
+ }
+
+ if (fault != NoFault)
+ reportFault(fault);
+
+ return 0; // fixme
}
-uint32_t ARM710::execBranch(bool L, uint32_t offset)
-{
- if (L)
- GPRs[14] = GPRs[15] - 8;
+uint32_t ARM710::execBranch(bool L, uint32_t offset) {
+ if (L)
+ GPRs[14] = GPRs[15] - 8;
- // start with 24 bits, shift left 2, sign extend to 32
- int32_t sextOffset = (int32_t)(offset << 8) >> 6;
+ // start with 24 bits, shift left 2, sign extend to 32
+ int32_t sextOffset = (int32_t)(offset << 8) >> 6;
- prefetchCount = 0;
- GPRs[15] -= 4; // account for our prefetch being +4 too much
- GPRs[15] += sextOffset;
- return 0;
+ prefetchCount = 0;
+ GPRs[15] -= 4; // account for our prefetch being +4 too much
+ GPRs[15] += sextOffset;
+ return 0;
}
-uint32_t ARM710::execCP15RegisterTransfer(uint32_t CPOpc, bool L, uint32_t CRn, uint32_t Rd, uint32_t CP, uint32_t CRm)
-{
- (void)CP;
- (void)CRm;
-
- if (!isPrivileged())
- return 0;
-
- if (L) {
- // read a value
- uint32_t what = 0;
-
- switch (CRn) {
- case 0: what = cp15_id; break;
- case 3: what = cp15_domainAccessControl; break;
- case 5: what = cp15_faultStatus; break;
- case 6: what = cp15_faultAddress; break;
- }
-
- if (Rd == 15)
- CPSR = (CPSR & ~CPSR_FlagMask) | (what & CPSR_FlagMask);
- else
- GPRs[Rd] = what;
- } else {
- // store a value
- uint32_t what = GPRs[Rd];
-
- switch (CRn) {
- case 1: cp15_control = what; log("setting cp15_control to %08x", what); break;
- case 2: cp15_translationTableBase = what; break;
- case 3: cp15_domainAccessControl = what; break;
- case 5:
- if (isTVersion)
- cp15_faultStatus = what;
+uint32_t ARM710::execCP15RegisterTransfer(uint32_t CPOpc, bool L, uint32_t CRn,
+ uint32_t Rd, uint32_t CP,
+ uint32_t CRm) {
+ (void)CP;
+ (void)CRm;
+
+ if (!isPrivileged())
+ return 0;
+
+ if (L) {
+ // read a value
+ uint32_t what = 0;
+
+ switch (CRn) {
+ case 0:
+ what = cp15_id;
+ break;
+ case 3:
+ what = cp15_domainAccessControl;
+ break;
+ case 5:
+ what = cp15_faultStatus;
+ break;
+ case 6:
+ what = cp15_faultAddress;
+ break;
+ }
+
+ if (Rd == 15)
+ CPSR = (CPSR & ~CPSR_FlagMask) | (what & CPSR_FlagMask);
+ else
+ GPRs[Rd] = what;
+ } else {
+ // store a value
+ uint32_t what = GPRs[Rd];
+
+ switch (CRn) {
+ case 1:
+ cp15_control = what;
+ log("setting cp15_control to %08x", what);
+ break;
+ case 2:
+ cp15_translationTableBase = what;
+ break;
+ case 3:
+ cp15_domainAccessControl = what;
+ break;
+ case 5:
+ if (isTVersion)
+ cp15_faultStatus = what;
#ifdef ARM710T_TLB
- else
- flushTlb();
+ else
+ flushTlb();
#endif
- break;
- case 6:
- if (isTVersion)
- cp15_faultAddress = what;
+ break;
+ case 6:
+ if (isTVersion)
+ cp15_faultAddress = what;
#ifdef ARM710T_TLB
- else
- flushTlb(what);
- break;
+ else
+ flushTlb(what);
+ break;
#endif
- case 7:
+ case 7:
#ifdef ARM710T_CACHE
- clearCache();
- log("cache cleared");
+ clearCache();
+ log("cache cleared");
#endif
- break;
- case 8: {
+ break;
+ case 8: {
#ifdef ARM710T_TLB
- if (isTVersion) {
- if (CPOpc == 1)
- flushTlb(what);
- else
- flushTlb();
- }
+ if (isTVersion) {
+ if (CPOpc == 1)
+ flushTlb(what);
+ else
+ flushTlb();
+ }
#endif
- break;
- }
- }
- }
+ break;
+ }
+ }
+ }
- return 0;
+ return 0;
}
-
-
#ifdef ARM710T_CACHE
void ARM710T::clearCache() {
- for (uint32_t i = 0; i < CacheSets; i++) {
- for (uint32_t j = 0; j < CacheBlocksPerSet; j++) {
- cacheBlockTags[i][j] = 0;
- }
- }
+ for (uint32_t i = 0; i < CacheSets; i++) {
+ for (uint32_t j = 0; j < CacheBlocksPerSet; j++) {
+ cacheBlockTags[i][j] = 0;
+ }
+ }
}
-uint8_t *ARM710T::findCacheLine(uint32_t virtAddr) {
- uint32_t set = virtAddr & CacheAddressSetMask;
- uint32_t tag = virtAddr & CacheAddressTagMask;
- set >>= CacheAddressSetShift;
+uint8_t* ARM710T::findCacheLine(uint32_t virtAddr) {
+ uint32_t set = virtAddr & CacheAddressSetMask;
+ uint32_t tag = virtAddr & CacheAddressTagMask;
+ set >>= CacheAddressSetShift;
- for (uint32_t i = 0; i < CacheBlocksPerSet; i++) {
- if (cacheBlockTags[set][i] & CacheBlockEnabled) {
- if ((cacheBlockTags[set][i] & ~CacheBlockEnabled) == tag)
- return &cacheBlocks[set][i][0];
- }
- }
+ for (uint32_t i = 0; i < CacheBlocksPerSet; i++) {
+ if (cacheBlockTags[set][i] & CacheBlockEnabled) {
+ if ((cacheBlockTags[set][i] & ~CacheBlockEnabled) == tag)
+ return &cacheBlocks[set][i][0];
+ }
+ }
- return nullptr;
+ return nullptr;
}
-pair<MaybeU32, ARM710T::MMUFault> ARM710T::addCacheLineAndRead(uint32_t physAddr, uint32_t virtAddr, ValueSize valueSize, int domain, bool isPage) {
- uint32_t set = virtAddr & CacheAddressSetMask;
- uint32_t tag = virtAddr & CacheAddressTagMask;
- set >>= CacheAddressSetShift;
-
- // "it will be randomly placed in a cache bank"
- // - the ARM710a data sheet, 6-2 (p90)
- uint32_t i = rand() % CacheBlocksPerSet;
- uint8_t *block = &cacheBlocks[set][i][0];
- MaybeU32 result;
- MMUFault fault = NoFault;
-
- for (uint32_t j = 0; j < CacheBlockSize; j += 4) {
- auto word = readPhysical((physAddr & ~CacheAddressLineMask) + j, V32);
- if (word.has_value()) {
- write32LE(&block[j], word.value());
- if (valueSize == V8 && j == (virtAddr & CacheAddressLineMask & ~3))
- result = (word.value() >> ((virtAddr & 3) * 8)) & 0xFF;
- else if (valueSize == V32 && j == (virtAddr & CacheAddressLineMask))
- result = word.value();
- } else {
- // read error, great
- // TODO: should probably prioritise specific kinds of faults over others
- fault = encodeFaultSorP(SorPLinefetchError, isPage, domain, virtAddr & ~CacheAddressLineMask);
- break;
- }
- }
-
- // the cache block is only stored if it's complete
- if (fault == NoFault)
- cacheBlockTags[set][i] = tag | CacheBlockEnabled;
-
- return make_pair(result, fault);
+pair<MaybeU32, ARM710T::MMUFault>
+ARM710T::addCacheLineAndRead(uint32_t physAddr, uint32_t virtAddr,
+ ValueSize valueSize, int domain, bool isPage) {
+ uint32_t set = virtAddr & CacheAddressSetMask;
+ uint32_t tag = virtAddr & CacheAddressTagMask;
+ set >>= CacheAddressSetShift;
+
+ // "it will be randomly placed in a cache bank"
+ // - the ARM710a data sheet, 6-2 (p90)
+ uint32_t i = rand() % CacheBlocksPerSet;
+ uint8_t* block = &cacheBlocks[set][i][0];
+ MaybeU32 result;
+ MMUFault fault = NoFault;
+
+ for (uint32_t j = 0; j < CacheBlockSize; j += 4) {
+ auto word = readPhysical((physAddr & ~CacheAddressLineMask) + j, V32);
+ if (word.has_value()) {
+ write32LE(&block[j], word.value());
+ if (valueSize == V8 && j == (virtAddr & CacheAddressLineMask & ~3))
+ result = (word.value() >> ((virtAddr & 3) * 8)) & 0xFF;
+ else if (valueSize == V32 && j == (virtAddr & CacheAddressLineMask))
+ result = word.value();
+ } else {
+ // read error, great
+ // TODO: should probably prioritise specific kinds of faults over others
+ fault = encodeFaultSorP(SorPLinefetchError, isPage, domain,
+ virtAddr & ~CacheAddressLineMask);
+ break;
+ }
+ }
+
+ // the cache block is only stored if it's complete
+ if (fault == NoFault)
+ cacheBlockTags[set][i] = tag | CacheBlockEnabled;
+
+ return make_pair(result, fault);
}
MaybeU32 ARM710T::readCached(uint32_t virtAddr, ValueSize valueSize) {
- uint8_t *line = findCacheLine(virtAddr);
- if (line) {
- if (valueSize == V8)
- return line[virtAddr & CacheAddressLineMask];
- else /*if (valueSize == V32)*/
- return read32LE(&line[virtAddr & CacheAddressLineMask]);
- }
- return {};
+ uint8_t* line = findCacheLine(virtAddr);
+ if (line) {
+ if (valueSize == V8)
+ return line[virtAddr & CacheAddressLineMask];
+ else /*if (valueSize == V32)*/
+ return read32LE(&line[virtAddr & CacheAddressLineMask]);
+ }
+ return {};
}
-
-bool ARM710T::writeCached(uint32_t value, uint32_t virtAddr, ValueSize valueSize) {
- uint8_t *line = findCacheLine(virtAddr);
- if (line) {
- if (valueSize == V8)
- line[virtAddr & CacheAddressLineMask] = value & 0xFF;
- else /*if (valueSize == V32)*/
- write32LE(&line[virtAddr & CacheAddressLineMask], value);
- return true;
- }
- return false;
+bool ARM710T::writeCached(uint32_t value, uint32_t virtAddr,
+ ValueSize valueSize) {
+ uint8_t* line = findCacheLine(virtAddr);
+ if (line) {
+ if (valueSize == V8)
+ line[virtAddr & CacheAddressLineMask] = value & 0xFF;
+ else /*if (valueSize == V32)*/
+ write32LE(&line[virtAddr & CacheAddressLineMask], value);
+ return true;
+ }
+ return false;
}
#endif
-
-uint32_t ARM710::physAddrFromTlbEntry(TlbEntry *tlbEntry, uint32_t virtAddr) {
- if ((tlbEntry->lv2Entry & 3) == 2) {
- // Smøl page
- return (tlbEntry->lv2Entry & 0xFFFFF000) | (virtAddr & 0xFFF);
- } else if ((tlbEntry->lv2Entry & 3) == 1) {
- // Lørge page
- return (tlbEntry->lv2Entry & 0xFFFF0000) | (virtAddr & 0xFFFF);
- } else {
- // Section
- return (tlbEntry->lv1Entry & 0xFFF00000) | (virtAddr & 0xFFFFF);
- }
+uint32_t ARM710::physAddrFromTlbEntry(TlbEntry* tlbEntry, uint32_t virtAddr) {
+ if ((tlbEntry->lv2Entry & 3) == 2) {
+ // Smøl page
+ return (tlbEntry->lv2Entry & 0xFFFFF000) | (virtAddr & 0xFFF);
+ } else if ((tlbEntry->lv2Entry & 3) == 1) {
+ // Lørge page
+ return (tlbEntry->lv2Entry & 0xFFFF0000) | (virtAddr & 0xFFFF);
+ } else {
+ // Section
+ return (tlbEntry->lv1Entry & 0xFFF00000) | (virtAddr & 0xFFFFF);
+ }
}
-
MaybeU32 ARM710::virtToPhys(uint32_t virtAddr) {
- if (!isMMUEnabled())
- return virtAddr;
-
- TlbEntry tempEntry;
- auto translated = translateAddressUsingTlb(virtAddr, &tempEntry);
- if (holds_alternative<TlbEntry *>(translated)) {
- auto tlbEntry = get<TlbEntry *>(translated);
- return physAddrFromTlbEntry(tlbEntry, virtAddr);
- } else {
- return MaybeU32();
- }
+ if (!isMMUEnabled())
+ return virtAddr;
+
+ TlbEntry tempEntry;
+ auto translated = translateAddressUsingTlb(virtAddr, &tempEntry);
+ if (holds_alternative<TlbEntry*>(translated)) {
+ auto tlbEntry = get<TlbEntry*>(translated);
+ return physAddrFromTlbEntry(tlbEntry, virtAddr);
+ } else {
+ return MaybeU32();
+ }
}
-
MaybeU32 ARM710::readVirtualDebug(uint32_t virtAddr, ValueSize valueSize) {
- if (auto v = virtToPhys(virtAddr); v.has_value())
- return readPhysical(v.value(), valueSize);
- else
- return {};
+ if (auto v = virtToPhys(virtAddr); v.has_value())
+ return readPhysical(v.value(), valueSize);
+ else
+ return {};
}
+pair<MaybeU32, ARM710::MMUFault> ARM710::readVirtual(uint32_t virtAddr,
+ ValueSize valueSize) {
+ if (isAlignmentFaultEnabled() && valueSize == V32 && virtAddr & 3)
+ return make_pair(MaybeU32(), encodeFault(AlignmentFault, 0, virtAddr));
-pair<MaybeU32, ARM710::MMUFault> ARM710::readVirtual(uint32_t virtAddr, ValueSize valueSize) {
- if (isAlignmentFaultEnabled() && valueSize == V32 && virtAddr & 3)
- return make_pair(MaybeU32(), encodeFault(AlignmentFault, 0, virtAddr));
-
- // fast path: cache
+ // fast path: cache
#ifdef ARM710T_CACHE
- if (auto v = readCached(virtAddr, valueSize); v.has_value())
- return make_pair(v.value(), NoFault);
+ if (auto v = readCached(virtAddr, valueSize); v.has_value())
+ return make_pair(v.value(), NoFault);
#endif
- if (!isMMUEnabled()) {
- // things are very simple without a MMU
- if (auto v = readPhysical(virtAddr, valueSize); v.has_value())
- return make_pair(v.value(), NoFault);
- else
- return make_pair(MaybeU32(), encodeFault(NonMMUError, 0, virtAddr));
- }
+ if (!isMMUEnabled()) {
+ // things are very simple without a MMU
+ if (auto v = readPhysical(virtAddr, valueSize); v.has_value())
+ return make_pair(v.value(), NoFault);
+ else
+ return make_pair(MaybeU32(), encodeFault(NonMMUError, 0, virtAddr));
+ }
- auto translated = translateAddressUsingTlb(virtAddr);
- if (holds_alternative<MMUFault>(translated))
- return make_pair(MaybeU32(), get<MMUFault>(translated));
+ auto translated = translateAddressUsingTlb(virtAddr);
+ if (holds_alternative<MMUFault>(translated))
+ return make_pair(MaybeU32(), get<MMUFault>(translated));
- // resolve this boy
- auto tlbEntry = get<TlbEntry *>(translated);
+ // resolve this boy
+ auto tlbEntry = get<TlbEntry*>(translated);
- if (auto f = checkAccessPermissions(tlbEntry, virtAddr, false); f != NoFault)
- return make_pair(MaybeU32(), f);
+ if (auto f = checkAccessPermissions(tlbEntry, virtAddr, false); f != NoFault)
+ return make_pair(MaybeU32(), f);
- int domain = (tlbEntry->lv1Entry >> 5) & 0xF;
- bool isPage = (tlbEntry->lv2Entry != 0);
+ int domain = (tlbEntry->lv1Entry >> 5) & 0xF;
+ bool isPage = (tlbEntry->lv2Entry != 0);
- uint32_t physAddr = physAddrFromTlbEntry(tlbEntry, virtAddr);
+ uint32_t physAddr = physAddrFromTlbEntry(tlbEntry, virtAddr);
#ifdef ARM710T_CACHE
- bool cacheable = tlbEntry->lv2Entry ? (tlbEntry->lv2Entry & 8) : (tlbEntry->lv1Entry & 8);
- if (cacheable && isCacheEnabled())
- return addCacheLineAndRead(physAddr, virtAddr, valueSize, domain, isPage);
- else
+ bool cacheable =
+ tlbEntry->lv2Entry ? (tlbEntry->lv2Entry & 8) : (tlbEntry->lv1Entry & 8);
+ if (cacheable && isCacheEnabled())
+ return addCacheLineAndRead(physAddr, virtAddr, valueSize, domain, isPage);
+ else
#endif
- if (auto result = readPhysical(physAddr, valueSize); result.has_value())
- return make_pair(result, NoFault);
- else
- return make_pair(result, encodeFaultSorP(SorPOtherBusError, isPage, domain, virtAddr));
+ if (auto result = readPhysical(physAddr, valueSize); result.has_value())
+ return make_pair(result, NoFault);
+ else
+ return make_pair(
+ result, encodeFaultSorP(SorPOtherBusError, isPage, domain, virtAddr));
}
-ARM710::MMUFault ARM710::writeVirtual(uint32_t value, uint32_t virtAddr, ValueSize valueSize) {
- if (isAlignmentFaultEnabled() && valueSize == V32 && virtAddr & 3)
- return encodeFault(AlignmentFault, 0, virtAddr);
+ARM710::MMUFault ARM710::writeVirtual(uint32_t value, uint32_t virtAddr,
+ ValueSize valueSize) {
+ if (isAlignmentFaultEnabled() && valueSize == V32 && virtAddr & 3)
+ return encodeFault(AlignmentFault, 0, virtAddr);
- if (!isMMUEnabled()) {
- // direct virtual -> physical mapping, sans MMU
- if (!writePhysical(value, virtAddr, valueSize))
- return encodeFault(NonMMUError, 0, virtAddr);
- } else {
- auto translated = translateAddressUsingTlb(virtAddr);
- if (holds_alternative<MMUFault>(translated))
- return get<MMUFault>(translated);
+ if (!isMMUEnabled()) {
+ // direct virtual -> physical mapping, sans MMU
+ if (!writePhysical(value, virtAddr, valueSize))
+ return encodeFault(NonMMUError, 0, virtAddr);
+ } else {
+ auto translated = translateAddressUsingTlb(virtAddr);
+ if (holds_alternative<MMUFault>(translated))
+ return get<MMUFault>(translated);
- // resolve this boy
- auto tlbEntry = get<TlbEntry *>(translated);
+ // resolve this boy
+ auto tlbEntry = get<TlbEntry*>(translated);
- if (auto f = checkAccessPermissions(tlbEntry, virtAddr, true); f != NoFault)
- return f;
+ if (auto f = checkAccessPermissions(tlbEntry, virtAddr, true); f != NoFault)
+ return f;
- uint32_t physAddr = physAddrFromTlbEntry(tlbEntry, virtAddr);
- int domain = (tlbEntry->lv1Entry >> 5) & 0xF;
- bool isPage = (tlbEntry->lv2Entry != 0);
+ uint32_t physAddr = physAddrFromTlbEntry(tlbEntry, virtAddr);
+ int domain = (tlbEntry->lv1Entry >> 5) & 0xF;
+ bool isPage = (tlbEntry->lv2Entry != 0);
- if (!writePhysical(value, physAddr, valueSize))
- return encodeFaultSorP(SorPOtherBusError, isPage, domain, virtAddr);
- }
+ if (!writePhysical(value, physAddr, valueSize))
+ return encodeFaultSorP(SorPOtherBusError, isPage, domain, virtAddr);
+ }
- // commit to cache if all was good
+ // commit to cache if all was good
#ifdef ARM710T_CACHE
- writeCached(value, virtAddr, valueSize);
+ writeCached(value, virtAddr, valueSize);
#endif
- return NoFault;
+ return NoFault;
}
-
-
// TLB
#ifdef ARM710T_TLB
void ARM710::flushTlb() {
- for (TlbEntry &e : tlb)
- e = {0, 0, 0, 0};
+ for (TlbEntry& e : tlb)
+ e = {0, 0, 0, 0};
}
void ARM710::flushTlb(uint32_t virtAddr) {
- for (TlbEntry &e : tlb) {
- if (e.addrMask && (virtAddr & e.addrMask) == e.addr) {
- e = {0, 0, 0, 0};
- break;
- }
- }
+ for (TlbEntry& e : tlb) {
+ if (e.addrMask && (virtAddr & e.addrMask) == e.addr) {
+ e = {0, 0, 0, 0};
+ break;
+ }
+ }
}
#endif
-ARM710::TlbEntry *ARM710::_allocateTlbEntry(uint32_t addrMask, uint32_t addr) {
+ARM710::TlbEntry* ARM710::_allocateTlbEntry(uint32_t addrMask, uint32_t addr) {
#ifdef ARM710T_TLB
- TlbEntry *entry = &tlb[nextTlbIndex];
- nextTlbIndex = (nextTlbIndex + 1) % TlbSize;
+ TlbEntry* entry = &tlb[nextTlbIndex];
+ nextTlbIndex = (nextTlbIndex + 1) % TlbSize;
#else
- TlbEntry *entry = &singleTlbEntry;
+ TlbEntry* entry = &singleTlbEntry;
#endif
- entry->addrMask = addrMask;
- entry->addr = addr & addrMask;
- return entry;
+ entry->addrMask = addrMask;
+ entry->addr = addr & addrMask;
+ return entry;
}
-variant<ARM710::TlbEntry *, ARM710::MMUFault> ARM710::translateAddressUsingTlb(uint32_t virtAddr, TlbEntry *useMe) {
+variant<ARM710::TlbEntry*, ARM710::MMUFault>
+ARM710::translateAddressUsingTlb(uint32_t virtAddr, TlbEntry* useMe) {
#ifdef ARM710T_TLB
- // first things first, do we have a matching entry in the TLB?
- for (TlbEntry &e : tlb) {
- if (e.addrMask && (virtAddr & e.addrMask) == e.addr)
- return &e;
- }
+ // first things first, do we have a matching entry in the TLB?
+ for (TlbEntry& e : tlb) {
+ if (e.addrMask && (virtAddr & e.addrMask) == e.addr)
+ return &e;
+ }
#endif
- // no, so do a page table walk
- TlbEntry *entry;
- uint32_t tableIndex = virtAddr >> 20;
-
- // fetch the Level 1 entry
- auto lv1EntryOpt = readPhysical(cp15_translationTableBase | (tableIndex << 2), V32);
- if (!lv1EntryOpt.has_value())
- return Lv1TranslationError;
- auto lv1Entry = lv1EntryOpt.value();
- int domain = (lv1Entry >> 5) & 0xF;
-
- switch (lv1Entry & 3) {
- case 0:
- case 3:
- // invalid!
- return encodeFault(SectionTranslationFault, domain, virtAddr);
- case 2:
- // a Section entry is straightforward
- // we just throw that immediately into the TLB
- entry = useMe ? useMe : _allocateTlbEntry(0xFFF00000, virtAddr);
- entry->lv1Entry = lv1Entry;
- entry->lv2Entry = 0;
- return entry;
- case 1:
- // a Page requires a Level 2 read
- uint32_t pageTableAddr = lv1Entry & 0xFFFFFC00;
- uint32_t lv2TableIndex = (virtAddr >> 12) & 0xFF;
-
- auto lv2EntryOpt = readPhysical(pageTableAddr | (lv2TableIndex << 2), V32);
- if (!lv2EntryOpt.has_value())
- return encodeFault(Lv2TranslationError, domain, virtAddr);
- auto lv2Entry = lv2EntryOpt.value();
-
- switch (lv2Entry & 3) {
- case 0:
- case 3:
- // invalid!
- return encodeFault(PageTranslationFault, domain, virtAddr);
- case 1:
- // Large 64kb page
- entry = useMe ? useMe : _allocateTlbEntry(0xFFFF0000, virtAddr);
- entry->lv1Entry = lv1Entry;
- entry->lv2Entry = lv2Entry;
- return entry;
- case 2:
- // Small 4kb page
- entry = useMe ? useMe : _allocateTlbEntry(0xFFFFF000, virtAddr);
- entry->lv1Entry = lv1Entry;
- entry->lv2Entry = lv2Entry;
- return entry;
- }
- }
-
- // we should never get here as the switch covers 0, 1, 2, 3
- // but this satisfies a compiler warning
- return SectionTranslationFault;
+ // no, so do a page table walk
+ TlbEntry* entry;
+ uint32_t tableIndex = virtAddr >> 20;
+
+ // fetch the Level 1 entry
+ auto lv1EntryOpt =
+ readPhysical(cp15_translationTableBase | (tableIndex << 2), V32);
+ if (!lv1EntryOpt.has_value())
+ return Lv1TranslationError;
+ auto lv1Entry = lv1EntryOpt.value();
+ int domain = (lv1Entry >> 5) & 0xF;
+
+ switch (lv1Entry & 3) {
+ case 0:
+ case 3:
+ // invalid!
+ return encodeFault(SectionTranslationFault, domain, virtAddr);
+ case 2:
+ // a Section entry is straightforward
+ // we just throw that immediately into the TLB
+ entry = useMe ? useMe : _allocateTlbEntry(0xFFF00000, virtAddr);
+ entry->lv1Entry = lv1Entry;
+ entry->lv2Entry = 0;
+ return entry;
+ case 1:
+ // a Page requires a Level 2 read
+ uint32_t pageTableAddr = lv1Entry & 0xFFFFFC00;
+ uint32_t lv2TableIndex = (virtAddr >> 12) & 0xFF;
+
+ auto lv2EntryOpt = readPhysical(pageTableAddr | (lv2TableIndex << 2), V32);
+ if (!lv2EntryOpt.has_value())
+ return encodeFault(Lv2TranslationError, domain, virtAddr);
+ auto lv2Entry = lv2EntryOpt.value();
+
+ switch (lv2Entry & 3) {
+ case 0:
+ case 3:
+ // invalid!
+ return encodeFault(PageTranslationFault, domain, virtAddr);
+ case 1:
+ // Large 64kb page
+ entry = useMe ? useMe : _allocateTlbEntry(0xFFFF0000, virtAddr);
+ entry->lv1Entry = lv1Entry;
+ entry->lv2Entry = lv2Entry;
+ return entry;
+ case 2:
+ // Small 4kb page
+ entry = useMe ? useMe : _allocateTlbEntry(0xFFFFF000, virtAddr);
+ entry->lv1Entry = lv1Entry;
+ entry->lv2Entry = lv2Entry;
+ return entry;
+ }
+ }
+
+ // we should never get here as the switch covers 0, 1, 2, 3
+ // but this satisfies a compiler warning
+ return SectionTranslationFault;
}
-
-
-ARM710::MMUFault ARM710::checkAccessPermissions(ARM710::TlbEntry *entry, uint32_t virtAddr, bool isWrite) const {
- int domain;
- int accessPerms;
- bool isPage;
-
- // extract info from the entries
- domain = (entry->lv1Entry >> 5) & 0xF;
- if (entry->lv2Entry) {
- // Page
- accessPerms = (entry->lv2Entry >> 4) & 0xFF;
-
- int permIndex;
- if ((entry->lv2Entry & 3) == 1) // Large 64kb
- permIndex = (virtAddr >> 14) & 3;
- else // Small 4kb
- permIndex = (virtAddr >> 10) & 3;
-
- accessPerms >>= (permIndex * 2);
- accessPerms &= 3;
- isPage = true;
- } else {
- // Section
- accessPerms = (entry->lv1Entry >> 10) & 3;
- isPage = false;
- }
-
- // now, do our checks
- int primaryAccessControls = (cp15_domainAccessControl >> (domain * 2)) & 3;
-
- // Manager: always allowed
- if (primaryAccessControls == 3)
- return NoFault;
-
- // Client: enforce checks!
- if (primaryAccessControls == 1) {
-#define OK_IF_TRUE(b) return ((b) ? NoFault : encodeFaultSorP(SorPPermissionFault, isPage, domain, virtAddr))
- bool System = cp15_control & 0x100;
- bool ROM = cp15_control & 0x200;
-
- if (accessPerms == 0) {
- if (!System && !ROM) {
- // 00/0/0: Any access generates a permission fault
- OK_IF_TRUE(false);
- } else if (System && !ROM) {
- // 00/1/0: Supervisor read only permitted
- OK_IF_TRUE(!isWrite && isPrivileged());
- } else if (!System && ROM) {
- // 00/0/1: Any write generates a permission fault
- OK_IF_TRUE(!isWrite);
- } else /*if (System && ROM)*/ {
- // Reserved
- OK_IF_TRUE(false);
- }
- } else if (accessPerms == 1) {
- // 01/x/x: Access allowed only in Supervisor mode
- OK_IF_TRUE(isPrivileged());
- } else if (accessPerms == 2) {
- // 10/x/x: Writes in User mode cause permission fault
- OK_IF_TRUE(!isWrite || isPrivileged());
- } else /*if (accessPerms == 3)*/ {
- // 11/x/x: All access types permitted in both modes
- OK_IF_TRUE(true);
- }
+ARM710::MMUFault ARM710::checkAccessPermissions(ARM710::TlbEntry* entry,
+ uint32_t virtAddr,
+ bool isWrite) const {
+ int domain;
+ int accessPerms;
+ bool isPage;
+
+ // extract info from the entries
+ domain = (entry->lv1Entry >> 5) & 0xF;
+ if (entry->lv2Entry) {
+ // Page
+ accessPerms = (entry->lv2Entry >> 4) & 0xFF;
+
+ int permIndex;
+ if ((entry->lv2Entry & 3) == 1) // Large 64kb
+ permIndex = (virtAddr >> 14) & 3;
+ else // Small 4kb
+ permIndex = (virtAddr >> 10) & 3;
+
+ accessPerms >>= (permIndex * 2);
+ accessPerms &= 3;
+ isPage = true;
+ } else {
+ // Section
+ accessPerms = (entry->lv1Entry >> 10) & 3;
+ isPage = false;
+ }
+
+ // now, do our checks
+ int primaryAccessControls = (cp15_domainAccessControl >> (domain * 2)) & 3;
+
+ // Manager: always allowed
+ if (primaryAccessControls == 3)
+ return NoFault;
+
+ // Client: enforce checks!
+ if (primaryAccessControls == 1) {
+#define OK_IF_TRUE(b) \
+ return ( \
+ (b) ? NoFault \
+ : encodeFaultSorP(SorPPermissionFault, isPage, domain, virtAddr))
+ bool System = cp15_control & 0x100;
+ bool ROM = cp15_control & 0x200;
+
+ if (accessPerms == 0) {
+ if (!System && !ROM) {
+ // 00/0/0: Any access generates a permission fault
+ OK_IF_TRUE(false);
+ } else if (System && !ROM) {
+ // 00/1/0: Supervisor read only permitted
+ OK_IF_TRUE(!isWrite && isPrivileged());
+ } else if (!System && ROM) {
+ // 00/0/1: Any write generates a permission fault
+ OK_IF_TRUE(!isWrite);
+ } else /*if (System && ROM)*/ {
+ // Reserved
+ OK_IF_TRUE(false);
+ }
+ } else if (accessPerms == 1) {
+ // 01/x/x: Access allowed only in Supervisor mode
+ OK_IF_TRUE(isPrivileged());
+ } else if (accessPerms == 2) {
+ // 10/x/x: Writes in User mode cause permission fault
+ OK_IF_TRUE(!isWrite || isPrivileged());
+ } else /*if (accessPerms == 3)*/ {
+ // 11/x/x: All access types permitted in both modes
+ OK_IF_TRUE(true);
+ }
#undef OK_IF_TRUE
- }
+ }
- // No Access or Reserved: never allowed (Domain Fault)
- return encodeFaultSorP(SorPDomainFault, isPage, domain, virtAddr);
+ // No Access or Reserved: never allowed (Domain Fault)
+ return encodeFaultSorP(SorPDomainFault, isPage, domain, virtAddr);
}
-
void ARM710::reportFault(MMUFault fault) {
- if (fault != NoFault) {
- if ((fault & 0xF) != NonMMUError) {
- cp15_faultStatus = fault & (MMUFaultTypeMask | MMUFaultDomainMask);
- cp15_faultAddress = fault >> MMUFaultAddressShift;
- }
-
- static const char *faultTypes[] = {
- "NoFault",
- "AlignmentFault",
- "???",
- "NonMMUError",
- "SectionLinefetchError",
- "SectionTranslationFault",
- "PageLinefetchError",
- "PageTranslationFault",
- "SectionOtherBusError",
- "SectionDomainFault",
- "PageOtherBusError",
- "PageDomainFault",
- "Lv1TranslationError",
- "SectionPermissionFault",
- "Lv2TranslationError",
- "PagePermissionFault"
- };
- log("⚠️ Fault type=%s domain=%d address=%08x pc=%08x lr=%08x",
- faultTypes[fault & MMUFaultTypeMask],
- (fault & MMUFaultDomainMask) >> MMUFaultDomainShift,
- fault >> MMUFaultAddressShift,
- GPRs[15], GPRs[14]);
-
- // this signals a branch to DataAbort after the
- // instruction is done executing
- faultTriggeredThisCycle = true;
- }
+ if (fault != NoFault) {
+ if ((fault & 0xF) != NonMMUError) {
+ cp15_faultStatus = fault & (MMUFaultTypeMask | MMUFaultDomainMask);
+ cp15_faultAddress = fault >> MMUFaultAddressShift;
+ }
+
+ static const char* faultTypes[] = {"NoFault",
+ "AlignmentFault",
+ "???",
+ "NonMMUError",
+ "SectionLinefetchError",
+ "SectionTranslationFault",
+ "PageLinefetchError",
+ "PageTranslationFault",
+ "SectionOtherBusError",
+ "SectionDomainFault",
+ "PageOtherBusError",
+ "PageDomainFault",
+ "Lv1TranslationError",
+ "SectionPermissionFault",
+ "Lv2TranslationError",
+ "PagePermissionFault"};
+ log("⚠️ Fault type=%s domain=%d address=%08x pc=%08x lr=%08x",
+ faultTypes[fault & MMUFaultTypeMask],
+ (fault & MMUFaultDomainMask) >> MMUFaultDomainShift,
+ fault >> MMUFaultAddressShift, GPRs[15], GPRs[14]);
+
+ // this signals a branch to DataAbort after the
+ // instruction is done executing
+ faultTriggeredThisCycle = true;
+ }
}
+void ARM710::log(const char* format, ...) {
+ if (logger) {
+ char buffer[1024];
-void ARM710::log(const char *format, ...) {
- if (logger) {
- char buffer[1024];
-
- va_list vaList;
- va_start(vaList, format);
- vsnprintf(buffer, sizeof(buffer), format, vaList);
- va_end(vaList);
+ va_list vaList;
+ va_start(vaList, format);
+ vsnprintf(buffer, sizeof(buffer), format, vaList);
+ va_end(vaList);
- logger(buffer);
- }
+ logger(buffer);
+ }
}
void ARM710::logPcHistory() {
- for (int i = 0; i < PcHistoryCount; i++) {
- pcHistoryIndex = (pcHistoryIndex + 1) % PcHistoryCount;
- log("%03d: %08x %08x", i, pcHistory[pcHistoryIndex].addr, pcHistory[pcHistoryIndex].insn);
- }
+ for (int i = 0; i < PcHistoryCount; i++) {
+ pcHistoryIndex = (pcHistoryIndex + 1) % PcHistoryCount;
+ log("%03d: %08x %08x", i, pcHistory[pcHistoryIndex].addr,
+ pcHistory[pcHistoryIndex].insn);
+ }
}
#pragma once
#include <functional>
-#include <stdint.h>
#include <optional>
+#include <stdint.h>
#include <variant>
using namespace std;
// TLB is 64 entries
// Speedhacks:
-//#define ARM710T_CACHE
-//#define ARM710T_TLB
+// #define ARM710T_CACHE
+// #define ARM710T_TLB
typedef optional<uint32_t> MaybeU32;
-class ARM710
-{
+class ARM710 {
public:
- enum ValueSize { V8 = 0, V16 = 1, V32 = 2 };
-
- enum MMUFault : uint64_t {
- // ref: datasheet 9-13 (p111)
- NoFault = 0,
- AlignmentFault = 1,
- // the ARM gods say there is to be no fault 2 or 3
- SectionLinefetchError = 4,
- SectionTranslationFault = 5,
- PageLinefetchError = 6,
- PageTranslationFault = 7,
- SectionOtherBusError = 8,
- SectionDomainFault = 9,
- PageOtherBusError = 0xA,
- PageDomainFault = 0xB,
- Lv1TranslationError = 0xC,
- SectionPermissionFault = 0xD,
- Lv2TranslationError = 0xE,
- PagePermissionFault = 0xF,
-
- // not actually in the ARM datasheet
- // so we are reusing it for nefarious purposes
- NonMMUError = 3,
-
- MMUFaultTypeMask = 0xF,
- MMUFaultDomainMask = 0xF0,
- MMUFaultDomainShift = 4,
- MMUFaultAddressMask = 0xFFFFFFFF00000000,
- MMUFaultAddressShift = 32
- };
-
-
-
- ARM710(bool _isTVersion) {
- isTVersion = _isTVersion;
- cp15_id = _isTVersion ? 0x41807100 : 0x41047100;
- clearAllValues();
- }
- virtual ~ARM710() { }
-
- void clearAllValues() {
- bank = MainBank;
- CPSR = 0;
- for (int i = 0; i < 16; i++) GPRs[i] = 0;
- for (int i = 0; i < 5; i++) {
- fiqBankedRegisters[0][i] = 0;
- fiqBankedRegisters[1][i] = 0;
- SPSRs[i] = 0;
- }
- for (int i = 0; i < 6; i++) {
- allModesBankedRegisters[i][0] = 0;
- allModesBankedRegisters[i][1] = 0;
- }
-
- cp15_control = 0;
- cp15_translationTableBase = 0;
- cp15_domainAccessControl = 0;
- cp15_faultStatus = 0;
- cp15_faultAddress = 0;
- prefetchCount = 0;
+ enum ValueSize { V8 = 0, V16 = 1, V32 = 2 };
+
+ enum MMUFault : uint64_t {
+ // ref: datasheet 9-13 (p111)
+ NoFault = 0,
+ AlignmentFault = 1,
+ // the ARM gods say there is to be no fault 2 or 3
+ SectionLinefetchError = 4,
+ SectionTranslationFault = 5,
+ PageLinefetchError = 6,
+ PageTranslationFault = 7,
+ SectionOtherBusError = 8,
+ SectionDomainFault = 9,
+ PageOtherBusError = 0xA,
+ PageDomainFault = 0xB,
+ Lv1TranslationError = 0xC,
+ SectionPermissionFault = 0xD,
+ Lv2TranslationError = 0xE,
+ PagePermissionFault = 0xF,
+
+ // not actually in the ARM datasheet
+ // so we are reusing it for nefarious purposes
+ NonMMUError = 3,
+
+ MMUFaultTypeMask = 0xF,
+ MMUFaultDomainMask = 0xF0,
+ MMUFaultDomainShift = 4,
+ MMUFaultAddressMask = 0xFFFFFFFF00000000,
+ MMUFaultAddressShift = 32
+ };
+
+ ARM710(bool _isTVersion) {
+ isTVersion = _isTVersion;
+ cp15_id = _isTVersion ? 0x41807100 : 0x41047100;
+ clearAllValues();
+ }
+ virtual ~ARM710() {}
+
+ void clearAllValues() {
+ bank = MainBank;
+ CPSR = 0;
+ for (int i = 0; i < 16; i++)
+ GPRs[i] = 0;
+ for (int i = 0; i < 5; i++) {
+ fiqBankedRegisters[0][i] = 0;
+ fiqBankedRegisters[1][i] = 0;
+ SPSRs[i] = 0;
+ }
+ for (int i = 0; i < 6; i++) {
+ allModesBankedRegisters[i][0] = 0;
+ allModesBankedRegisters[i][1] = 0;
+ }
+
+ cp15_control = 0;
+ cp15_translationTableBase = 0;
+ cp15_domainAccessControl = 0;
+ cp15_faultStatus = 0;
+ cp15_faultAddress = 0;
+ prefetchCount = 0;
#ifdef ARM710T_CACHE
- clearCache();
+ clearCache();
#endif
#ifdef ARM710T_TLB
- flushTlb();
+ flushTlb();
#endif
- }
-
- void setProcessorID(uint32_t v) { cp15_id = v; }
- bool canAcceptFIQ() const { return !(CPSR & CPSR_FIQDisable); }
- bool canAcceptIRQ() const { return !(CPSR & CPSR_IRQDisable); }
- void requestFIQ(); // pull nFIQ low
- void requestIRQ(); // pull nIRQ low
- void reset(); // pull nRESET low
-
- bool instructionReady() const { return (prefetchCount == 2); }
- uint32_t tick(); // run the chip for at least 1 clock cycle
-
- MaybeU32 readVirtualDebug(uint32_t virtAddr, ValueSize valueSize);
- MaybeU32 virtToPhys(uint32_t virtAddr);
-
- pair<MaybeU32, MMUFault> readVirtual(uint32_t virtAddr, ValueSize valueSize);
- virtual MaybeU32 readPhysical(uint32_t physAddr, ValueSize valueSize) = 0;
- MMUFault writeVirtual(uint32_t value, uint32_t virtAddr, ARM710::ValueSize valueSize);
- virtual bool writePhysical(uint32_t value, uint32_t physAddr, ARM710::ValueSize valueSize) = 0;
-
- uint32_t getGPR(int index) const { return GPRs[index]; }
- uint32_t getCPSR() const { return CPSR; }
- uint32_t getRealPC() const {
- return GPRs[15] - (4 * prefetchCount);
- }
-
- void setLogger(std::function<void(const char *)> newLogger) { logger = newLogger; }
- uint32_t lastPcExecuted() const { return pcHistory[(pcHistoryIndex - 1) % PcHistoryCount].addr; }
+ }
+
+ void setProcessorID(uint32_t v) { cp15_id = v; }
+ bool canAcceptFIQ() const { return !(CPSR & CPSR_FIQDisable); }
+ bool canAcceptIRQ() const { return !(CPSR & CPSR_IRQDisable); }
+ void requestFIQ(); // pull nFIQ low
+ void requestIRQ(); // pull nIRQ low
+ void reset(); // pull nRESET low
+
+ bool instructionReady() const { return (prefetchCount == 2); }
+ uint32_t tick(); // run the chip for at least 1 clock cycle
+
+ MaybeU32 readVirtualDebug(uint32_t virtAddr, ValueSize valueSize);
+ MaybeU32 virtToPhys(uint32_t virtAddr);
+
+ pair<MaybeU32, MMUFault> readVirtual(uint32_t virtAddr, ValueSize valueSize);
+ virtual MaybeU32 readPhysical(uint32_t physAddr, ValueSize valueSize) = 0;
+ MMUFault writeVirtual(uint32_t value, uint32_t virtAddr,
+ ARM710::ValueSize valueSize);
+ virtual bool writePhysical(uint32_t value, uint32_t physAddr,
+ ARM710::ValueSize valueSize) = 0;
+
+ uint32_t getGPR(int index) const { return GPRs[index]; }
+ uint32_t getCPSR() const { return CPSR; }
+ uint32_t getRealPC() const { return GPRs[15] - (4 * prefetchCount); }
+
+ void setLogger(std::function<void(const char*)> newLogger) {
+ logger = newLogger;
+ }
+ uint32_t lastPcExecuted() const {
+ return pcHistory[(pcHistoryIndex - 1) % PcHistoryCount].addr;
+ }
+
public:
- void log(const char *format, ...);
- void logPcHistory();
+ void log(const char* format, ...);
+ void logPcHistory();
+
private:
- std::function<void(const char *)> logger;
-
- enum { PcHistoryCount = 10 };
- struct { uint32_t addr, insn; } pcHistory[PcHistoryCount];
- uint32_t pcHistoryIndex = 0;
-
- enum { Nop = 0xE1A00000 };
-
- enum Mode : uint8_t {
- User32 = 0x10,
- FIQ32 = 0x11,
- IRQ32 = 0x12,
- Supervisor32 = 0x13,
- Abort32 = 0x17,
- Undefined32 = 0x1B
- };
-
- enum BankIndex : uint8_t {
- FiqBank,
- IrqBank,
- SvcBank,
- AbtBank,
- UndBank,
- MainBank
- };
-
- constexpr static const BankIndex modeToBank[16] = {
- MainBank, FiqBank, IrqBank, SvcBank,
- MainBank, MainBank, MainBank, AbtBank,
- MainBank, MainBank, MainBank, UndBank,
- MainBank, MainBank, MainBank, MainBank
- };
-
- enum : uint32_t {
- CPSR_ModeMask = 0x0000001F,
- CPSR_FIQDisable = 0x00000040,
- CPSR_IRQDisable = 0x00000080,
- CPSR_V = 0x10000000,
- CPSR_C = 0x20000000,
- CPSR_Z = 0x40000000,
- CPSR_N = 0x80000000,
- CPSR_FlagMask = 0xF0000000
- };
-
- // active state
- BankIndex bank;
- uint32_t CPSR;
- uint32_t GPRs[16];
-
- // saved state
- uint32_t fiqBankedRegisters[2][5]; // R8..R12 inclusive
- uint32_t allModesBankedRegisters[6][2]; // R13, R14
- uint32_t SPSRs[5];
-
- // coprocessor 15
- uint32_t cp15_id; // 0: read-only
- uint32_t cp15_control; // 1: write-only
- uint32_t cp15_translationTableBase; // 2: write-only
- uint32_t cp15_domainAccessControl; // 3: write-only
- uint8_t cp15_faultStatus; // 5: read-only (writing has unrelated effects)
- uint32_t cp15_faultAddress; // 6: read-only (writing has unrelated effects)
-
- bool isTVersion;
-
- bool flagV() const { return CPSR & CPSR_V; }
- bool flagC() const { return CPSR & CPSR_C; }
- bool flagZ() const { return CPSR & CPSR_Z; }
- bool flagN() const { return CPSR & CPSR_N; }
- bool checkCondition(int cond) const {
- switch (cond) {
- /*EQ*/ case 0: return flagZ();
- /*NE*/ case 1: return !flagZ();
- /*CS*/ case 2: return flagC();
- /*CC*/ case 3: return !flagC();
- /*MI*/ case 4: return flagN();
- /*PL*/ case 5: return !flagN();
- /*VS*/ case 6: return flagV();
- /*VC*/ case 7: return !flagV();
- /*HI*/ case 8: return flagC() && !flagZ();
- /*LS*/ case 9: return !flagC() || flagZ();
- /*GE*/ case 0xA: return flagN() == flagV();
- /*LT*/ case 0xB: return flagN() != flagV();
- /*GT*/ case 0xC: return !flagZ() && (flagN() == flagV());
- /*LE*/ case 0xD: return flagZ() || (flagN() != flagV());
- /*AL*/ case 0xE: return true;
- /*NV*/ /*case 0xF:*/
- default: return false;
- }
- }
-
- static Mode modeFromCPSR(uint32_t v) { return (Mode)(v & CPSR_ModeMask); }
- Mode currentMode() const { return modeFromCPSR(CPSR); }
- BankIndex currentBank() const { return modeToBank[(Mode)(CPSR & 0xF)]; }
- bool isPrivileged() const { return (CPSR & 0x1F) > User32; }
- bool isMMUEnabled() const { return (cp15_control & 1); }
- bool isAlignmentFaultEnabled() const { return (cp15_control & 2); }
- bool isCacheEnabled() const { return (cp15_control & 4); }
- bool isWriteBufferEnabled() const { return (cp15_control & 8); }
-
- void switchMode(Mode mode);
- void switchBank(BankIndex bank);
- void raiseException(Mode mode, uint32_t savedPC, uint32_t newPC);
-
- // MMU/TLB
- enum MMUFaultSorP : uint64_t {
- SorPLinefetchError = 4,
- SorPTranslationFault = 5,
- SorPOtherBusError = 8,
- SorPDomainFault = 9,
- SorPPermissionFault = 0xD,
- };
-
- MMUFault encodeFault(MMUFault fault, int domain, uint32_t virtAddr) const {
- return (MMUFault)(fault | (domain << 4) | ((uint64_t)virtAddr << 32));
- }
- MMUFault encodeFaultSorP(MMUFaultSorP baseFault, bool isPage, int domain, uint32_t virtAddr) const {
- return (MMUFault)(baseFault | (isPage ? 2 : 0) | (domain << 4) | ((uint64_t)virtAddr << 32));
- }
-
- struct TlbEntry { uint32_t addrMask, addr, lv1Entry, lv2Entry; };
+ std::function<void(const char*)> logger;
+
+ enum { PcHistoryCount = 10 };
+ struct {
+ uint32_t addr, insn;
+ } pcHistory[PcHistoryCount];
+ uint32_t pcHistoryIndex = 0;
+
+ enum { Nop = 0xE1A00000 };
+
+ enum Mode : uint8_t {
+ User32 = 0x10,
+ FIQ32 = 0x11,
+ IRQ32 = 0x12,
+ Supervisor32 = 0x13,
+ Abort32 = 0x17,
+ Undefined32 = 0x1B
+ };
+
+ enum BankIndex : uint8_t {
+ FiqBank,
+ IrqBank,
+ SvcBank,
+ AbtBank,
+ UndBank,
+ MainBank
+ };
+
+ constexpr static const BankIndex modeToBank[16] = {
+ MainBank, FiqBank, IrqBank, SvcBank, MainBank, MainBank,
+ MainBank, AbtBank, MainBank, MainBank, MainBank, UndBank,
+ MainBank, MainBank, MainBank, MainBank};
+
+ enum : uint32_t {
+ CPSR_ModeMask = 0x0000001F,
+ CPSR_FIQDisable = 0x00000040,
+ CPSR_IRQDisable = 0x00000080,
+ CPSR_V = 0x10000000,
+ CPSR_C = 0x20000000,
+ CPSR_Z = 0x40000000,
+ CPSR_N = 0x80000000,
+ CPSR_FlagMask = 0xF0000000
+ };
+
+ // active state
+ BankIndex bank;
+ uint32_t CPSR;
+ uint32_t GPRs[16];
+
+ // saved state
+ uint32_t fiqBankedRegisters[2][5]; // R8..R12 inclusive
+ uint32_t allModesBankedRegisters[6][2]; // R13, R14
+ uint32_t SPSRs[5];
+
+ // coprocessor 15
+ uint32_t cp15_id; // 0: read-only
+ uint32_t cp15_control; // 1: write-only
+ uint32_t cp15_translationTableBase; // 2: write-only
+ uint32_t cp15_domainAccessControl; // 3: write-only
+ uint8_t cp15_faultStatus; // 5: read-only (writing has unrelated effects)
+ uint32_t cp15_faultAddress; // 6: read-only (writing has unrelated effects)
+
+ bool isTVersion;
+
+ bool flagV() const { return CPSR & CPSR_V; }
+ bool flagC() const { return CPSR & CPSR_C; }
+ bool flagZ() const { return CPSR & CPSR_Z; }
+ bool flagN() const { return CPSR & CPSR_N; }
+ bool checkCondition(int cond) const {
+ switch (cond) {
+ /*EQ*/ case 0:
+ return flagZ();
+ /*NE*/ case 1:
+ return !flagZ();
+ /*CS*/ case 2:
+ return flagC();
+ /*CC*/ case 3:
+ return !flagC();
+ /*MI*/ case 4:
+ return flagN();
+ /*PL*/ case 5:
+ return !flagN();
+ /*VS*/ case 6:
+ return flagV();
+ /*VC*/ case 7:
+ return !flagV();
+ /*HI*/ case 8:
+ return flagC() && !flagZ();
+ /*LS*/ case 9:
+ return !flagC() || flagZ();
+ /*GE*/ case 0xA:
+ return flagN() == flagV();
+ /*LT*/ case 0xB:
+ return flagN() != flagV();
+ /*GT*/ case 0xC:
+ return !flagZ() && (flagN() == flagV());
+ /*LE*/ case 0xD:
+ return flagZ() || (flagN() != flagV());
+ /*AL*/ case 0xE:
+ return true;
+ /*NV*/ /*case 0xF:*/
+ default:
+ return false;
+ }
+ }
+
+ static Mode modeFromCPSR(uint32_t v) { return (Mode)(v & CPSR_ModeMask); }
+ Mode currentMode() const { return modeFromCPSR(CPSR); }
+ BankIndex currentBank() const { return modeToBank[(Mode)(CPSR & 0xF)]; }
+ bool isPrivileged() const { return (CPSR & 0x1F) > User32; }
+ bool isMMUEnabled() const { return (cp15_control & 1); }
+ bool isAlignmentFaultEnabled() const { return (cp15_control & 2); }
+ bool isCacheEnabled() const { return (cp15_control & 4); }
+ bool isWriteBufferEnabled() const { return (cp15_control & 8); }
+
+ void switchMode(Mode mode);
+ void switchBank(BankIndex bank);
+ void raiseException(Mode mode, uint32_t savedPC, uint32_t newPC);
+
+ // MMU/TLB
+ enum MMUFaultSorP : uint64_t {
+ SorPLinefetchError = 4,
+ SorPTranslationFault = 5,
+ SorPOtherBusError = 8,
+ SorPDomainFault = 9,
+ SorPPermissionFault = 0xD,
+ };
+
+ MMUFault encodeFault(MMUFault fault, int domain, uint32_t virtAddr) const {
+ return (MMUFault)(fault | (domain << 4) | ((uint64_t)virtAddr << 32));
+ }
+ MMUFault encodeFaultSorP(MMUFaultSorP baseFault, bool isPage, int domain,
+ uint32_t virtAddr) const {
+ return (MMUFault)(baseFault | (isPage ? 2 : 0) | (domain << 4) |
+ ((uint64_t)virtAddr << 32));
+ }
+
+ struct TlbEntry {
+ uint32_t addrMask, addr, lv1Entry, lv2Entry;
+ };
#ifdef ARM710T_TLB
- enum { TlbSize = 64 };
- TlbEntry tlb[TlbSize];
- int nextTlbIndex = 0;
+ enum { TlbSize = 64 };
+ TlbEntry tlb[TlbSize];
+ int nextTlbIndex = 0;
- void flushTlb();
- void flushTlb(uint32_t virtAddr);
+ void flushTlb();
+ void flushTlb(uint32_t virtAddr);
#else
- TlbEntry singleTlbEntry;
-#endif
+ TlbEntry singleTlbEntry;
+#endif
- TlbEntry *_allocateTlbEntry(uint32_t addrMask, uint32_t addr);
- variant<TlbEntry *, MMUFault> translateAddressUsingTlb(uint32_t virtAddr, TlbEntry *useMe=nullptr);
- static uint32_t physAddrFromTlbEntry(TlbEntry *tlbEntry, uint32_t virtAddr);
- MMUFault checkAccessPermissions(TlbEntry *entry, uint32_t virtAddr, bool isWrite) const;
+ TlbEntry* _allocateTlbEntry(uint32_t addrMask, uint32_t addr);
+ variant<TlbEntry*, MMUFault>
+ translateAddressUsingTlb(uint32_t virtAddr, TlbEntry* useMe = nullptr);
+ static uint32_t physAddrFromTlbEntry(TlbEntry* tlbEntry, uint32_t virtAddr);
+ MMUFault checkAccessPermissions(TlbEntry* entry, uint32_t virtAddr,
+ bool isWrite) const;
- bool faultTriggeredThisCycle = false;
- void reportFault(MMUFault fault);
+ bool faultTriggeredThisCycle = false;
+ void reportFault(MMUFault fault);
- // Instruction/Data Cache
+ // Instruction/Data Cache
#ifdef ARM710T_CACHE
- enum {
- CacheSets = 4,
- CacheBlocksPerSet = 128,
- CacheBlockSize = 0x10,
-
- CacheAddressLineMask = 0x0000000F,
- CacheAddressSetMask = 0x00000030, CacheAddressSetShift = 4,
- CacheAddressTagMask = 0xFFFFFFC0,
-
- CacheBlockEnabled = 1
- };
- uint32_t cacheBlockTags[CacheSets][CacheBlocksPerSet];
- uint8_t cacheBlocks[CacheSets][CacheBlocksPerSet][CacheBlockSize];
-
- void clearCache();
- uint8_t *findCacheLine(uint32_t virtAddr);
- pair<MaybeU32, MMUFault> addCacheLineAndRead(uint32_t physAddr, uint32_t virtAddr, ValueSize valueSize, int domain, bool isPage);
- MaybeU32 readCached(uint32_t virtAddr, ValueSize valueSize);
- bool writeCached(uint32_t value, uint32_t virtAddr, ValueSize valueSize);
+ enum {
+ CacheSets = 4,
+ CacheBlocksPerSet = 128,
+ CacheBlockSize = 0x10,
+
+ CacheAddressLineMask = 0x0000000F,
+ CacheAddressSetMask = 0x00000030,
+ CacheAddressSetShift = 4,
+ CacheAddressTagMask = 0xFFFFFFC0,
+
+ CacheBlockEnabled = 1
+ };
+ uint32_t cacheBlockTags[CacheSets][CacheBlocksPerSet];
+ uint8_t cacheBlocks[CacheSets][CacheBlocksPerSet][CacheBlockSize];
+
+ void clearCache();
+ uint8_t* findCacheLine(uint32_t virtAddr);
+ pair<MaybeU32, MMUFault> addCacheLineAndRead(uint32_t physAddr,
+ uint32_t virtAddr,
+ ValueSize valueSize, int domain,
+ bool isPage);
+ MaybeU32 readCached(uint32_t virtAddr, ValueSize valueSize);
+ bool writeCached(uint32_t value, uint32_t virtAddr, ValueSize valueSize);
#endif
- // Instruction Loop
- int prefetchCount;
- uint32_t prefetch[2];
- MMUFault prefetchFaults[2];
-
- uint32_t executeInstruction(uint32_t insn);
-
- uint32_t execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t Rn, uint32_t Rd, uint32_t Operand2);
- uint32_t execMultiply(uint32_t AS, uint32_t Rd, uint32_t Rn, uint32_t Rs, uint32_t Rm);
- uint32_t execMultiplyLong(uint32_t UAS, uint32_t RdHi, uint32_t RdLo, uint32_t Rs, uint32_t Rm);
- uint32_t execSingleDataSwap(bool B, uint32_t Rn, uint32_t Rd, uint32_t Rm);
- uint32_t execSingleDataTransfer(uint32_t IPUBWL, uint32_t Rn, uint32_t Rd, uint32_t offset);
- uint32_t execSingleHalfWordDataTransfer(uint32_t PUIWL, uint32_t Rn, uint32_t Rd, uint32_t addrMode1, uint32_t SH, uint32_t addrMode2);
- uint32_t execBlockDataTransfer(uint32_t PUSWL, uint32_t Rn, uint32_t registerList);
- uint32_t execBranch(bool L, uint32_t offset);
- uint32_t execCP15RegisterTransfer(uint32_t CPOpc, bool L, uint32_t CRn, uint32_t Rd, uint32_t CP, uint32_t CRm);
+ // Instruction Loop
+ int prefetchCount;
+ uint32_t prefetch[2];
+ MMUFault prefetchFaults[2];
+
+ uint32_t executeInstruction(uint32_t insn);
+
+ uint32_t execDataProcessing(bool I, uint32_t Opcode, bool S, uint32_t Rn,
+ uint32_t Rd, uint32_t Operand2);
+ uint32_t execMultiply(uint32_t AS, uint32_t Rd, uint32_t Rn, uint32_t Rs,
+ uint32_t Rm);
+ uint32_t execMultiplyLong(uint32_t UAS, uint32_t RdHi, uint32_t RdLo,
+ uint32_t Rs, uint32_t Rm);
+ uint32_t execSingleDataSwap(bool B, uint32_t Rn, uint32_t Rd, uint32_t Rm);
+ uint32_t execSingleDataTransfer(uint32_t IPUBWL, uint32_t Rn, uint32_t Rd,
+ uint32_t offset);
+ uint32_t execSingleHalfWordDataTransfer(uint32_t PUIWL, uint32_t Rn,
+ uint32_t Rd, uint32_t addrMode1,
+ uint32_t SH, uint32_t addrMode2);
+ uint32_t execBlockDataTransfer(uint32_t PUSWL, uint32_t Rn,
+ uint32_t registerList);
+ uint32_t execBranch(bool L, uint32_t offset);
+ uint32_t execCP15RegisterTransfer(uint32_t CPOpc, bool L, uint32_t CRn,
+ uint32_t Rd, uint32_t CP, uint32_t CRm);
};
#include "clps7111.h"
#include "clps7111_defs.h"
+#include "common.h"
#include "hardware.h"
#include <time.h>
-#include "common.h"
-
namespace CLPS7111 {
-Emulator::Emulator() : EmuBase(false), pcCardController(this) {
-}
-
-
-uint32_t Emulator::getRTC() {
- return time(nullptr) - 946684800;
-}
-
+Emulator::Emulator() : EmuBase(false), pcCardController(this) {}
+uint32_t Emulator::getRTC() { return time(nullptr) - 946684800; }
uint32_t Emulator::readReg8(uint32_t reg) {
- if (reg == PADR) {
- return ((portValues >> 24) & 0x80) | (readKeyboard() & 0x7F);
- } else if (reg == PBDR) {
- return ((portValues >> 16) & 0x0F) | ((keyboardExtra ^ 0xF) << 4);
- } else if (reg == PDDR) {
- return (portValues >> 8) & 0xFF;
- } else if (reg == PEDR) {
- return portValues & 0xFF;
- } else if (reg == PADDR) {
- return (portDirections >> 24) & 0xFF;
- } else if (reg == PBDDR) {
- return (portDirections >> 16) & 0xFF;
- } else if (reg == PDDDR) {
- return (portDirections >> 8) & 0xFF;
- } else if (reg == PEDDR) {
- return portDirections & 0xFF;
- } else {
- log("RegRead8 unknown:: pc=%08x lr=%08x reg=%03x", getRealPC(), getGPR(14), reg);
- return 0xFF;
- }
+ if (reg == PADR) {
+ return ((portValues >> 24) & 0x80) | (readKeyboard() & 0x7F);
+ } else if (reg == PBDR) {
+ return ((portValues >> 16) & 0x0F) | ((keyboardExtra ^ 0xF) << 4);
+ } else if (reg == PDDR) {
+ return (portValues >> 8) & 0xFF;
+ } else if (reg == PEDR) {
+ return portValues & 0xFF;
+ } else if (reg == PADDR) {
+ return (portDirections >> 24) & 0xFF;
+ } else if (reg == PBDDR) {
+ return (portDirections >> 16) & 0xFF;
+ } else if (reg == PDDDR) {
+ return (portDirections >> 8) & 0xFF;
+ } else if (reg == PEDDR) {
+ return portDirections & 0xFF;
+ } else {
+ log("RegRead8 unknown:: pc=%08x lr=%08x reg=%03x", getRealPC(), getGPR(14),
+ reg);
+ return 0xFF;
+ }
}
uint32_t Emulator::readReg32(uint32_t reg) {
- if (reg == SYSCON1) {
- uint32_t flg = 0;
- if (tc1.config & Timer::PERIODIC) flg |= 0x10;
- if (tc1.config & Timer::MODE_512KHZ) flg |= 0x20;
- if (tc2.config & Timer::PERIODIC) flg |= 0x40;
- if (tc2.config & Timer::MODE_512KHZ) flg |= 0x80;
- flg |= (kScan & 0xF);
- return flg;
- } else if (reg == SYSFLG1) {
- uint32_t flg = sysFlg1;
- flg |= 2; // external power present
- flg |= (rtcDiv << 16);
- // maybe set more stuff?
- return flg;
- } else if (reg == INTSR1) {
- return pendingInterrupts & 0xFFFF;
- } else if (reg == INTMR1) {
- return interruptMask & 0xFFFF;
- } else if (reg == LCDCON) {
- return lcdControl;
- } else if (reg == TC1D) {
- return tc1.value;
- } else if (reg == TC2D) {
- return tc2.value;
- } else if (reg == RTCDR) {
- return rtc;
- } else if (reg == SYNCIO) {
- switch (lastSyncioRequest & 0xFF) {
- case 0xC1: // DigitiserX
- return (touchX * 8) + 305;
- case 0x81: // DigitiserY
- return (touchY * 13.53) + 680;
- case 0x91: // MainBattery
- return 3000;
- case 0xD1: // BackupBattery
- return 3100;
- case 0xA1: // Reference
- return 1000;
- }
- log("SYNCIO read unknown:: req=%08x", lastSyncioRequest);
- return 0xFFFFFFFF;
- } else if (reg == PALLSW) {
- return lcdPalette & 0xFFFFFFFF;
- } else if (reg == PALMSW) {
- return lcdPalette >> 32;
- } else if (reg == SYSCON2) {
- return 0;
- } else if (reg == SYSFLG2) {
- return 0;
- } else if (reg == INTSR2) {
- return pendingInterrupts >> 16;
- } else if (reg == INTMR2) {
- return interruptMask >> 16;
- } else {
- log("RegRead32 unknown:: pc=%08x lr=%08x reg=%03x", getRealPC(), getGPR(14), reg);
- return 0xFFFFFFFF;
- }
+ if (reg == SYSCON1) {
+ uint32_t flg = 0;
+ if (tc1.config & Timer::PERIODIC)
+ flg |= 0x10;
+ if (tc1.config & Timer::MODE_512KHZ)
+ flg |= 0x20;
+ if (tc2.config & Timer::PERIODIC)
+ flg |= 0x40;
+ if (tc2.config & Timer::MODE_512KHZ)
+ flg |= 0x80;
+ flg |= (kScan & 0xF);
+ return flg;
+ } else if (reg == SYSFLG1) {
+ uint32_t flg = sysFlg1;
+ flg |= 2; // external power present
+ flg |= (rtcDiv << 16);
+ // maybe set more stuff?
+ return flg;
+ } else if (reg == INTSR1) {
+ return pendingInterrupts & 0xFFFF;
+ } else if (reg == INTMR1) {
+ return interruptMask & 0xFFFF;
+ } else if (reg == LCDCON) {
+ return lcdControl;
+ } else if (reg == TC1D) {
+ return tc1.value;
+ } else if (reg == TC2D) {
+ return tc2.value;
+ } else if (reg == RTCDR) {
+ return rtc;
+ } else if (reg == SYNCIO) {
+ switch (lastSyncioRequest & 0xFF) {
+ case 0xC1: // DigitiserX
+ return (touchX * 8) + 305;
+ case 0x81: // DigitiserY
+ return (touchY * 13.53) + 680;
+ case 0x91: // MainBattery
+ return 3000;
+ case 0xD1: // BackupBattery
+ return 3100;
+ case 0xA1: // Reference
+ return 1000;
+ }
+ log("SYNCIO read unknown:: req=%08x", lastSyncioRequest);
+ return 0xFFFFFFFF;
+ } else if (reg == PALLSW) {
+ return lcdPalette & 0xFFFFFFFF;
+ } else if (reg == PALMSW) {
+ return lcdPalette >> 32;
+ } else if (reg == SYSCON2) {
+ return 0;
+ } else if (reg == SYSFLG2) {
+ return 0;
+ } else if (reg == INTSR2) {
+ return pendingInterrupts >> 16;
+ } else if (reg == INTMR2) {
+ return interruptMask >> 16;
+ } else {
+ log("RegRead32 unknown:: pc=%08x lr=%08x reg=%03x", getRealPC(), getGPR(14),
+ reg);
+ return 0xFFFFFFFF;
+ }
}
void Emulator::writeReg8(uint32_t reg, uint8_t value) {
- if (reg == PADR) {
- uint32_t oldPorts = portValues;
- portValues &= 0x00FFFFFF;
- portValues |= (uint32_t)value << 24;
- diffPorts(oldPorts, portValues);
- } else if (reg == PBDR) {
- uint32_t oldPorts = portValues;
- portValues &= 0xFF00FFFF;
- portValues |= (uint32_t)value << 16;
-// if ((portValues & 0x10000) && !(oldPorts & 0x10000))
-// etna.setPromBit0High();
-// else if (!(portValues & 0x10000) && (oldPorts & 0x10000))
-// etna.setPromBit0Low();
-// if ((portValues & 0x20000) && !(oldPorts & 0x20000))
-// etna.setPromBit1High();
- diffPorts(oldPorts, portValues);
- } else if (reg == PDDR) {
- uint32_t oldPorts = portValues;
- portValues &= 0xFFFF00FF;
- portValues |= (uint32_t)value << 8;
- diffPorts(oldPorts, portValues);
- } else if (reg == PEDR) {
- uint32_t oldPorts = portValues;
- portValues &= 0xFFFFFF00;
- portValues |= (uint32_t)value;
- diffPorts(oldPorts, portValues);
- } else if (reg == PADDR) {
- portDirections &= 0x00FFFFFF;
- portDirections |= (uint32_t)value << 24;
- } else if (reg == PBDDR) {
- portDirections &= 0xFF00FFFF;
- portDirections |= (uint32_t)value << 16;
- } else if (reg == PDDDR) {
- portDirections &= 0xFFFF00FF;
- portDirections |= (uint32_t)value << 8;
- } else if (reg == PEDDR) {
- portDirections &= 0xFFFFFF00;
- portDirections |= (uint32_t)value;
- } else if (reg == FRBADDR) {
- log("LCD: address write %08x", value << 28);
- lcdAddress = value << 28;
- } else {
- log("RegWrite8 unknown:: pc=%08x reg=%03x value=%02x", getRealPC(), reg, value);
- }
+ if (reg == PADR) {
+ uint32_t oldPorts = portValues;
+ portValues &= 0x00FFFFFF;
+ portValues |= (uint32_t)value << 24;
+ diffPorts(oldPorts, portValues);
+ } else if (reg == PBDR) {
+ uint32_t oldPorts = portValues;
+ portValues &= 0xFF00FFFF;
+ portValues |= (uint32_t)value << 16;
+ // if ((portValues & 0x10000) && !(oldPorts & 0x10000))
+ // etna.setPromBit0High();
+ // else if (!(portValues & 0x10000) && (oldPorts & 0x10000))
+ // etna.setPromBit0Low();
+ // if ((portValues & 0x20000) && !(oldPorts & 0x20000))
+ // etna.setPromBit1High();
+ diffPorts(oldPorts, portValues);
+ } else if (reg == PDDR) {
+ uint32_t oldPorts = portValues;
+ portValues &= 0xFFFF00FF;
+ portValues |= (uint32_t)value << 8;
+ diffPorts(oldPorts, portValues);
+ } else if (reg == PEDR) {
+ uint32_t oldPorts = portValues;
+ portValues &= 0xFFFFFF00;
+ portValues |= (uint32_t)value;
+ diffPorts(oldPorts, portValues);
+ } else if (reg == PADDR) {
+ portDirections &= 0x00FFFFFF;
+ portDirections |= (uint32_t)value << 24;
+ } else if (reg == PBDDR) {
+ portDirections &= 0xFF00FFFF;
+ portDirections |= (uint32_t)value << 16;
+ } else if (reg == PDDDR) {
+ portDirections &= 0xFFFF00FF;
+ portDirections |= (uint32_t)value << 8;
+ } else if (reg == PEDDR) {
+ portDirections &= 0xFFFFFF00;
+ portDirections |= (uint32_t)value;
+ } else if (reg == FRBADDR) {
+ log("LCD: address write %08x", value << 28);
+ lcdAddress = value << 28;
+ } else {
+ log("RegWrite8 unknown:: pc=%08x reg=%03x value=%02x", getRealPC(), reg,
+ value);
+ }
}
void Emulator::writeReg32(uint32_t reg, uint32_t value) {
- if (reg == SYSCON1) {
- kScan = value & 0xF;
- uint8_t tc1cfg = Timer::ENABLED; // always on with PS-7111!
- if (value & 0x10) tc1cfg |= Timer::PERIODIC;
- if (value & 0x20) tc1cfg |= Timer::MODE_512KHZ;
- uint8_t tc2cfg = Timer::ENABLED;
- if (value & 0x40) tc2cfg |= Timer::PERIODIC;
- if (value & 0x80) tc2cfg |= Timer::MODE_512KHZ;
- tc1.setConfig(tc1cfg);
- tc2.setConfig(tc2cfg);
- } else if (reg == INTMR1) {
- interruptMask &= 0xFFFF0000;;
- interruptMask |= (value & 0xFFFF);
- } else if (reg == LCDCON) {
- log("LCD: ctl write %08x", value);
- lcdControl = value;
- } else if (reg == TC1D) {
- tc1.load(value);
- } else if (reg == TC2D) {
- tc2.load(value);
- } else if (reg == RTCDR) {
- rtc = value;
- } else if (reg == SYNCIO) {
- lastSyncioRequest = value & 0xFFFF;
- } else if (reg == PALLSW) {
- lcdPalette &= 0xFFFFFFFF00000000;
- lcdPalette |= value;
- } else if (reg == PALMSW) {
- lcdPalette &= 0x00000000FFFFFFFF;
- lcdPalette |= (uint64_t)value << 32;
- } else if (reg == HALT) {
- halted = true;
- // BLEOI = 0x410,
- // MCEOI = 0x414,
- } else if (reg == TEOI) {
- pendingInterrupts &= ~(1 << TINT);
- // TEOI = 0x418,
- // STFCLR = 0x41C,
- // E2EOI = 0x420,
- } else if (reg == TC1EOI) {
- pendingInterrupts &= ~(1 << TC1OI);
- } else if (reg == TC2EOI) {
- pendingInterrupts &= ~(1 << TC2OI);
- } else if (reg == SYSCON2) {
- log("SysCon2 write: %08x", value);
- } else if (reg == INTMR2) {
- interruptMask &= 0xFFFF;
- interruptMask |= (value << 16);
- } else if (reg == KBDEOI) {
- pendingInterrupts &= ~(1 << KBDINT);
- } else {
- log("RegWrite32 unknown:: pc=%08x reg=%03x value=%08x", getRealPC(), reg, value);
- }
+ if (reg == SYSCON1) {
+ kScan = value & 0xF;
+ uint8_t tc1cfg = Timer::ENABLED; // always on with PS-7111!
+ if (value & 0x10)
+ tc1cfg |= Timer::PERIODIC;
+ if (value & 0x20)
+ tc1cfg |= Timer::MODE_512KHZ;
+ uint8_t tc2cfg = Timer::ENABLED;
+ if (value & 0x40)
+ tc2cfg |= Timer::PERIODIC;
+ if (value & 0x80)
+ tc2cfg |= Timer::MODE_512KHZ;
+ tc1.setConfig(tc1cfg);
+ tc2.setConfig(tc2cfg);
+ } else if (reg == INTMR1) {
+ interruptMask &= 0xFFFF0000;
+ ;
+ interruptMask |= (value & 0xFFFF);
+ } else if (reg == LCDCON) {
+ log("LCD: ctl write %08x", value);
+ lcdControl = value;
+ } else if (reg == TC1D) {
+ tc1.load(value);
+ } else if (reg == TC2D) {
+ tc2.load(value);
+ } else if (reg == RTCDR) {
+ rtc = value;
+ } else if (reg == SYNCIO) {
+ lastSyncioRequest = value & 0xFFFF;
+ } else if (reg == PALLSW) {
+ lcdPalette &= 0xFFFFFFFF00000000;
+ lcdPalette |= value;
+ } else if (reg == PALMSW) {
+ lcdPalette &= 0x00000000FFFFFFFF;
+ lcdPalette |= (uint64_t)value << 32;
+ } else if (reg == HALT) {
+ halted = true;
+ // BLEOI = 0x410,
+ // MCEOI = 0x414,
+ } else if (reg == TEOI) {
+ pendingInterrupts &= ~(1 << TINT);
+ // TEOI = 0x418,
+ // STFCLR = 0x41C,
+ // E2EOI = 0x420,
+ } else if (reg == TC1EOI) {
+ pendingInterrupts &= ~(1 << TC1OI);
+ } else if (reg == TC2EOI) {
+ pendingInterrupts &= ~(1 << TC2OI);
+ } else if (reg == SYSCON2) {
+ log("SysCon2 write: %08x", value);
+ } else if (reg == INTMR2) {
+ interruptMask &= 0xFFFF;
+ interruptMask |= (value << 16);
+ } else if (reg == KBDEOI) {
+ pendingInterrupts &= ~(1 << KBDINT);
+ } else {
+ log("RegWrite32 unknown:: pc=%08x reg=%03x value=%08x", getRealPC(), reg,
+ value);
+ }
}
MaybeU32 Emulator::readPhysical(uint32_t physAddr, ValueSize valueSize) {
- uint8_t region = (physAddr >> 28);
- if (valueSize == V8) {
- if (region == 0)
- return ROM[physAddr & 0xFFFFFF];
- else if (region == 1)
- return ROM2[physAddr & 0x3FFFF];
- else if (region == 4)
- return pcCardController.read(physAddr & 0xFFFFFFF, V8);
- else if (region == 8 && physAddr <= 0x80001FFF)
- return readReg8(physAddr & 0x1FFF);
- else if (region == 0xC)
- return MemoryBlockC0[physAddr & MemoryBlockMask];
- else if (region > 0xC)
- return 0xFF; // just throw accesses to unmapped RAM away
- } else {
- uint32_t result;
- if (region == 0)
- LOAD_32LE(result, physAddr & 0xFFFFFF, ROM);
- else if (region == 1)
- LOAD_32LE(result, physAddr & 0x3FFFF, ROM2);
- else if (region == 4)
- result = pcCardController.read(physAddr & 0xFFFFFFF, V32);
- else if (region == 8 && physAddr <= 0x80001FFF)
- result = readReg32(physAddr & 0x1FFF);
- else if (region == 0xC)
- LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockC0);
- else if (region > 0xC)
- return 0xFFFFFFFF; // just throw accesses to unmapped RAM away
- else
- return {};
- return result;
- }
-
- return {};
+ uint8_t region = (physAddr >> 28);
+ if (valueSize == V8) {
+ if (region == 0)
+ return ROM[physAddr & 0xFFFFFF];
+ else if (region == 1)
+ return ROM2[physAddr & 0x3FFFF];
+ else if (region == 4)
+ return pcCardController.read(physAddr & 0xFFFFFFF, V8);
+ else if (region == 8 && physAddr <= 0x80001FFF)
+ return readReg8(physAddr & 0x1FFF);
+ else if (region == 0xC)
+ return MemoryBlockC0[physAddr & MemoryBlockMask];
+ else if (region > 0xC)
+ return 0xFF; // just throw accesses to unmapped RAM away
+ } else {
+ uint32_t result;
+ if (region == 0)
+ LOAD_32LE(result, physAddr & 0xFFFFFF, ROM);
+ else if (region == 1)
+ LOAD_32LE(result, physAddr & 0x3FFFF, ROM2);
+ else if (region == 4)
+ result = pcCardController.read(physAddr & 0xFFFFFFF, V32);
+ else if (region == 8 && physAddr <= 0x80001FFF)
+ result = readReg32(physAddr & 0x1FFF);
+ else if (region == 0xC)
+ LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockC0);
+ else if (region > 0xC)
+ return 0xFFFFFFFF; // just throw accesses to unmapped RAM away
+ else
+ return {};
+ return result;
+ }
+
+ return {};
}
-bool Emulator::writePhysical(uint32_t value, uint32_t physAddr, ValueSize valueSize) {
- uint8_t region = (physAddr >> 28);
- if (valueSize == V8) {
- if (region == 0xC)
- MemoryBlockC0[physAddr & MemoryBlockMask] = (uint8_t)value;
- else if (region > 0xC)
- return true; // just throw accesses to unmapped RAM away
- else if (region == 4)
- pcCardController.write(value, physAddr & 0xFFFFFFF, V8);
- else if (region == 8 && physAddr <= 0x80001FFF)
- writeReg8(physAddr & 0x1FFF, value);
- else
- return false;
- } else {
- if (region == 0xC)
- STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockC0);
- else if (region > 0xC)
- return true; // just throw accesses to unmapped RAM away
- else if (region == 4)
- pcCardController.write(value, physAddr & 0xFFFFFFF, V32);
- else if (region == 8 && physAddr <= 0x80001FFF)
- writeReg32(physAddr & 0x1FFF, value);
- else
- return false;
- }
- return true;
+bool Emulator::writePhysical(uint32_t value, uint32_t physAddr,
+ ValueSize valueSize) {
+ uint8_t region = (physAddr >> 28);
+ if (valueSize == V8) {
+ if (region == 0xC)
+ MemoryBlockC0[physAddr & MemoryBlockMask] = (uint8_t)value;
+ else if (region > 0xC)
+ return true; // just throw accesses to unmapped RAM away
+ else if (region == 4)
+ pcCardController.write(value, physAddr & 0xFFFFFFF, V8);
+ else if (region == 8 && physAddr <= 0x80001FFF)
+ writeReg8(physAddr & 0x1FFF, value);
+ else
+ return false;
+ } else {
+ if (region == 0xC)
+ STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockC0);
+ else if (region > 0xC)
+ return true; // just throw accesses to unmapped RAM away
+ else if (region == 4)
+ pcCardController.write(value, physAddr & 0xFFFFFFF, V32);
+ else if (region == 8 && physAddr <= 0x80001FFF)
+ writeReg32(physAddr & 0x1FFF, value);
+ else
+ return false;
+ }
+ return true;
}
-
-
void Emulator::configure() {
- if (configured) return;
- configured = true;
+ if (configured)
+ return;
+ configured = true;
- srand(1000);
+ srand(1000);
- memset(&tc1, 0, sizeof(tc1));
- memset(&tc2, 0, sizeof(tc1));
- tc1.clockSpeed = CLOCK_SPEED;
- tc2.clockSpeed = CLOCK_SPEED;
+ memset(&tc1, 0, sizeof(tc1));
+ memset(&tc2, 0, sizeof(tc1));
+ tc1.clockSpeed = CLOCK_SPEED;
+ tc2.clockSpeed = CLOCK_SPEED;
- nextTickAt = TICK_INTERVAL;
- tc1.nextTickAt = tc1.tickInterval();
- tc2.nextTickAt = tc2.tickInterval();
- rtc = getRTC();
+ nextTickAt = TICK_INTERVAL;
+ tc1.nextTickAt = tc1.tickInterval();
+ tc2.nextTickAt = tc2.tickInterval();
+ rtc = getRTC();
- reset();
+ reset();
}
-uint8_t *Emulator::getROMBuffer() {
- return ROM;
-}
-size_t Emulator::getROMSize() {
- return sizeof(ROM);
-}
-void Emulator::loadROM(uint8_t *buffer, size_t size) {
- memcpy(ROM, buffer, min(size, sizeof(ROM)));
+uint8_t* Emulator::getROMBuffer() { return ROM; }
+size_t Emulator::getROMSize() { return sizeof(ROM); }
+void Emulator::loadROM(uint8_t* buffer, size_t size) {
+ memcpy(ROM, buffer, min(size, sizeof(ROM)));
}
void Emulator::executeUntil(int64_t cycles) {
- if (!configured)
- configure();
-
- while (!asleep && passedCycles < cycles) {
- if (passedCycles >= nextTickAt) {
- // increment RTCDIV
- if (rtcDiv == 0x3F) {
- rtc++;
- rtcDiv = 0;
- } else {
- rtcDiv++;
- }
-
- nextTickAt += TICK_INTERVAL;
- pendingInterrupts |= (1<<TINT);
- }
- if (tc1.tick(passedCycles))
- pendingInterrupts |= (1<<TC1OI);
- if (tc2.tick(passedCycles))
- pendingInterrupts |= (1<<TC2OI);
-
- if ((pendingInterrupts & interruptMask & FIQ_INTERRUPTS) != 0 && canAcceptFIQ()) {
- requestFIQ();
- halted = false;
- }
- if ((pendingInterrupts & interruptMask & IRQ_INTERRUPTS) != 0 && canAcceptIRQ()) {
- requestIRQ();
- halted = false;
- }
-
- // what's running?
- if (halted) {
- // keep the clock moving
- passedCycles++;
- } else {
- if (auto v = virtToPhys(getGPR(15) - 0xC); v.has_value() && instructionReady())
- debugPC(v.value());
- passedCycles += tick();
-
- uint32_t new_pc = getGPR(15) - 0xC;
- if (_breakpoints.find(new_pc) != _breakpoints.end()) {
- log("⚠️ Breakpoint triggered at %08x!", new_pc);
- return;
- }
- if (new_pc >= 0x80000000 && new_pc <= 0x90000000) {
- log("BAD PC %08x!!", new_pc);
- logPcHistory();
- return;
- }
- }
- }
+ if (!configured)
+ configure();
+
+ while (!asleep && passedCycles < cycles) {
+ if (passedCycles >= nextTickAt) {
+ // increment RTCDIV
+ if (rtcDiv == 0x3F) {
+ rtc++;
+ rtcDiv = 0;
+ } else {
+ rtcDiv++;
+ }
+
+ nextTickAt += TICK_INTERVAL;
+ pendingInterrupts |= (1 << TINT);
+ }
+ if (tc1.tick(passedCycles))
+ pendingInterrupts |= (1 << TC1OI);
+ if (tc2.tick(passedCycles))
+ pendingInterrupts |= (1 << TC2OI);
+
+ if ((pendingInterrupts & interruptMask & FIQ_INTERRUPTS) != 0 &&
+ canAcceptFIQ()) {
+ requestFIQ();
+ halted = false;
+ }
+ if ((pendingInterrupts & interruptMask & IRQ_INTERRUPTS) != 0 &&
+ canAcceptIRQ()) {
+ requestIRQ();
+ halted = false;
+ }
+
+ // what's running?
+ if (halted) {
+ // keep the clock moving
+ passedCycles++;
+ } else {
+ if (auto v = virtToPhys(getGPR(15) - 0xC);
+ v.has_value() && instructionReady())
+ debugPC(v.value());
+ passedCycles += tick();
+
+ uint32_t new_pc = getGPR(15) - 0xC;
+ if (_breakpoints.find(new_pc) != _breakpoints.end()) {
+ log("⚠️ Breakpoint triggered at %08x!", new_pc);
+ return;
+ }
+ if (new_pc >= 0x80000000 && new_pc <= 0x90000000) {
+ log("BAD PC %08x!!", new_pc);
+ logPcHistory();
+ return;
+ }
+ }
+ }
}
-
-const char *Emulator::identifyObjectCon(uint32_t ptr) {
- if (ptr == readVirtualDebug(0x80000880, V32).value()) return "process";
- if (ptr == readVirtualDebug(0x80000884, V32).value()) return "thread";
- if (ptr == readVirtualDebug(0x80000888, V32).value()) return "chunk";
-// if (ptr == readVirtualDebug(0x8000088C, V32).value()) return "semaphore";
-// if (ptr == readVirtualDebug(0x80000890, V32).value()) return "mutex";
- if (ptr == readVirtualDebug(0x80000894, V32).value()) return "logicaldevice";
- if (ptr == readVirtualDebug(0x80000898, V32).value()) return "physicaldevice";
- if (ptr == readVirtualDebug(0x8000089C, V32).value()) return "channel";
- if (ptr == readVirtualDebug(0x800008A0, V32).value()) return "server";
-// if (ptr == readVirtualDebug(0x800008A4, V32).value()) return "unk8A4"; // name always null
- if (ptr == readVirtualDebug(0x800008AC, V32).value()) return "library";
-// if (ptr == readVirtualDebug(0x800008B0, V32).value()) return "unk8B0"; // name always null
-// if (ptr == readVirtualDebug(0x800008B4, V32).value()) return "unk8B4"; // name always null
- return nullptr;
+const char* Emulator::identifyObjectCon(uint32_t ptr) {
+ if (ptr == readVirtualDebug(0x80000880, V32).value())
+ return "process";
+ if (ptr == readVirtualDebug(0x80000884, V32).value())
+ return "thread";
+ if (ptr == readVirtualDebug(0x80000888, V32).value())
+ return "chunk";
+ // if (ptr == readVirtualDebug(0x8000088C, V32).value()) return
+ //"semaphore"; if (ptr == readVirtualDebug(0x80000890, V32).value())
+ //return "mutex";
+ if (ptr == readVirtualDebug(0x80000894, V32).value())
+ return "logicaldevice";
+ if (ptr == readVirtualDebug(0x80000898, V32).value())
+ return "physicaldevice";
+ if (ptr == readVirtualDebug(0x8000089C, V32).value())
+ return "channel";
+ if (ptr == readVirtualDebug(0x800008A0, V32).value())
+ return "server";
+ // if (ptr == readVirtualDebug(0x800008A4, V32).value()) return "unk8A4";
+ //// name always null
+ if (ptr == readVirtualDebug(0x800008AC, V32).value())
+ return "library";
+ // if (ptr == readVirtualDebug(0x800008B0, V32).value()) return "unk8B0";
+ //// name always null if (ptr == readVirtualDebug(0x800008B4,
+ ///V32).value())
+ // return "unk8B4"; // name always null
+ return nullptr;
}
-void Emulator::fetchStr(uint32_t str, char *buf) {
- if (str == 0) {
- strcpy(buf, "<NULL>");
- return;
- }
- int size = readVirtualDebug(str, V32).value();
- for (int i = 0; i < size; i++) {
- buf[i] = readVirtualDebug(str + 4 + i, V8).value();
- }
- buf[size] = 0;
+void Emulator::fetchStr(uint32_t str, char* buf) {
+ if (str == 0) {
+ strcpy(buf, "<NULL>");
+ return;
+ }
+ int size = readVirtualDebug(str, V32).value();
+ for (int i = 0; i < size; i++) {
+ buf[i] = readVirtualDebug(str + 4 + i, V8).value();
+ }
+ buf[size] = 0;
}
-void Emulator::fetchName(uint32_t obj, char *buf) {
- fetchStr(readVirtualDebug(obj + 0x10, V32).value(), buf);
+void Emulator::fetchName(uint32_t obj, char* buf) {
+ fetchStr(readVirtualDebug(obj + 0x10, V32).value(), buf);
}
-void Emulator::fetchProcessFilename(uint32_t obj, char *buf) {
- fetchStr(readVirtualDebug(obj + 0x3C, V32).value(), buf);
+void Emulator::fetchProcessFilename(uint32_t obj, char* buf) {
+ fetchStr(readVirtualDebug(obj + 0x3C, V32).value(), buf);
}
void Emulator::debugPC(uint32_t pc) {
- char objName[1000];
- if (pc == 0x32304) {
- // CObjectCon::AddL()
- uint32_t container = getGPR(0);
- uint32_t obj = getGPR(1);
- const char *wut = identifyObjectCon(container);
- if (wut) {
- fetchName(obj, objName);
- if (strcmp(wut, "process") == 0) {
- char procName[1000];
- fetchProcessFilename(obj, procName);
- log("OBJS: added %s at %08x <%s> <%s>", wut, obj, objName, procName);
- } else {
- log("OBJS: added %s at %08x <%s>", wut, obj, objName);
- }
- }
- }
-
- if (pc == 0x634) {
- uint32_t virtAddr = getGPR(0);
- uint32_t physAddr = getGPR(1);
- uint32_t btIndex = getGPR(2);
- uint32_t regionSize = getGPR(3);
- log("KERNEL MMU SECTION: v:%08x p:%08x size:%08x idx:%02x",
- virtAddr, physAddr, regionSize, btIndex);
- }
- if (pc == 0x66C) {
- uint32_t virtAddr = getGPR(0);
- uint32_t physAddr = getGPR(1);
- uint32_t btIndex = getGPR(2);
- uint32_t regionSize = getGPR(3);
- uint32_t pageTableA = getGPR(4);
- uint32_t pageTableB = getGPR(5);
- log("KERNEL MMU PAGES: v:%08x p:%08x size:%08x idx:%02x tableA:%08x tableB:%08x",
- virtAddr, physAddr, regionSize, btIndex, pageTableA, pageTableB);
- }
- if (pc == 0x15070) {
- uint32_t virtAddr = getGPR(0);
- uint32_t physAddr = getGPR(1);
- uint32_t regionSize = getGPR(2);
- uint32_t a = getGPR(3);
- log("DPlatChunkHw MAPPING: v:%08x p:%08x size:%08x arg:%08x",
- virtAddr, physAddr, regionSize, a);
- }
-
- if (pc == 0x16198) {
- uint32_t rawEvent = getGPR(0);
- uint32_t evtType = readVirtualDebug(rawEvent, V32).value_or(0);
- uint32_t evtTick = readVirtualDebug(rawEvent + 4, V32).value_or(0);
- uint32_t evtParamA = readVirtualDebug(rawEvent + 8, V32).value_or(0);
- uint32_t evtParamB = readVirtualDebug(rawEvent + 0xC, V32).value_or(0);
- const char *n = "???";
- switch (evtType) {
- case 0: n = "ENone"; break;
- case 1: n = "EPointerMove"; break;
- case 2: n = "EPointerSwitchOn"; break;
- case 3: n = "EKeyDown"; break;
- case 4: n = "EKeyUp"; break;
- case 5: n = "ERedraw"; break;
- case 6: n = "ESwitchOn"; break;
- case 7: n = "EActive"; break;
- case 8: n = "EInactive"; break;
- case 9: n = "EUpdateModifiers"; break;
- case 10: n = "EButton1Down"; break;
- case 11: n = "EButton1Up"; break;
- case 12: n = "EButton2Down"; break;
- case 13: n = "EButton2Up"; break;
- case 14: n = "EButton3Down"; break;
- case 15: n = "EButton3Up"; break;
- case 16: n = "ESwitchOff"; break;
- }
- log("EVENT %s: tick=%d params=%08x,%08x", n, evtTick, evtParamA, evtParamB);
- }
+ char objName[1000];
+ if (pc == 0x32304) {
+ // CObjectCon::AddL()
+ uint32_t container = getGPR(0);
+ uint32_t obj = getGPR(1);
+ const char* wut = identifyObjectCon(container);
+ if (wut) {
+ fetchName(obj, objName);
+ if (strcmp(wut, "process") == 0) {
+ char procName[1000];
+ fetchProcessFilename(obj, procName);
+ log("OBJS: added %s at %08x <%s> <%s>", wut, obj, objName, procName);
+ } else {
+ log("OBJS: added %s at %08x <%s>", wut, obj, objName);
+ }
+ }
+ }
+
+ if (pc == 0x634) {
+ uint32_t virtAddr = getGPR(0);
+ uint32_t physAddr = getGPR(1);
+ uint32_t btIndex = getGPR(2);
+ uint32_t regionSize = getGPR(3);
+ log("KERNEL MMU SECTION: v:%08x p:%08x size:%08x idx:%02x", virtAddr,
+ physAddr, regionSize, btIndex);
+ }
+ if (pc == 0x66C) {
+ uint32_t virtAddr = getGPR(0);
+ uint32_t physAddr = getGPR(1);
+ uint32_t btIndex = getGPR(2);
+ uint32_t regionSize = getGPR(3);
+ uint32_t pageTableA = getGPR(4);
+ uint32_t pageTableB = getGPR(5);
+ log("KERNEL MMU PAGES: v:%08x p:%08x size:%08x idx:%02x tableA:%08x "
+ "tableB:%08x",
+ virtAddr, physAddr, regionSize, btIndex, pageTableA, pageTableB);
+ }
+ if (pc == 0x15070) {
+ uint32_t virtAddr = getGPR(0);
+ uint32_t physAddr = getGPR(1);
+ uint32_t regionSize = getGPR(2);
+ uint32_t a = getGPR(3);
+ log("DPlatChunkHw MAPPING: v:%08x p:%08x size:%08x arg:%08x", virtAddr,
+ physAddr, regionSize, a);
+ }
+
+ if (pc == 0x16198) {
+ uint32_t rawEvent = getGPR(0);
+ uint32_t evtType = readVirtualDebug(rawEvent, V32).value_or(0);
+ uint32_t evtTick = readVirtualDebug(rawEvent + 4, V32).value_or(0);
+ uint32_t evtParamA = readVirtualDebug(rawEvent + 8, V32).value_or(0);
+ uint32_t evtParamB = readVirtualDebug(rawEvent + 0xC, V32).value_or(0);
+ const char* n = "???";
+ switch (evtType) {
+ case 0:
+ n = "ENone";
+ break;
+ case 1:
+ n = "EPointerMove";
+ break;
+ case 2:
+ n = "EPointerSwitchOn";
+ break;
+ case 3:
+ n = "EKeyDown";
+ break;
+ case 4:
+ n = "EKeyUp";
+ break;
+ case 5:
+ n = "ERedraw";
+ break;
+ case 6:
+ n = "ESwitchOn";
+ break;
+ case 7:
+ n = "EActive";
+ break;
+ case 8:
+ n = "EInactive";
+ break;
+ case 9:
+ n = "EUpdateModifiers";
+ break;
+ case 10:
+ n = "EButton1Down";
+ break;
+ case 11:
+ n = "EButton1Up";
+ break;
+ case 12:
+ n = "EButton2Down";
+ break;
+ case 13:
+ n = "EButton2Up";
+ break;
+ case 14:
+ n = "EButton3Down";
+ break;
+ case 15:
+ n = "EButton3Up";
+ break;
+ case 16:
+ n = "ESwitchOff";
+ break;
+ }
+ log("EVENT %s: tick=%d params=%08x,%08x", n, evtTick, evtParamA, evtParamB);
+ }
}
-
-const char *Emulator::getDeviceName() const { return "Osaris"; }
-int Emulator::getDigitiserWidth() const { return 440; }
+const char* Emulator::getDeviceName() const { return "Osaris"; }
+int Emulator::getDigitiserWidth() const { return 440; }
int Emulator::getDigitiserHeight() const { return 200; }
-int Emulator::getLCDOffsetX() const { return 60; }
-int Emulator::getLCDOffsetY() const { return 0; }
-int Emulator::getLCDWidth() const { return 320; }
-int Emulator::getLCDHeight() const { return 200; }
-
-void Emulator::readLCDIntoBuffer(uint8_t **lines, bool is32BitOutput) const {
- if (lcdAddress == 0xC0000000) {
- int width = 320, height = 200;
- int bpp = 1;
- if (lcdControl & 0x40000000) bpp = 2;
- if (lcdControl & 0x80000000) bpp = 4;
- int ppb = 8 / bpp;
-
- // build our image out
- int lineWidth = (width * bpp) / 8;
- for (int y = 0; y < height; y++) {
- int lineOffs = lineWidth * y;
- for (int x = 0; x < width; x++) {
- uint8_t byte = MemoryBlockC0[lineOffs + (x / ppb)];
- int shift = (x & (ppb - 1)) * bpp;
- int mask = (1 << bpp) - 1;
- int palIdx = (byte >> shift) & mask;
- int palValue;
- if (bpp == 1)
- palValue = palIdx * 255;
- else
- palValue = (lcdPalette >> (palIdx * 4)) & 0xF;
-
- palValue |= (palValue << 4);
- if (is32BitOutput) {
- lines[y][x*4] = palValue ^ 0xFF;
- lines[y][x*4+1] = palValue ^ 0xFF;
- lines[y][x*4+2] = palValue ^ 0xFF;
- } else {
- lines[y][x] = palValue ^ 0xFF;
- }
- }
- }
- }
+int Emulator::getLCDOffsetX() const { return 60; }
+int Emulator::getLCDOffsetY() const { return 0; }
+int Emulator::getLCDWidth() const { return 320; }
+int Emulator::getLCDHeight() const { return 200; }
+
+void Emulator::readLCDIntoBuffer(uint8_t** lines, bool is32BitOutput) const {
+ if (lcdAddress == 0xC0000000) {
+ int width = 320, height = 200;
+ int bpp = 1;
+ if (lcdControl & 0x40000000)
+ bpp = 2;
+ if (lcdControl & 0x80000000)
+ bpp = 4;
+ int ppb = 8 / bpp;
+
+ // build our image out
+ int lineWidth = (width * bpp) / 8;
+ for (int y = 0; y < height; y++) {
+ int lineOffs = lineWidth * y;
+ for (int x = 0; x < width; x++) {
+ uint8_t byte = MemoryBlockC0[lineOffs + (x / ppb)];
+ int shift = (x & (ppb - 1)) * bpp;
+ int mask = (1 << bpp) - 1;
+ int palIdx = (byte >> shift) & mask;
+ int palValue;
+ if (bpp == 1)
+ palValue = palIdx * 255;
+ else
+ palValue = (lcdPalette >> (palIdx * 4)) & 0xF;
+
+ palValue |= (palValue << 4);
+ if (is32BitOutput) {
+ lines[y][x * 4] = palValue ^ 0xFF;
+ lines[y][x * 4 + 1] = palValue ^ 0xFF;
+ lines[y][x * 4 + 2] = palValue ^ 0xFF;
+ } else {
+ lines[y][x] = palValue ^ 0xFF;
+ }
+ }
+ }
+ }
}
-
-
void Emulator::diffPorts(uint32_t oldval, uint32_t newval) {
- uint32_t changes = oldval ^ newval;
- if (changes & 1) log("PRT E0: %d", newval&1);
- if (changes & 2) log("PRT E1: %d", newval&2);
- if (changes & 4) log("PRT E2: %d", newval&4);
- if (changes & 0x100) log("PRT D0: %d", newval&0x100);
- if (changes & 0x200) log("PRT D1: %d", newval&0x200);
- if (changes & 0x400) log("PRT D2: %d", newval&0x400);
- if (changes & 0x800) log("PRT D3: %d", newval&0x800);
- if (changes & 0x1000) log("PRT D4: %d", newval&0x1000);
- if (changes & 0x2000) log("PRT D5: %d", newval&0x2000);
- if (changes & 0x4000) log("PRT D6: %d", newval&0x4000);
- if (changes & 0x8000) log("PRT D7: %d", newval&0x8000);
- if (changes & 0x10000) log("PRT B0: %d", newval&0x10000);
- if (changes & 0x20000) log("PRT B1: %d", newval&0x20000);
- if (changes & 0x40000) log("PRT B2: %d", newval&0x40000);
- if (changes & 0x80000) log("PRT B3: %d", newval&0x80000);
- if (changes & 0x100000) log("PRT B4: %d", newval&0x100000);
- if (changes & 0x200000) log("PRT B5: %d", newval&0x200000);
- if (changes & 0x400000) log("PRT B6: %d", newval&0x400000);
- if (changes & 0x800000) log("PRT B7: %d", newval&0x800000);
+ uint32_t changes = oldval ^ newval;
+ if (changes & 1)
+ log("PRT E0: %d", newval & 1);
+ if (changes & 2)
+ log("PRT E1: %d", newval & 2);
+ if (changes & 4)
+ log("PRT E2: %d", newval & 4);
+ if (changes & 0x100)
+ log("PRT D0: %d", newval & 0x100);
+ if (changes & 0x200)
+ log("PRT D1: %d", newval & 0x200);
+ if (changes & 0x400)
+ log("PRT D2: %d", newval & 0x400);
+ if (changes & 0x800)
+ log("PRT D3: %d", newval & 0x800);
+ if (changes & 0x1000)
+ log("PRT D4: %d", newval & 0x1000);
+ if (changes & 0x2000)
+ log("PRT D5: %d", newval & 0x2000);
+ if (changes & 0x4000)
+ log("PRT D6: %d", newval & 0x4000);
+ if (changes & 0x8000)
+ log("PRT D7: %d", newval & 0x8000);
+ if (changes & 0x10000)
+ log("PRT B0: %d", newval & 0x10000);
+ if (changes & 0x20000)
+ log("PRT B1: %d", newval & 0x20000);
+ if (changes & 0x40000)
+ log("PRT B2: %d", newval & 0x40000);
+ if (changes & 0x80000)
+ log("PRT B3: %d", newval & 0x80000);
+ if (changes & 0x100000)
+ log("PRT B4: %d", newval & 0x100000);
+ if (changes & 0x200000)
+ log("PRT B5: %d", newval & 0x200000);
+ if (changes & 0x400000)
+ log("PRT B6: %d", newval & 0x400000);
+ if (changes & 0x800000)
+ log("PRT B7: %d", newval & 0x800000);
}
-
uint32_t Emulator::readKeyboard() const {
- if (kScan & 8) {
- // Select one keyboard
- if ((kScan & 7) < 7)
- return keyboardColumns[kScan & 7];
- else
- return 0;
- } else if (kScan == 0) {
- // Report all columns combined
- uint8_t val = 0;
- for (int i = 0; i < 7; i++)
- val |= keyboardColumns[i];
- return val;
- } else {
- return 0;
- }
+ if (kScan & 8) {
+ // Select one keyboard
+ if ((kScan & 7) < 7)
+ return keyboardColumns[kScan & 7];
+ else
+ return 0;
+ } else if (kScan == 0) {
+ // Report all columns combined
+ uint8_t val = 0;
+ for (int i = 0; i < 7; i++)
+ val |= keyboardColumns[i];
+ return val;
+ } else {
+ return 0;
+ }
}
void Emulator::setKeyboardKey(EpocKey key, bool value) {
- int idx = -1;
-#define KEY(column, bit) idx = (column << 8) | (1 << bit); break
-
- switch ((int)key) {
- case '1': KEY(0, 0);
- case '2': KEY(1, 0);
- case '3': KEY(2, 0);
- case '4': KEY(3, 0);
- case '5': KEY(4, 0);
- case '6': KEY(5, 0);
- case '7': KEY(6, 0);
-
- case '8': KEY(0, 1);
- case '9': KEY(1, 1);
- case '0': KEY(2, 1);
- case 'P': KEY(3, 1);
- case EStdKeySingleQuote: KEY(4, 1);
- case EStdKeyEnter: KEY(5, 1);
- case EStdKeyBackspace: KEY(6, 1);
-
- case EStdKeyEscape: KEY(0, 2);
- case 'Q': KEY(1, 2);
- case 'W': KEY(2, 2);
- case 'E': KEY(3, 2);
- case 'R': KEY(4, 2);
- case 'T': KEY(5, 2);
- case 'Y': KEY(6, 2);
-
- case 'U': KEY(0, 3);
- case 'J': KEY(1, 3);
- case 'I': KEY(2, 3);
- case 'K': KEY(3, 3);
- case 'O': KEY(4, 3);
- case 'L': KEY(5, 3);
- case EStdKeyUpArrow: KEY(6, 3);
-
- case EStdKeyTab: KEY(0, 4);
- case 'A': KEY(1, 4);
- case 'S': KEY(2, 4);
- case 'D': KEY(3, 4);
- case 'F': KEY(4, 4);
- case 'G': KEY(5, 4);
- case 'H': KEY(6, 4);
-
- case EStdKeySpace: KEY(0, 5);
- case EStdKeyComma: KEY(1, 5);
- case 'M': KEY(2, 5);
- case EStdKeyFullStop: KEY(3, 5);
- case EStdKeyLeftArrow: KEY(4, 5);
- case EStdKeyDownArrow: KEY(5, 5);
- case EStdKeyRightArrow: KEY(6, 5);
-
- case 'Z': KEY(0, 6);
- case 'X': KEY(1, 6);
- case EStdKeyMenu: KEY(2, 6);
- case 'C': KEY(3, 6);
- case 'V': KEY(4, 6);
- case 'B': KEY(5, 6);
- case 'N': KEY(6, 6);
-
- case EStdKeyLeftShift: KEY(8, 0);
- case EStdKeyRightShift: KEY(8, 1);
- case EStdKeyLeftCtrl: KEY(8, 2);
- case EStdKeyLeftFunc: KEY(8, 3);
- }
-
- if (idx >= 0x800) {
- if (value)
- keyboardExtra |= (idx & 0xFF);
- else
- keyboardExtra &= ~(idx & 0xFF);
- } else if (idx >= 0) {
- if (value)
- keyboardColumns[idx >> 8] |= (idx & 0xFF);
- else
- keyboardColumns[idx >> 8] &= ~(idx & 0xFF);
- }
+ int idx = -1;
+#define KEY(column, bit) \
+ idx = (column << 8) | (1 << bit); \
+ break
+
+ switch ((int)key) {
+ case '1':
+ KEY(0, 0);
+ case '2':
+ KEY(1, 0);
+ case '3':
+ KEY(2, 0);
+ case '4':
+ KEY(3, 0);
+ case '5':
+ KEY(4, 0);
+ case '6':
+ KEY(5, 0);
+ case '7':
+ KEY(6, 0);
+
+ case '8':
+ KEY(0, 1);
+ case '9':
+ KEY(1, 1);
+ case '0':
+ KEY(2, 1);
+ case 'P':
+ KEY(3, 1);
+ case EStdKeySingleQuote:
+ KEY(4, 1);
+ case EStdKeyEnter:
+ KEY(5, 1);
+ case EStdKeyBackspace:
+ KEY(6, 1);
+
+ case EStdKeyEscape:
+ KEY(0, 2);
+ case 'Q':
+ KEY(1, 2);
+ case 'W':
+ KEY(2, 2);
+ case 'E':
+ KEY(3, 2);
+ case 'R':
+ KEY(4, 2);
+ case 'T':
+ KEY(5, 2);
+ case 'Y':
+ KEY(6, 2);
+
+ case 'U':
+ KEY(0, 3);
+ case 'J':
+ KEY(1, 3);
+ case 'I':
+ KEY(2, 3);
+ case 'K':
+ KEY(3, 3);
+ case 'O':
+ KEY(4, 3);
+ case 'L':
+ KEY(5, 3);
+ case EStdKeyUpArrow:
+ KEY(6, 3);
+
+ case EStdKeyTab:
+ KEY(0, 4);
+ case 'A':
+ KEY(1, 4);
+ case 'S':
+ KEY(2, 4);
+ case 'D':
+ KEY(3, 4);
+ case 'F':
+ KEY(4, 4);
+ case 'G':
+ KEY(5, 4);
+ case 'H':
+ KEY(6, 4);
+
+ case EStdKeySpace:
+ KEY(0, 5);
+ case EStdKeyComma:
+ KEY(1, 5);
+ case 'M':
+ KEY(2, 5);
+ case EStdKeyFullStop:
+ KEY(3, 5);
+ case EStdKeyLeftArrow:
+ KEY(4, 5);
+ case EStdKeyDownArrow:
+ KEY(5, 5);
+ case EStdKeyRightArrow:
+ KEY(6, 5);
+
+ case 'Z':
+ KEY(0, 6);
+ case 'X':
+ KEY(1, 6);
+ case EStdKeyMenu:
+ KEY(2, 6);
+ case 'C':
+ KEY(3, 6);
+ case 'V':
+ KEY(4, 6);
+ case 'B':
+ KEY(5, 6);
+ case 'N':
+ KEY(6, 6);
+
+ case EStdKeyLeftShift:
+ KEY(8, 0);
+ case EStdKeyRightShift:
+ KEY(8, 1);
+ case EStdKeyLeftCtrl:
+ KEY(8, 2);
+ case EStdKeyLeftFunc:
+ KEY(8, 3);
+ }
+
+ if (idx >= 0x800) {
+ if (value)
+ keyboardExtra |= (idx & 0xFF);
+ else
+ keyboardExtra &= ~(idx & 0xFF);
+ } else if (idx >= 0) {
+ if (value)
+ keyboardColumns[idx >> 8] |= (idx & 0xFF);
+ else
+ keyboardColumns[idx >> 8] &= ~(idx & 0xFF);
+ }
}
-
void Emulator::updateTouchInput(int32_t x, int32_t y, bool down) {
- pendingInterrupts &= ~(1 << EINT2);
- if (down)
- pendingInterrupts |= (1 << EINT2);
- log("Touch: x=%d y=%d down=%s", x, y, down ? "yes" : "no");
- touchX = x;
- touchY = y;
+ pendingInterrupts &= ~(1 << EINT2);
+ if (down)
+ pendingInterrupts |= (1 << EINT2);
+ log("Touch: x=%d y=%d down=%s", x, y, down ? "yes" : "no");
+ touchX = x;
+ touchY = y;
}
-}
+} // namespace CLPS7111
#pragma once
-#include "emubase.h"
#include "clps7111_defs.h"
#include "clps7600.h"
-#include "hardware.h"
+#include "emubase.h"
#include "etna.h"
+#include "hardware.h"
namespace CLPS7111 {
class Emulator : public EmuBase {
public:
- uint8_t ROM[0x800000];
- uint8_t ROM2[0x40000];
- uint8_t MemoryBlockC0[0x400000];
- enum { MemoryBlockMask = 0x3FFFFF };
+ uint8_t ROM[0x800000];
+ uint8_t ROM2[0x40000];
+ uint8_t MemoryBlockC0[0x400000];
+ enum { MemoryBlockMask = 0x3FFFFF };
private:
- uint16_t pendingInterrupts = 0;
- uint16_t interruptMask = 0;
- uint32_t portValues = 0;
- uint32_t portDirections = 0;
- uint32_t sysFlg1 = 0x20008000; // constant CL-PS7111 flag and cold start flag
- uint32_t lcdControl = 0;
- uint32_t lcdAddress = 0xC0000000;
- uint32_t rtc = 0;
- uint32_t rtcDiv = 0;
- uint64_t lcdPalette = 0;
- uint16_t lastSyncioRequest = 0;
-
- uint32_t kScan = 0;
- uint8_t keyboardColumns[7] = {0,0,0,0,0,0,0};
- uint8_t keyboardExtra = 0;
- int32_t touchX = 0, touchY = 0;
+ uint16_t pendingInterrupts = 0;
+ uint16_t interruptMask = 0;
+ uint32_t portValues = 0;
+ uint32_t portDirections = 0;
+ uint32_t sysFlg1 = 0x20008000; // constant CL-PS7111 flag and cold start flag
+ uint32_t lcdControl = 0;
+ uint32_t lcdAddress = 0xC0000000;
+ uint32_t rtc = 0;
+ uint32_t rtcDiv = 0;
+ uint64_t lcdPalette = 0;
+ uint16_t lastSyncioRequest = 0;
- Timer tc1, tc2;
- CLPS7600 pcCardController;
- bool halted = false, asleep = false;
+ uint32_t kScan = 0;
+ uint8_t keyboardColumns[7] = {0, 0, 0, 0, 0, 0, 0};
+ uint8_t keyboardExtra = 0;
+ int32_t touchX = 0, touchY = 0;
+ Timer tc1, tc2;
+ CLPS7600 pcCardController;
+ bool halted = false, asleep = false;
- uint32_t getRTC();
+ uint32_t getRTC();
- uint32_t readReg8(uint32_t reg);
- uint32_t readReg32(uint32_t reg);
- void writeReg8(uint32_t reg, uint8_t value);
- void writeReg32(uint32_t reg, uint32_t value);
+ uint32_t readReg8(uint32_t reg);
+ uint32_t readReg32(uint32_t reg);
+ void writeReg8(uint32_t reg, uint8_t value);
+ void writeReg32(uint32_t reg, uint32_t value);
public:
- MaybeU32 readPhysical(uint32_t physAddr, ValueSize valueSize) override;
- bool writePhysical(uint32_t value, uint32_t physAddr, ValueSize valueSize) override;
+ MaybeU32 readPhysical(uint32_t physAddr, ValueSize valueSize) override;
+ bool writePhysical(uint32_t value, uint32_t physAddr,
+ ValueSize valueSize) override;
private:
- bool configured = false;
- void configure();
+ bool configured = false;
+ void configure();
- const char *identifyObjectCon(uint32_t ptr);
- void fetchStr(uint32_t str, char *buf);
- void fetchName(uint32_t obj, char *buf);
- void fetchProcessFilename(uint32_t obj, char *buf);
- void debugPC(uint32_t pc);
- void diffPorts(uint32_t oldval, uint32_t newval);
- uint32_t readKeyboard() const;
+ const char* identifyObjectCon(uint32_t ptr);
+ void fetchStr(uint32_t str, char* buf);
+ void fetchName(uint32_t obj, char* buf);
+ void fetchProcessFilename(uint32_t obj, char* buf);
+ void debugPC(uint32_t pc);
+ void diffPorts(uint32_t oldval, uint32_t newval);
+ uint32_t readKeyboard() const;
public:
- Emulator();
- uint8_t *getROMBuffer() override;
- size_t getROMSize() override;
- void loadROM(uint8_t *buffer, size_t size) override;
- void executeUntil(int64_t cycles) override;
- int32_t getClockSpeed() const override { return CLOCK_SPEED; }
- const char *getDeviceName() const override;
- int getDigitiserWidth() const override;
- int getDigitiserHeight() const override;
- int getLCDOffsetX() const override;
- int getLCDOffsetY() const override;
- int getLCDWidth() const override;
- int getLCDHeight() const override;
- void readLCDIntoBuffer(uint8_t **lines, bool is32BitOutput) const override;
- void setKeyboardKey(EpocKey key, bool value) override;
- void updateTouchInput(int32_t x, int32_t y, bool down) override;
+ Emulator();
+ uint8_t* getROMBuffer() override;
+ size_t getROMSize() override;
+ void loadROM(uint8_t* buffer, size_t size) override;
+ void executeUntil(int64_t cycles) override;
+ int32_t getClockSpeed() const override { return CLOCK_SPEED; }
+ const char* getDeviceName() const override;
+ int getDigitiserWidth() const override;
+ int getDigitiserHeight() const override;
+ int getLCDOffsetX() const override;
+ int getLCDOffsetY() const override;
+ int getLCDWidth() const override;
+ int getLCDHeight() const override;
+ void readLCDIntoBuffer(uint8_t** lines, bool is32BitOutput) const override;
+ void setKeyboardKey(EpocKey key, bool value) override;
+ void updateTouchInput(int32_t x, int32_t y, bool down) override;
};
-}
+} // namespace CLPS7111
#include <stdint.h>
namespace CLPS7111 {
-enum {
- CLOCK_SPEED = 0x4800*1000,
- TICK_INTERVAL = CLOCK_SPEED / 64
-};
+enum { CLOCK_SPEED = 0x4800 * 1000, TICK_INTERVAL = CLOCK_SPEED / 64 };
enum Interrupt {
- EXTFIQ = 0, // FiqExternal
- BLINT = 1, // FiqBatLow
- WEINT = 2, // FiqWatchDog
- MCINT = 3, // FiqMediaChg
- CSINT = 4, // IrqCodec
- EINT1 = 5, // IrqExt1
- EINT2 = 6, // IrqExt2
- EINT3 = 7, // IrqExt3
- TC1OI = 8, // IrqTimer1
- TC2OI = 9, // IrqTimer2
- RTCMI = 10, // IrqRtcMatch
- TINT = 11, // IrqTick
- UTXINT = 12, // IrqUartTx?
- URXINT1 = 13, // IrqUartRx?
- UMSINT = 14, // IrqUartModem?
- SSEOTI = 15, // IrqSpi
- KBDINT = 16, // IrqKeyPress?
- UTXINT2 = 28, // IrqSpi2Tx?
- URXINT2 = 29, // IrqSpi2Rx?
- FIQ_INTERRUPTS = 0x000F,
- IRQ_INTERRUPTS = 0xFFF0
+ EXTFIQ = 0, // FiqExternal
+ BLINT = 1, // FiqBatLow
+ WEINT = 2, // FiqWatchDog
+ MCINT = 3, // FiqMediaChg
+ CSINT = 4, // IrqCodec
+ EINT1 = 5, // IrqExt1
+ EINT2 = 6, // IrqExt2
+ EINT3 = 7, // IrqExt3
+ TC1OI = 8, // IrqTimer1
+ TC2OI = 9, // IrqTimer2
+ RTCMI = 10, // IrqRtcMatch
+ TINT = 11, // IrqTick
+ UTXINT = 12, // IrqUartTx?
+ URXINT1 = 13, // IrqUartRx?
+ UMSINT = 14, // IrqUartModem?
+ SSEOTI = 15, // IrqSpi
+ KBDINT = 16, // IrqKeyPress?
+ UTXINT2 = 28, // IrqSpi2Tx?
+ URXINT2 = 29, // IrqSpi2Rx?
+ FIQ_INTERRUPTS = 0x000F,
+ IRQ_INTERRUPTS = 0xFFF0
};
enum Register {
- PADR = 0,
- PBDR = 1,
- PDDR = 3,
- PADDR = 0x40,
- PBDDR = 0x41,
- PDDDR = 0x43,
- PEDR = 0x80,
- PEDDR = 0xC0,
- SYSCON1 = 0x100,
- SYSFLG1 = 0x140,
- MEMCFG1 = 0x180,
- MEMCFG2 = 0x1C0,
- DRFPR = 0x200,
- INTSR1 = 0x240,
- INTMR1 = 0x280,
- LCDCON = 0x2C0,
- TC1D = 0x300,
- TC2D = 0x340,
- RTCDR = 0x380,
- RTCMR = 0x3C0,
- PMPCON = 0x400,
- CODR = 0x440,
- UARTDR1 = 0x480,
- UBRLCR1 = 0x4C0,
- SYNCIO = 0x500,
- PALLSW = 0x540,
- PALMSW = 0x580,
- STFCLR = 0x5C0,
- BLEOI = 0x600,
- MCEOI = 0x640,
- TEOI = 0x680,
- TC1EOI = 0x6C0,
- TC2EOI = 0x700,
- RTCEOI = 0x740,
- UMSEOI = 0x780,
- COEOI = 0x7C0,
- HALT = 0x800,
- STDBY = 0x840,
- FRBADDR = 0x1000,
- SYSCON2 = 0x1100,
- SYSFLG2 = 0x1140,
- INTSR2 = 0x1240,
- INTMR2 = 0x1280,
- UARTDR2 = 0x1480,
- UBRLCR2 = 0x14C0,
- KBDEOI = 0x1700
+ PADR = 0,
+ PBDR = 1,
+ PDDR = 3,
+ PADDR = 0x40,
+ PBDDR = 0x41,
+ PDDDR = 0x43,
+ PEDR = 0x80,
+ PEDDR = 0xC0,
+ SYSCON1 = 0x100,
+ SYSFLG1 = 0x140,
+ MEMCFG1 = 0x180,
+ MEMCFG2 = 0x1C0,
+ DRFPR = 0x200,
+ INTSR1 = 0x240,
+ INTMR1 = 0x280,
+ LCDCON = 0x2C0,
+ TC1D = 0x300,
+ TC2D = 0x340,
+ RTCDR = 0x380,
+ RTCMR = 0x3C0,
+ PMPCON = 0x400,
+ CODR = 0x440,
+ UARTDR1 = 0x480,
+ UBRLCR1 = 0x4C0,
+ SYNCIO = 0x500,
+ PALLSW = 0x540,
+ PALMSW = 0x580,
+ STFCLR = 0x5C0,
+ BLEOI = 0x600,
+ MCEOI = 0x640,
+ TEOI = 0x680,
+ TC1EOI = 0x6C0,
+ TC2EOI = 0x700,
+ RTCEOI = 0x740,
+ UMSEOI = 0x780,
+ COEOI = 0x7C0,
+ HALT = 0x800,
+ STDBY = 0x840,
+ FRBADDR = 0x1000,
+ SYSCON2 = 0x1100,
+ SYSFLG2 = 0x1140,
+ INTSR2 = 0x1240,
+ INTMR2 = 0x1280,
+ UARTDR2 = 0x1480,
+ UBRLCR2 = 0x14C0,
+ KBDEOI = 0x1700
};
-}
-
+} // namespace CLPS7111
#include "clps7600.h"
#include "arm710.h"
-CLPS7600::CLPS7600(ARM710 *_cpu)
-{
- cpu = _cpu;
-}
+CLPS7600::CLPS7600(ARM710* _cpu) { cpu = _cpu; }
enum {
- PCM_BVD1 = 1,
- PCM_BVD2 = 2,
- PCM_CD1 = 4,
- PCM_CD2 = 8,
- PCM_VS1 = 0x10,
- PCM_VS2 = 0x20,
- PDREQ_L = 0x40,
- PCTL = 0x100,
- PCM_WP = 0x200,
- PCM_RDY = 0x400,
- FIFOTHLD = 0x800,
- IDLE = 0x1000,
- WR_FAIL = 0x2000,
- RD_FAIL = 0x4000,
- RESERVED = 0x8000
+ PCM_BVD1 = 1,
+ PCM_BVD2 = 2,
+ PCM_CD1 = 4,
+ PCM_CD2 = 8,
+ PCM_VS1 = 0x10,
+ PCM_VS2 = 0x20,
+ PDREQ_L = 0x40,
+ PCTL = 0x100,
+ PCM_WP = 0x200,
+ PCM_RDY = 0x400,
+ FIFOTHLD = 0x800,
+ IDLE = 0x1000,
+ WR_FAIL = 0x2000,
+ RD_FAIL = 0x4000,
+ RESERVED = 0x8000
};
uint32_t CLPS7600::getInputLevel() const {
- uint32_t v = 0;
+ uint32_t v = 0;
- if (isMemoryMode())
- v |= PCM_RDY; // we are ALWAYS ready
+ if (isMemoryMode())
+ v |= PCM_RDY; // we are ALWAYS ready
- return v;
+ return v;
}
-uint32_t CLPS7600::read(uint32_t addr, ARM710::ValueSize valueSize)
-{
- cpu->log("CLPS7600 read: addr=%07x size=%d pc=%08x lr=%08x", addr, (valueSize == ARM710::V32) ? 32 : 8, cpu->getRealPC(), cpu->getGPR(14));
- if (valueSize == ARM710::V32) {
- switch (addr) {
- case 0xC000000: // Interrupt Status
- return interruptStatus;
- case 0xC000400: // Interrupt Mask
- return interruptMask;
- case 0xC001C00: // Interrupt Input Level
- return getInputLevel();
- case 0xC002000: // System Interface Configuration
- return systemInterfaceConfig;
- case 0xC002400: // Card Interface Configuration
- return cardInterfaceConfig;
- case 0xC002800: // Power Management
- return powerManagement;
- case 0xC002C00: // Card Power Control
- return cardPowerControl;
- case 0xC003000: // Card Interface Timing 0A
- return cardInterfaceTiming0A;
- case 0xC003400: // Card Interface Timing 0B
- return cardInterfaceTiming0B;
- case 0xC003800: // Card Interface Timing 1A
- return cardInterfaceTiming1A;
- case 0xC003C00: // Card Interface Timing 1B
- return cardInterfaceTiming1B;
- case 0xC004000: // DMA Control
- return dmaControl;
- case 0xC004400: // Device Information
- return deviceInformation;
- default:
- cpu->log("CLPS7600 unknown register read: addr=%07x pc=%08x lr=%08x", addr, cpu->getRealPC(), cpu->getGPR(14));
- return 0xFFFFFFFF;
- }
- }
- cpu->log("unknown!!");
- return 0xFF;
+uint32_t CLPS7600::read(uint32_t addr, ARM710::ValueSize valueSize) {
+ cpu->log("CLPS7600 read: addr=%07x size=%d pc=%08x lr=%08x", addr,
+ (valueSize == ARM710::V32) ? 32 : 8, cpu->getRealPC(),
+ cpu->getGPR(14));
+ if (valueSize == ARM710::V32) {
+ switch (addr) {
+ case 0xC000000: // Interrupt Status
+ return interruptStatus;
+ case 0xC000400: // Interrupt Mask
+ return interruptMask;
+ case 0xC001C00: // Interrupt Input Level
+ return getInputLevel();
+ case 0xC002000: // System Interface Configuration
+ return systemInterfaceConfig;
+ case 0xC002400: // Card Interface Configuration
+ return cardInterfaceConfig;
+ case 0xC002800: // Power Management
+ return powerManagement;
+ case 0xC002C00: // Card Power Control
+ return cardPowerControl;
+ case 0xC003000: // Card Interface Timing 0A
+ return cardInterfaceTiming0A;
+ case 0xC003400: // Card Interface Timing 0B
+ return cardInterfaceTiming0B;
+ case 0xC003800: // Card Interface Timing 1A
+ return cardInterfaceTiming1A;
+ case 0xC003C00: // Card Interface Timing 1B
+ return cardInterfaceTiming1B;
+ case 0xC004000: // DMA Control
+ return dmaControl;
+ case 0xC004400: // Device Information
+ return deviceInformation;
+ default:
+ cpu->log("CLPS7600 unknown register read: addr=%07x pc=%08x lr=%08x",
+ addr, cpu->getRealPC(), cpu->getGPR(14));
+ return 0xFFFFFFFF;
+ }
+ }
+ cpu->log("unknown!!");
+ return 0xFF;
}
-void CLPS7600::write(uint32_t value, uint32_t addr, ARM710::ValueSize valueSize)
-{
- cpu->log("CLPS7600 write: addr=%07x size=%d value=%08x pc=%08x lr=%08x", addr, (valueSize == ARM710::V32) ? 32 : 8, value, cpu->getRealPC(), cpu->getGPR(14));
- if (valueSize == ARM710::V32) {
- switch (addr) {
- case 0xC000400: // Interrupt Mask
- interruptMask = value;
- break;
- case 0xC000800: // Interrupt Clear
- break;
- case 0xC000C00: // Interrupt Output Select
- break;
- case 0xC001000: // Interrupt Reserved Register 1
- break;
- case 0xC001400: // Interrupt Reserved Register 2
- break;
- case 0xC001800: // Interrupt Reserved Register 3
- break;
- case 0xC002000: // System Interface Configuration
- systemInterfaceConfig = value;
- break;
- case 0xC002400: // Card Interface Configuration
- cardInterfaceConfig = value;
- cpu->log("PC card enabled: %s", (value & 0x400) ? "yes" : "no");
- cpu->log("PC card write protect: %s", (value & 0x200) ? "yes" : "no");
- cpu->log("PC card mode: %s", (value & 0x100) ? "i/o" : "memory");
- break;
- case 0xC002800: // Power Management
- powerManagement = value;
- break;
- case 0xC002C00: // Card Power Control
- cardPowerControl = value;
- break;
- case 0xC003000: // Card Interface Timing 0A
- cardInterfaceTiming0A = value;
- break;
- case 0xC003400: // Card Interface Timing 0B
- cardInterfaceTiming0B = value;
- break;
- case 0xC003800: // Card Interface Timing 1A
- cardInterfaceTiming1A = value;
- break;
- case 0xC003C00: // Card Interface Timing 1B
- cardInterfaceTiming1B = value;
- break;
- case 0xC004000: // DMA Control
- dmaControl = value;
- break;
- case 0xC004400: // Device Information
- deviceInformation = value;
- break;
- default:
- cpu->log("CLPS7600 unknown register write: addr=%07x value=%08x pc=%08x lr=%08x", addr, value, cpu->getRealPC(), cpu->getGPR(14));
- }
- } else {
- cpu->log("unknown write!!");
- }
+void CLPS7600::write(uint32_t value, uint32_t addr,
+ ARM710::ValueSize valueSize) {
+ cpu->log("CLPS7600 write: addr=%07x size=%d value=%08x pc=%08x lr=%08x", addr,
+ (valueSize == ARM710::V32) ? 32 : 8, value, cpu->getRealPC(),
+ cpu->getGPR(14));
+ if (valueSize == ARM710::V32) {
+ switch (addr) {
+ case 0xC000400: // Interrupt Mask
+ interruptMask = value;
+ break;
+ case 0xC000800: // Interrupt Clear
+ break;
+ case 0xC000C00: // Interrupt Output Select
+ break;
+ case 0xC001000: // Interrupt Reserved Register 1
+ break;
+ case 0xC001400: // Interrupt Reserved Register 2
+ break;
+ case 0xC001800: // Interrupt Reserved Register 3
+ break;
+ case 0xC002000: // System Interface Configuration
+ systemInterfaceConfig = value;
+ break;
+ case 0xC002400: // Card Interface Configuration
+ cardInterfaceConfig = value;
+ cpu->log("PC card enabled: %s", (value & 0x400) ? "yes" : "no");
+ cpu->log("PC card write protect: %s", (value & 0x200) ? "yes" : "no");
+ cpu->log("PC card mode: %s", (value & 0x100) ? "i/o" : "memory");
+ break;
+ case 0xC002800: // Power Management
+ powerManagement = value;
+ break;
+ case 0xC002C00: // Card Power Control
+ cardPowerControl = value;
+ break;
+ case 0xC003000: // Card Interface Timing 0A
+ cardInterfaceTiming0A = value;
+ break;
+ case 0xC003400: // Card Interface Timing 0B
+ cardInterfaceTiming0B = value;
+ break;
+ case 0xC003800: // Card Interface Timing 1A
+ cardInterfaceTiming1A = value;
+ break;
+ case 0xC003C00: // Card Interface Timing 1B
+ cardInterfaceTiming1B = value;
+ break;
+ case 0xC004000: // DMA Control
+ dmaControl = value;
+ break;
+ case 0xC004400: // Device Information
+ deviceInformation = value;
+ break;
+ default:
+ cpu->log("CLPS7600 unknown register write: addr=%07x value=%08x pc=%08x "
+ "lr=%08x",
+ addr, value, cpu->getRealPC(), cpu->getGPR(14));
+ }
+ } else {
+ cpu->log("unknown write!!");
+ }
}
#pragma once
-#include <stdint.h>
#include "arm710.h"
+#include <stdint.h>
-class CLPS7600
-{
+class CLPS7600 {
private:
- ARM710 *cpu;
+ ARM710* cpu;
- uint32_t interruptStatus = 0;
- uint32_t interruptMask = 0;
- uint32_t systemInterfaceConfig = 0x1F8;
- uint32_t cardInterfaceConfig = 0;
- uint32_t powerManagement = 0;
- uint32_t cardPowerControl = 0;
- uint32_t cardInterfaceTiming0A = 0x1F00;
- uint32_t cardInterfaceTiming0B = 0;
- uint32_t cardInterfaceTiming1A = 0x1F00;
- uint32_t cardInterfaceTiming1B = 0;
- uint32_t dmaControl = 0;
- uint32_t deviceInformation = 0x40;
+ uint32_t interruptStatus = 0;
+ uint32_t interruptMask = 0;
+ uint32_t systemInterfaceConfig = 0x1F8;
+ uint32_t cardInterfaceConfig = 0;
+ uint32_t powerManagement = 0;
+ uint32_t cardPowerControl = 0;
+ uint32_t cardInterfaceTiming0A = 0x1F00;
+ uint32_t cardInterfaceTiming0B = 0;
+ uint32_t cardInterfaceTiming1A = 0x1F00;
+ uint32_t cardInterfaceTiming1B = 0;
+ uint32_t dmaControl = 0;
+ uint32_t deviceInformation = 0x40;
- bool isIOMode() const { return (cardInterfaceConfig & 0x100); }
- bool isMemoryMode() const { return !(cardInterfaceConfig & 0x100); }
- uint32_t getInputLevel() const;
+ bool isIOMode() const { return (cardInterfaceConfig & 0x100); }
+ bool isMemoryMode() const { return !(cardInterfaceConfig & 0x100); }
+ uint32_t getInputLevel() const;
public:
- CLPS7600(ARM710 *_cpu);
+ CLPS7600(ARM710* _cpu);
- uint32_t read(uint32_t addr, ARM710::ValueSize valueSize);
- void write(uint32_t value, uint32_t addr, ARM710::ValueSize valueSize);
+ uint32_t read(uint32_t addr, ARM710::ValueSize valueSize);
+ void write(uint32_t value, uint32_t addr, ARM710::ValueSize valueSize);
};
-
#define snprintf _snprintf
#define strdup _strdup
#define lseek _lseek
-#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
+#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
#elif defined(__wii__)
#include <sys/time.h>
typedef intptr_t ssize_t;
#else
#include <strings.h>
-#include <unistd.h>
#include <sys/time.h>
+#include <unistd.h>
#endif
#ifdef PSP2
#endif
#ifndef SSIZE_MAX
-#define SSIZE_MAX ((ssize_t) (SIZE_MAX >> 1))
+#define SSIZE_MAX ((ssize_t)(SIZE_MAX >> 1))
#endif
#ifndef UNUSED
#define M_PI 3.141592654f
#endif
-#if !defined(_MSC_VER) && (defined(__llvm__) || (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
+#if !defined(_MSC_VER) && (defined(__llvm__) || (__GNUC__ > 4) || \
+ (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
#define ATOMIC_STORE(DST, SRC) __atomic_store_n(&DST, SRC, __ATOMIC_RELEASE)
#define ATOMIC_LOAD(DST, SRC) DST = __atomic_load_n(&SRC, __ATOMIC_ACQUIRE)
#define ATOMIC_ADD(DST, OP) __atomic_add_fetch(&DST, OP, __ATOMIC_RELEASE)
#define ATOMIC_SUB(DST, OP) __atomic_sub_fetch(&DST, OP, __ATOMIC_RELEASE)
#define ATOMIC_OR(DST, OP) __atomic_or_fetch(&DST, OP, __ATOMIC_RELEASE)
#define ATOMIC_AND(DST, OP) __atomic_and_fetch(&DST, OP, __ATOMIC_RELEASE)
-#define ATOMIC_CMPXCHG(DST, EXPECTED, SRC) __atomic_compare_exchange_n(&DST, &EXPECTED, SRC, true,__ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)
+#define ATOMIC_CMPXCHG(DST, EXPECTED, SRC) \
+ __atomic_compare_exchange_n(&DST, &EXPECTED, SRC, true, __ATOMIC_ACQ_REL, \
+ __ATOMIC_ACQUIRE)
#define ATOMIC_STORE_PTR(DST, SRC) ATOMIC_STORE(DST, SRC)
#define ATOMIC_LOAD_PTR(DST, SRC) ATOMIC_LOAD(DST, SRC)
#elif defined _MSC_VER
#define ATOMIC_SUB(DST, OP) InterlockedAddRelease(&DST, -OP)
#define ATOMIC_OR(DST, OP) InterlockedOrRelease(&DST, OP)
#define ATOMIC_AND(DST, OP) InterlockedAndRelease(&DST, OP)
-#define ATOMIC_CMPXCHG(DST, EXPECTED, SRC) (InterlockedCompareExchange(&DST, SRC, EXPECTED) == EXPECTED)
+#define ATOMIC_CMPXCHG(DST, EXPECTED, SRC) \
+ (InterlockedCompareExchange(&DST, SRC, EXPECTED) == EXPECTED)
#define ATOMIC_STORE_PTR(DST, SRC) InterlockedExchangePointer(&DST, SRC)
-#define ATOMIC_LOAD_PTR(DST, SRC) DST = InterlockedCompareExchangePointer(&SRC, 0, 0)
+#define ATOMIC_LOAD_PTR(DST, SRC) \
+ DST = InterlockedCompareExchangePointer(&SRC, 0, 0)
#else
// TODO
#define ATOMIC_STORE(DST, SRC) DST = SRC
#define ATOMIC_SUB(DST, OP) DST -= OP
#define ATOMIC_OR(DST, OP) DST |= OP
#define ATOMIC_AND(DST, OP) DST &= OP
-#define ATOMIC_CMPXCHG(DST, EXPECTED, OP) ((DST == EXPECTED) ? ((DST = OP), true) : false)
+#define ATOMIC_CMPXCHG(DST, EXPECTED, OP) \
+ ((DST == EXPECTED) ? ((DST = OP), true) : false)
#define ATOMIC_STORE_PTR(DST, SRC) ATOMIC_STORE(DST, SRC)
#define ATOMIC_LOAD_PTR(DST, SRC) ATOMIC_LOAD(DST, SRC)
#endif
#endif
#if defined __BIG_ENDIAN__
-#define LOAD_32BE(DEST, ADDR, ARR) DEST = *(uint32_t*) ((uintptr_t) (ARR) + (size_t) (ADDR))
+#define LOAD_32BE(DEST, ADDR, ARR) \
+ DEST = *(uint32_t*)((uintptr_t)(ARR) + (size_t)(ADDR))
#if defined(__PPC__) || defined(__POWERPC__)
-#define LOAD_32LE(DEST, ADDR, ARR) { \
- uint32_t _addr = (ADDR); \
- const void* _ptr = (ARR); \
- __asm__("lwbrx %0, %1, %2" : "=r"(DEST) : "b"(_ptr), "r"(_addr)); \
-}
+#define LOAD_32LE(DEST, ADDR, ARR) \
+ { \
+ uint32_t _addr = (ADDR); \
+ const void* _ptr = (ARR); \
+ __asm__("lwbrx %0, %1, %2" : "=r"(DEST) : "b"(_ptr), "r"(_addr)); \
+ }
-#define LOAD_16LE(DEST, ADDR, ARR) { \
- uint32_t _addr = (ADDR); \
- const void* _ptr = (ARR); \
- __asm__("lhbrx %0, %1, %2" : "=r"(DEST) : "b"(_ptr), "r"(_addr)); \
-}
+#define LOAD_16LE(DEST, ADDR, ARR) \
+ { \
+ uint32_t _addr = (ADDR); \
+ const void* _ptr = (ARR); \
+ __asm__("lhbrx %0, %1, %2" : "=r"(DEST) : "b"(_ptr), "r"(_addr)); \
+ }
-#define STORE_32LE(SRC, ADDR, ARR) { \
- uint32_t _addr = (ADDR); \
- void* _ptr = (ARR); \
- __asm__("stwbrx %0, %1, %2" : : "r"(SRC), "b"(_ptr), "r"(_addr) : "memory"); \
-}
+#define STORE_32LE(SRC, ADDR, ARR) \
+ { \
+ uint32_t _addr = (ADDR); \
+ void* _ptr = (ARR); \
+ __asm__("stwbrx %0, %1, %2" \
+ : \
+ : "r"(SRC), "b"(_ptr), "r"(_addr) \
+ : "memory"); \
+ }
-#define STORE_16LE(SRC, ADDR, ARR) { \
- uint32_t _addr = (ADDR); \
- void* _ptr = (ARR); \
- __asm__("sthbrx %0, %1, %2" : : "r"(SRC), "b"(_ptr), "r"(_addr) : "memory"); \
-}
+#define STORE_16LE(SRC, ADDR, ARR) \
+ { \
+ uint32_t _addr = (ADDR); \
+ void* _ptr = (ARR); \
+ __asm__("sthbrx %0, %1, %2" \
+ : \
+ : "r"(SRC), "b"(_ptr), "r"(_addr) \
+ : "memory"); \
+ }
-#define LOAD_64LE(DEST, ADDR, ARR) { \
- uint32_t _addr = (ADDR); \
- union { \
- struct { \
- uint32_t hi; \
- uint32_t lo; \
- }; \
- uint64_t b64; \
- } bswap; \
- const void* _ptr = (ARR); \
- __asm__( \
- "lwbrx %0, %2, %3 \n" \
- "lwbrx %1, %2, %4 \n" \
- : "=&r"(bswap.lo), "=&r"(bswap.hi) : "b"(_ptr), "r"(_addr), "r"(_addr + 4)) ; \
- DEST = bswap.b64; \
-}
+#define LOAD_64LE(DEST, ADDR, ARR) \
+ { \
+ uint32_t _addr = (ADDR); \
+ union { \
+ struct { \
+ uint32_t hi; \
+ uint32_t lo; \
+ }; \
+ uint64_t b64; \
+ } bswap; \
+ const void* _ptr = (ARR); \
+ __asm__("lwbrx %0, %2, %3 \n" \
+ "lwbrx %1, %2, %4 \n" \
+ : "=&r"(bswap.lo), "=&r"(bswap.hi) \
+ : "b"(_ptr), "r"(_addr), "r"(_addr + 4)); \
+ DEST = bswap.b64; \
+ }
-#define STORE_64LE(SRC, ADDR, ARR) { \
- uint32_t _addr = (ADDR); \
- union { \
- struct { \
- uint32_t hi; \
- uint32_t lo; \
- }; \
- uint64_t b64; \
- } bswap = { .b64 = SRC }; \
- const void* _ptr = (ARR); \
- __asm__( \
- "stwbrx %0, %2, %3 \n" \
- "stwbrx %1, %2, %4 \n" \
- : : "r"(bswap.hi), "r"(bswap.lo), "b"(_ptr), "r"(_addr), "r"(_addr + 4) : "memory"); \
-}
+#define STORE_64LE(SRC, ADDR, ARR) \
+ { \
+ uint32_t _addr = (ADDR); \
+ union { \
+ struct { \
+ uint32_t hi; \
+ uint32_t lo; \
+ }; \
+ uint64_t b64; \
+ } bswap = {.b64 = SRC}; \
+ const void* _ptr = (ARR); \
+ __asm__("stwbrx %0, %2, %3 \n" \
+ "stwbrx %1, %2, %4 \n" \
+ : \
+ : "r"(bswap.hi), "r"(bswap.lo), "b"(_ptr), "r"(_addr), \
+ "r"(_addr + 4) \
+ : "memory"); \
+ }
-#elif defined(__llvm__) || (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
-#define LOAD_64LE(DEST, ADDR, ARR) DEST = __builtin_bswap64(((uint64_t*) ARR)[(ADDR) >> 3])
-#define LOAD_32LE(DEST, ADDR, ARR) DEST = __builtin_bswap32(((uint32_t*) ARR)[(ADDR) >> 2])
-#define LOAD_16LE(DEST, ADDR, ARR) DEST = __builtin_bswap16(((uint16_t*) ARR)[(ADDR) >> 1])
-#define STORE_64LE(SRC, ADDR, ARR) ((uint64_t*) ARR)[(ADDR) >> 3] = __builtin_bswap64(SRC)
-#define STORE_32LE(SRC, ADDR, ARR) ((uint32_t*) ARR)[(ADDR) >> 2] = __builtin_bswap32(SRC)
-#define STORE_16LE(SRC, ADDR, ARR) ((uint16_t*) ARR)[(ADDR) >> 1] = __builtin_bswap16(SRC)
+#elif defined(__llvm__) || (__GNUC__ > 4) || \
+ (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+#define LOAD_64LE(DEST, ADDR, ARR) \
+ DEST = __builtin_bswap64(((uint64_t*)ARR)[(ADDR) >> 3])
+#define LOAD_32LE(DEST, ADDR, ARR) \
+ DEST = __builtin_bswap32(((uint32_t*)ARR)[(ADDR) >> 2])
+#define LOAD_16LE(DEST, ADDR, ARR) \
+ DEST = __builtin_bswap16(((uint16_t*)ARR)[(ADDR) >> 1])
+#define STORE_64LE(SRC, ADDR, ARR) \
+ ((uint64_t*)ARR)[(ADDR) >> 3] = __builtin_bswap64(SRC)
+#define STORE_32LE(SRC, ADDR, ARR) \
+ ((uint32_t*)ARR)[(ADDR) >> 2] = __builtin_bswap32(SRC)
+#define STORE_16LE(SRC, ADDR, ARR) \
+ ((uint16_t*)ARR)[(ADDR) >> 1] = __builtin_bswap16(SRC)
#else
#error Big endian build not supported on this platform.
#endif
#else
-#define LOAD_64LE(DEST, ADDR, ARR) DEST = *(uint64_t*) ((uintptr_t) (ARR) + (size_t) (ADDR))
-#define LOAD_32LE(DEST, ADDR, ARR) DEST = *(uint32_t*) ((uintptr_t) (ARR) + (size_t) (ADDR))
-#define LOAD_16LE(DEST, ADDR, ARR) DEST = *(uint16_t*) ((uintptr_t) (ARR) + (size_t) (ADDR))
-#define STORE_64LE(SRC, ADDR, ARR) *(uint64_t*) ((uintptr_t) (ARR) + (size_t) (ADDR)) = SRC
-#define STORE_32LE(SRC, ADDR, ARR) *(uint32_t*) ((uintptr_t) (ARR) + (size_t) (ADDR)) = SRC
-#define STORE_16LE(SRC, ADDR, ARR) *(uint16_t*) ((uintptr_t) (ARR) + (size_t) (ADDR)) = SRC
+#define LOAD_64LE(DEST, ADDR, ARR) \
+ DEST = *(uint64_t*)((uintptr_t)(ARR) + (size_t)(ADDR))
+#define LOAD_32LE(DEST, ADDR, ARR) \
+ DEST = *(uint32_t*)((uintptr_t)(ARR) + (size_t)(ADDR))
+#define LOAD_16LE(DEST, ADDR, ARR) \
+ DEST = *(uint16_t*)((uintptr_t)(ARR) + (size_t)(ADDR))
+#define STORE_64LE(SRC, ADDR, ARR) \
+ *(uint64_t*)((uintptr_t)(ARR) + (size_t)(ADDR)) = SRC
+#define STORE_32LE(SRC, ADDR, ARR) \
+ *(uint32_t*)((uintptr_t)(ARR) + (size_t)(ADDR)) = SRC
+#define STORE_16LE(SRC, ADDR, ARR) \
+ *(uint16_t*)((uintptr_t)(ARR) + (size_t)(ADDR)) = SRC
#ifdef _MSC_VER
-#define LOAD_32BE(DEST, ADDR, ARR) DEST = _byteswap_ulong(((uint32_t*) ARR)[(ADDR) >> 2])
+#define LOAD_32BE(DEST, ADDR, ARR) \
+ DEST = _byteswap_ulong(((uint32_t*)ARR)[(ADDR) >> 2])
#else
-#define LOAD_32BE(DEST, ADDR, ARR) DEST = __builtin_bswap32(((uint32_t*) ARR)[(ADDR) >> 2])
+#define LOAD_32BE(DEST, ADDR, ARR) \
+ DEST = __builtin_bswap32(((uint32_t*)ARR)[(ADDR) >> 2])
#endif
#endif
#define MAKE_MASK(START, END) (((1 << ((END) - (START))) - 1) << (START))
#define CHECK_BITS(SRC, START, END) ((SRC) & MAKE_MASK(START, END))
-#define EXT_BITS(SRC, START, END) (((SRC) >> (START)) & ((1 << ((END) - (START))) - 1))
-#define INS_BITS(SRC, START, END, BITS) (CLEAR_BITS(SRC, START, END) | (((BITS) << (START)) & MAKE_MASK(START, END)))
+#define EXT_BITS(SRC, START, END) \
+ (((SRC) >> (START)) & ((1 << ((END) - (START))) - 1))
+#define INS_BITS(SRC, START, END, BITS) \
+ (CLEAR_BITS(SRC, START, END) | (((BITS) << (START)) & MAKE_MASK(START, END)))
#define CLEAR_BITS(SRC, START, END) ((SRC) & ~MAKE_MASK(START, END))
#define FILL_BITS(SRC, START, END) ((SRC) | MAKE_MASK(START, END))
-#define TEST_FILL_BITS(SRC, START, END, TEST) ((TEST) ? (FILL_BITS(SRC, START, END)) : (CLEAR_BITS(SRC, START, END)))
+#define TEST_FILL_BITS(SRC, START, END, TEST) \
+ ((TEST) ? (FILL_BITS(SRC, START, END)) : (CLEAR_BITS(SRC, START, END)))
#ifdef _MSC_VER
-#pragma section(".CRT$XCU",read)
+#pragma section(".CRT$XCU", read)
#define ATTRIBUTE_UNUSED
#define ATTRIBUTE_FORMAT(X, Y, Z)
#define ATTRIBUTE_NOINLINE
// Adapted from https://stackoverflow.com/a/2390626
-#define _CONSTRUCTOR(FN, PRE) \
- static void FN(void); \
- __declspec(allocate(".CRT$XCU")) void (*_CONSTRUCTOR_ ## FN)(void) = FN; \
- static void FN(void)
+#define _CONSTRUCTOR(FN, PRE) \
+ static void FN(void); \
+ __declspec(allocate(".CRT$XCU")) void (*_CONSTRUCTOR_##FN)(void) = FN; \
+ static void FN(void)
#ifdef _WIN64
#define CONSTRUCTOR(FN) _CONSTRUCTOR(FN, "")
#else
#define DECL_BITFIELD(NAME, TYPE) typedef TYPE NAME
-#define DECL_BITS(TYPE, FIELD, START, SIZE) \
- ATTRIBUTE_UNUSED static inline TYPE TYPE ## Is ## FIELD (TYPE src) { \
- return CHECK_BITS(src, (START), (START) + (SIZE)); \
- } \
- ATTRIBUTE_UNUSED static inline TYPE TYPE ## Get ## FIELD (TYPE src) { \
- return EXT_BITS(src, (START), (START) + (SIZE)); \
- } \
- ATTRIBUTE_UNUSED static inline TYPE TYPE ## Clear ## FIELD (TYPE src) { \
- return CLEAR_BITS(src, (START), (START) + (SIZE)); \
- } \
- ATTRIBUTE_UNUSED static inline TYPE TYPE ## Fill ## FIELD (TYPE src) { \
- return FILL_BITS(src, (START), (START) + (SIZE)); \
- } \
- ATTRIBUTE_UNUSED static inline TYPE TYPE ## Set ## FIELD (TYPE src, TYPE bits) { \
- return INS_BITS(src, (START), (START) + (SIZE), bits); \
- } \
- ATTRIBUTE_UNUSED static inline TYPE TYPE ## TestFill ## FIELD (TYPE src, bool test) { \
- return TEST_FILL_BITS(src, (START), (START) + (SIZE), test); \
- }
+#define DECL_BITS(TYPE, FIELD, START, SIZE) \
+ ATTRIBUTE_UNUSED static inline TYPE TYPE##Is##FIELD(TYPE src) { \
+ return CHECK_BITS(src, (START), (START) + (SIZE)); \
+ } \
+ ATTRIBUTE_UNUSED static inline TYPE TYPE##Get##FIELD(TYPE src) { \
+ return EXT_BITS(src, (START), (START) + (SIZE)); \
+ } \
+ ATTRIBUTE_UNUSED static inline TYPE TYPE##Clear##FIELD(TYPE src) { \
+ return CLEAR_BITS(src, (START), (START) + (SIZE)); \
+ } \
+ ATTRIBUTE_UNUSED static inline TYPE TYPE##Fill##FIELD(TYPE src) { \
+ return FILL_BITS(src, (START), (START) + (SIZE)); \
+ } \
+ ATTRIBUTE_UNUSED static inline TYPE TYPE##Set##FIELD(TYPE src, TYPE bits) { \
+ return INS_BITS(src, (START), (START) + (SIZE), bits); \
+ } \
+ ATTRIBUTE_UNUSED static inline TYPE TYPE##TestFill##FIELD(TYPE src, \
+ bool test) { \
+ return TEST_FILL_BITS(src, (START), (START) + (SIZE), test); \
+ }
#define DECL_BIT(TYPE, FIELD, BIT) DECL_BITS(TYPE, FIELD, BIT, 1)
#define UNLIKELY(X) (!!(X))
#endif
-#define ROR(I, ROTATE) ((((uint32_t) (I)) >> ROTATE) | ((uint32_t) (I) << ((-ROTATE) & 31)))
+#define ROR(I, ROTATE) \
+ ((((uint32_t)(I)) >> ROTATE) | ((uint32_t)(I) << ((-ROTATE) & 31)))
static inline uint32_t popcount32(unsigned bits) {
- bits = bits - ((bits >> 1) & 0x55555555);
- bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
- return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
+ bits = bits - ((bits >> 1) & 0x55555555);
+ bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
+ return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
}
CXX_GUARD_END
#include "emitter-arm.h"
#include "isa-inlines.h"
-#define ADDR_MODE_1_SHIFT(OP) \
- info->op3.reg = opcode & 0x0000000F; \
- info->op3.shifterOp = ARM_SHIFT_ ## OP; \
- info->operandFormat |= ARM_OPERAND_REGISTER_3; \
- if (opcode & 0x00000010) { \
- info->op3.shifterReg = (opcode >> 8) & 0xF; \
- ++info->iCycles; \
- info->operandFormat |= ARM_OPERAND_SHIFT_REGISTER_3; \
- } else { \
- info->op3.shifterImm = (opcode >> 7) & 0x1F; \
- info->operandFormat |= ARM_OPERAND_SHIFT_IMMEDIATE_3; \
- }
-
-#define ADDR_MODE_1_LSL \
- ADDR_MODE_1_SHIFT(LSL) \
- if (!info->op3.shifterImm) { \
- info->operandFormat &= ~ARM_OPERAND_SHIFT_IMMEDIATE_3; \
- info->op3.shifterOp = ARM_SHIFT_NONE; \
- }
+#define ADDR_MODE_1_SHIFT(OP) \
+ info->op3.reg = opcode & 0x0000000F; \
+ info->op3.shifterOp = ARM_SHIFT_##OP; \
+ info->operandFormat |= ARM_OPERAND_REGISTER_3; \
+ if (opcode & 0x00000010) { \
+ info->op3.shifterReg = (opcode >> 8) & 0xF; \
+ ++info->iCycles; \
+ info->operandFormat |= ARM_OPERAND_SHIFT_REGISTER_3; \
+ } else { \
+ info->op3.shifterImm = (opcode >> 7) & 0x1F; \
+ info->operandFormat |= ARM_OPERAND_SHIFT_IMMEDIATE_3; \
+ }
+
+#define ADDR_MODE_1_LSL \
+ ADDR_MODE_1_SHIFT(LSL) \
+ if (!info->op3.shifterImm) { \
+ info->operandFormat &= ~ARM_OPERAND_SHIFT_IMMEDIATE_3; \
+ info->op3.shifterOp = ARM_SHIFT_NONE; \
+ }
#define ADDR_MODE_1_LSR ADDR_MODE_1_SHIFT(LSR)
#define ADDR_MODE_1_ASR ADDR_MODE_1_SHIFT(ASR)
-#define ADDR_MODE_1_ROR \
- ADDR_MODE_1_SHIFT(ROR) \
- if (!info->op3.shifterImm) { \
- info->op3.shifterOp = ARM_SHIFT_RRX; \
- }
-
-#define ADDR_MODE_1_IMM \
- int rotate = (opcode & 0x00000F00) >> 7; \
- int immediate = opcode & 0x000000FF; \
- info->op3.immediate = ROR(immediate, rotate); \
- info->operandFormat |= ARM_OPERAND_IMMEDIATE_3;
-
-#define ADDR_MODE_2_SHIFT(OP) \
- info->memory.format |= ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_SHIFTED_OFFSET; \
- info->memory.offset.shifterOp = ARM_SHIFT_ ## OP; \
- info->memory.offset.shifterImm = (opcode >> 7) & 0x1F; \
- info->memory.offset.reg = opcode & 0x0000000F;
-
-#define ADDR_MODE_2_LSL \
- ADDR_MODE_2_SHIFT(LSL) \
- if (!info->memory.offset.shifterImm) { \
- info->memory.format &= ~ARM_MEMORY_SHIFTED_OFFSET; \
- info->memory.offset.shifterOp = ARM_SHIFT_NONE; \
- }
-
-#define ADDR_MODE_2_LSR ADDR_MODE_2_SHIFT(LSR) \
- if (!info->memory.offset.shifterImm) { \
- info->memory.offset.shifterImm = 32; \
- }
-
-#define ADDR_MODE_2_ASR ADDR_MODE_2_SHIFT(ASR) \
- if (!info->memory.offset.shifterImm) { \
- info->memory.offset.shifterImm = 32; \
- }
-
-#define ADDR_MODE_2_ROR \
- ADDR_MODE_2_SHIFT(ROR) \
- if (!info->memory.offset.shifterImm) { \
- info->memory.offset.shifterOp = ARM_SHIFT_RRX; \
- }
-
-#define ADDR_MODE_2_IMM \
- info->memory.format |= ARM_MEMORY_IMMEDIATE_OFFSET; \
- info->memory.offset.immediate = opcode & 0x00000FFF;
-
-#define ADDR_MODE_3_REG \
- info->memory.format |= ARM_MEMORY_REGISTER_OFFSET; \
- info->memory.offset.reg = opcode & 0x0000000F;
-
-#define ADDR_MODE_3_IMM \
- info->memory.format |= ARM_MEMORY_IMMEDIATE_OFFSET; \
- info->memory.offset.immediate = (opcode & 0x0000000F) | ((opcode & 0x00000F00) >> 4);
-
-#define DEFINE_DECODER_ARM(NAME, MNEMONIC, BODY) \
- static void _ARMDecode ## NAME (uint32_t opcode, struct ARMInstructionInfo* info) { \
- UNUSED(opcode); \
- info->mnemonic = ARM_MN_ ## MNEMONIC; \
- BODY; \
- }
-
-#define DEFINE_ALU_DECODER_EX_ARM(NAME, MNEMONIC, S, SHIFTER, OTHER_AFFECTED, SKIPPED) \
- DEFINE_DECODER_ARM(NAME, MNEMONIC, \
- info->op1.reg = (opcode >> 12) & 0xF; \
- info->op2.reg = (opcode >> 16) & 0xF; \
- info->operandFormat = ARM_OPERAND_REGISTER_1 | \
- OTHER_AFFECTED | \
- ARM_OPERAND_REGISTER_2; \
- info->affectsCPSR = S; \
- SHIFTER; \
- if (SKIPPED == 1) { \
- info->op1 = info->op2; \
- info->op2 = info->op3; \
- info->operandFormat >>= 8; \
- } else if (SKIPPED == 2) { \
- info->op2 = info->op3; \
- info->operandFormat |= info->operandFormat >> 8; \
- info->operandFormat &= ~ARM_OPERAND_3; \
- } \
- if (info->op1.reg == ARM_PC) { \
- info->branchType = ARM_BRANCH_INDIRECT; \
- })
-
-#define DEFINE_ALU_DECODER_ARM(NAME, SKIPPED) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSL, NAME, 0, ADDR_MODE_1_LSL, ARM_OPERAND_AFFECTED_1, SKIPPED) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## S_LSL, NAME, 1, ADDR_MODE_1_LSL, ARM_OPERAND_AFFECTED_1, SKIPPED) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSR, NAME, 0, ADDR_MODE_1_LSR, ARM_OPERAND_AFFECTED_1, SKIPPED) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## S_LSR, NAME, 1, ADDR_MODE_1_LSR, ARM_OPERAND_AFFECTED_1, SKIPPED) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## _ASR, NAME, 0, ADDR_MODE_1_ASR, ARM_OPERAND_AFFECTED_1, SKIPPED) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## S_ASR, NAME, 1, ADDR_MODE_1_ASR, ARM_OPERAND_AFFECTED_1, SKIPPED) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## _ROR, NAME, 0, ADDR_MODE_1_ROR, ARM_OPERAND_AFFECTED_1, SKIPPED) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## S_ROR, NAME, 1, ADDR_MODE_1_ROR, ARM_OPERAND_AFFECTED_1, SKIPPED) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## I, NAME, 0, ADDR_MODE_1_IMM, ARM_OPERAND_AFFECTED_1, SKIPPED) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## SI, NAME, 1, ADDR_MODE_1_IMM, ARM_OPERAND_AFFECTED_1, SKIPPED)
-
-#define DEFINE_ALU_DECODER_S_ONLY_ARM(NAME) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSL, NAME, 1, ADDR_MODE_1_LSL, ARM_OPERAND_NONE, 1) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## _LSR, NAME, 1, ADDR_MODE_1_LSR, ARM_OPERAND_NONE, 1) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## _ASR, NAME, 1, ADDR_MODE_1_ASR, ARM_OPERAND_NONE, 1) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## _ROR, NAME, 1, ADDR_MODE_1_ROR, ARM_OPERAND_NONE, 1) \
- DEFINE_ALU_DECODER_EX_ARM(NAME ## I, NAME, 1, ADDR_MODE_1_IMM, ARM_OPERAND_NONE, 1)
-
-#define DEFINE_MULTIPLY_DECODER_EX_ARM(NAME, MNEMONIC, S, OTHER_AFFECTED) \
- DEFINE_DECODER_ARM(NAME, MNEMONIC, \
- info->op1.reg = (opcode >> 16) & 0xF; \
- info->op2.reg = opcode & 0xF; \
- info->op3.reg = (opcode >> 8) & 0xF; \
- info->op4.reg = (opcode >> 12) & 0xF; \
- info->operandFormat = ARM_OPERAND_REGISTER_1 | \
- ARM_OPERAND_AFFECTED_1 | \
- ARM_OPERAND_REGISTER_2 | \
- ARM_OPERAND_REGISTER_3 | \
- OTHER_AFFECTED; \
- info->affectsCPSR = S; \
- if (info->op1.reg == ARM_PC) { \
- info->branchType = ARM_BRANCH_INDIRECT; \
- })
-
-#define DEFINE_LONG_MULTIPLY_DECODER_EX_ARM(NAME, MNEMONIC, S) \
- DEFINE_DECODER_ARM(NAME, MNEMONIC, \
- info->op1.reg = (opcode >> 12) & 0xF; \
- info->op2.reg = (opcode >> 16) & 0xF; \
- info->op3.reg = opcode & 0xF; \
- info->op4.reg = (opcode >> 8) & 0xF; \
- info->operandFormat = ARM_OPERAND_REGISTER_1 | \
- ARM_OPERAND_AFFECTED_1 | \
- ARM_OPERAND_REGISTER_2 | \
- ARM_OPERAND_AFFECTED_2 | \
- ARM_OPERAND_REGISTER_3 | \
- ARM_OPERAND_REGISTER_4; \
- info->affectsCPSR = S; \
- if (info->op1.reg == ARM_PC) { \
- info->branchType = ARM_BRANCH_INDIRECT; \
- })
-
-#define DEFINE_MULTIPLY_DECODER_ARM(NAME, OTHER_AFFECTED) \
- DEFINE_MULTIPLY_DECODER_EX_ARM(NAME, NAME, 0, OTHER_AFFECTED) \
- DEFINE_MULTIPLY_DECODER_EX_ARM(NAME ## S, NAME, 1, OTHER_AFFECTED)
-
-#define DEFINE_LONG_MULTIPLY_DECODER_ARM(NAME) \
- DEFINE_LONG_MULTIPLY_DECODER_EX_ARM(NAME, NAME, 0) \
- DEFINE_LONG_MULTIPLY_DECODER_EX_ARM(NAME ## S, NAME, 1)
-
-#define DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME, MNEMONIC, ADDRESSING_MODE, ADDRESSING_DECODING, CYCLES, TYPE) \
- DEFINE_DECODER_ARM(NAME, MNEMONIC, \
- info->op1.reg = (opcode >> 12) & 0xF; \
- info->memory.baseReg = (opcode >> 16) & 0xF; \
- info->memory.width = TYPE; \
- info->operandFormat = ARM_OPERAND_REGISTER_1 | \
- ARM_OPERAND_AFFECTED_1 | /* TODO: Remove this for STR */ \
- ARM_OPERAND_MEMORY_2; \
- info->memory.format = ARM_MEMORY_REGISTER_BASE | ADDRESSING_MODE; \
- ADDRESSING_DECODING; \
- CYCLES;)
-
-#define DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME, MNEMONIC, ADDRESSING_MODE, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME, MNEMONIC, \
- ARM_MEMORY_POST_INCREMENT | \
- ARM_MEMORY_WRITEBACK | \
- ARM_MEMORY_OFFSET_SUBTRACT, \
- ADDRESSING_MODE, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## U, MNEMONIC, \
- ARM_MEMORY_POST_INCREMENT | \
- ARM_MEMORY_WRITEBACK, \
- ADDRESSING_MODE, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## P, MNEMONIC, \
- ARM_MEMORY_OFFSET_SUBTRACT, \
- ADDRESSING_MODE, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## PW, MNEMONIC, \
- ARM_MEMORY_PRE_INCREMENT | \
- ARM_MEMORY_WRITEBACK | \
- ARM_MEMORY_OFFSET_SUBTRACT, \
- ADDRESSING_MODE, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## PU, MNEMONIC, \
- 0, \
- ADDRESSING_MODE, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## PUW, MNEMONIC, \
- ARM_MEMORY_WRITEBACK, \
- ADDRESSING_MODE, CYCLES, TYPE)
-
-#define DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(NAME, MNEMONIC, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _LSL_, MNEMONIC, ADDR_MODE_2_LSL, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _LSR_, MNEMONIC, ADDR_MODE_2_LSR, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _ASR_, MNEMONIC, ADDR_MODE_2_ASR, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## _ROR_, MNEMONIC, ADDR_MODE_2_ROR, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## I, MNEMONIC, ADDR_MODE_2_IMM, CYCLES, TYPE)
-
-#define DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(NAME, MNEMONIC, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME, MNEMONIC, ADDR_MODE_3_REG, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME ## I, MNEMONIC, ADDR_MODE_3_IMM, CYCLES, TYPE)
-
-#define DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME, MNEMONIC, ADDRESSING_MODE, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME, MNEMONIC, \
- ARM_MEMORY_POST_INCREMENT | \
- ARM_MEMORY_WRITEBACK | \
- ARM_MEMORY_OFFSET_SUBTRACT, \
- ADDRESSING_MODE, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME ## U, MNEMONIC, \
- ARM_MEMORY_POST_INCREMENT | \
- ARM_MEMORY_WRITEBACK, \
- ADDRESSING_MODE, CYCLES, TYPE)
-
-#define DEFINE_LOAD_STORE_T_DECODER_ARM(NAME, MNEMONIC, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _LSL_, MNEMONIC, ADDR_MODE_2_LSL, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _LSR_, MNEMONIC, ADDR_MODE_2_LSR, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _ASR_, MNEMONIC, ADDR_MODE_2_ASR, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## _ROR_, MNEMONIC, ADDR_MODE_2_ROR, CYCLES, TYPE) \
- DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME ## I, MNEMONIC, ADDR_MODE_2_IMM, CYCLES, TYPE)
-
-#define DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME, MNEMONIC, DIRECTION, WRITEBACK) \
- DEFINE_DECODER_ARM(NAME, MNEMONIC, \
- info->memory.baseReg = (opcode >> 16) & 0xF; \
- info->op1.immediate = opcode & 0x0000FFFF; \
- if (info->op1.immediate & (1 << ARM_PC)) { \
- info->branchType = ARM_BRANCH_INDIRECT; \
- } \
- info->operandFormat = ARM_OPERAND_MEMORY_1; \
- info->memory.format = ARM_MEMORY_REGISTER_BASE | \
- WRITEBACK | \
- ARM_MEMORY_ ## DIRECTION;)
-
-
-#define DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(NAME) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DA, NAME, DECREMENT_AFTER, 0) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DAW, NAME, DECREMENT_AFTER, ARM_MEMORY_WRITEBACK) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DB, NAME, DECREMENT_BEFORE, 0) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## DBW, NAME, DECREMENT_BEFORE, ARM_MEMORY_WRITEBACK) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IA, NAME, INCREMENT_AFTER, 0) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IAW, NAME, INCREMENT_AFTER, ARM_MEMORY_WRITEBACK) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IB, NAME, INCREMENT_BEFORE, 0) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## IBW, NAME, INCREMENT_BEFORE, ARM_MEMORY_WRITEBACK) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDA, NAME, DECREMENT_AFTER, ARM_MEMORY_SPSR_SWAP) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDAW, NAME, DECREMENT_AFTER, ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDB, NAME, DECREMENT_BEFORE, ARM_MEMORY_SPSR_SWAP) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SDBW, NAME, DECREMENT_BEFORE, ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIA, NAME, INCREMENT_AFTER, ARM_MEMORY_SPSR_SWAP) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIAW, NAME, INCREMENT_AFTER, ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIB, NAME, INCREMENT_BEFORE, ARM_MEMORY_SPSR_SWAP) \
- DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME ## SIBW, NAME, INCREMENT_BEFORE, ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP)
-
-#define DEFINE_SWP_DECODER_ARM(NAME, TYPE) \
- DEFINE_DECODER_ARM(NAME, SWP, \
- info->memory.baseReg = (opcode >> 16) & 0xF; \
- info->op1.reg = (opcode >> 12) & 0xF; \
- info->op2.reg = opcode & 0xF; \
- info->operandFormat = ARM_OPERAND_REGISTER_1 | \
- ARM_OPERAND_AFFECTED_1 | \
- ARM_OPERAND_REGISTER_2 | \
- ARM_OPERAND_MEMORY_3; \
- info->memory.format = ARM_MEMORY_REGISTER_BASE; \
- info->memory.width = TYPE;)
+#define ADDR_MODE_1_ROR \
+ ADDR_MODE_1_SHIFT(ROR) \
+ if (!info->op3.shifterImm) { \
+ info->op3.shifterOp = ARM_SHIFT_RRX; \
+ }
+
+#define ADDR_MODE_1_IMM \
+ int rotate = (opcode & 0x00000F00) >> 7; \
+ int immediate = opcode & 0x000000FF; \
+ info->op3.immediate = ROR(immediate, rotate); \
+ info->operandFormat |= ARM_OPERAND_IMMEDIATE_3;
+
+#define ADDR_MODE_2_SHIFT(OP) \
+ info->memory.format |= \
+ ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_SHIFTED_OFFSET; \
+ info->memory.offset.shifterOp = ARM_SHIFT_##OP; \
+ info->memory.offset.shifterImm = (opcode >> 7) & 0x1F; \
+ info->memory.offset.reg = opcode & 0x0000000F;
+
+#define ADDR_MODE_2_LSL \
+ ADDR_MODE_2_SHIFT(LSL) \
+ if (!info->memory.offset.shifterImm) { \
+ info->memory.format &= ~ARM_MEMORY_SHIFTED_OFFSET; \
+ info->memory.offset.shifterOp = ARM_SHIFT_NONE; \
+ }
+
+#define ADDR_MODE_2_LSR \
+ ADDR_MODE_2_SHIFT(LSR) \
+ if (!info->memory.offset.shifterImm) { \
+ info->memory.offset.shifterImm = 32; \
+ }
+
+#define ADDR_MODE_2_ASR \
+ ADDR_MODE_2_SHIFT(ASR) \
+ if (!info->memory.offset.shifterImm) { \
+ info->memory.offset.shifterImm = 32; \
+ }
+
+#define ADDR_MODE_2_ROR \
+ ADDR_MODE_2_SHIFT(ROR) \
+ if (!info->memory.offset.shifterImm) { \
+ info->memory.offset.shifterOp = ARM_SHIFT_RRX; \
+ }
+
+#define ADDR_MODE_2_IMM \
+ info->memory.format |= ARM_MEMORY_IMMEDIATE_OFFSET; \
+ info->memory.offset.immediate = opcode & 0x00000FFF;
+
+#define ADDR_MODE_3_REG \
+ info->memory.format |= ARM_MEMORY_REGISTER_OFFSET; \
+ info->memory.offset.reg = opcode & 0x0000000F;
+
+#define ADDR_MODE_3_IMM \
+ info->memory.format |= ARM_MEMORY_IMMEDIATE_OFFSET; \
+ info->memory.offset.immediate = \
+ (opcode & 0x0000000F) | ((opcode & 0x00000F00) >> 4);
+
+#define DEFINE_DECODER_ARM(NAME, MNEMONIC, BODY) \
+ static void _ARMDecode##NAME(uint32_t opcode, \
+ struct ARMInstructionInfo* info) { \
+ UNUSED(opcode); \
+ info->mnemonic = ARM_MN_##MNEMONIC; \
+ BODY; \
+ }
+
+#define DEFINE_ALU_DECODER_EX_ARM(NAME, MNEMONIC, S, SHIFTER, OTHER_AFFECTED, \
+ SKIPPED) \
+ DEFINE_DECODER_ARM( \
+ NAME, MNEMONIC, info->op1.reg = (opcode >> 12) & 0xF; \
+ info->op2.reg = (opcode >> 16) & 0xF; \
+ info->operandFormat = \
+ ARM_OPERAND_REGISTER_1 | OTHER_AFFECTED | ARM_OPERAND_REGISTER_2; \
+ info->affectsCPSR = S; SHIFTER; if (SKIPPED == 1) { \
+ info->op1 = info->op2; \
+ info->op2 = info->op3; \
+ info->operandFormat >>= 8; \
+ } else if (SKIPPED == 2) { \
+ info->op2 = info->op3; \
+ info->operandFormat |= info->operandFormat >> 8; \
+ info->operandFormat &= ~ARM_OPERAND_3; \
+ } if (info->op1.reg == ARM_PC) { \
+ info->branchType = ARM_BRANCH_INDIRECT; \
+ })
+
+#define DEFINE_ALU_DECODER_ARM(NAME, SKIPPED) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##_LSL, NAME, 0, ADDR_MODE_1_LSL, \
+ ARM_OPERAND_AFFECTED_1, SKIPPED) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##S_LSL, NAME, 1, ADDR_MODE_1_LSL, \
+ ARM_OPERAND_AFFECTED_1, SKIPPED) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##_LSR, NAME, 0, ADDR_MODE_1_LSR, \
+ ARM_OPERAND_AFFECTED_1, SKIPPED) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##S_LSR, NAME, 1, ADDR_MODE_1_LSR, \
+ ARM_OPERAND_AFFECTED_1, SKIPPED) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##_ASR, NAME, 0, ADDR_MODE_1_ASR, \
+ ARM_OPERAND_AFFECTED_1, SKIPPED) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##S_ASR, NAME, 1, ADDR_MODE_1_ASR, \
+ ARM_OPERAND_AFFECTED_1, SKIPPED) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##_ROR, NAME, 0, ADDR_MODE_1_ROR, \
+ ARM_OPERAND_AFFECTED_1, SKIPPED) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##S_ROR, NAME, 1, ADDR_MODE_1_ROR, \
+ ARM_OPERAND_AFFECTED_1, SKIPPED) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##I, NAME, 0, ADDR_MODE_1_IMM, \
+ ARM_OPERAND_AFFECTED_1, SKIPPED) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##SI, NAME, 1, ADDR_MODE_1_IMM, \
+ ARM_OPERAND_AFFECTED_1, SKIPPED)
+
+#define DEFINE_ALU_DECODER_S_ONLY_ARM(NAME) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##_LSL, NAME, 1, ADDR_MODE_1_LSL, \
+ ARM_OPERAND_NONE, 1) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##_LSR, NAME, 1, ADDR_MODE_1_LSR, \
+ ARM_OPERAND_NONE, 1) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##_ASR, NAME, 1, ADDR_MODE_1_ASR, \
+ ARM_OPERAND_NONE, 1) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##_ROR, NAME, 1, ADDR_MODE_1_ROR, \
+ ARM_OPERAND_NONE, 1) \
+ DEFINE_ALU_DECODER_EX_ARM(NAME##I, NAME, 1, ADDR_MODE_1_IMM, \
+ ARM_OPERAND_NONE, 1)
+
+#define DEFINE_MULTIPLY_DECODER_EX_ARM(NAME, MNEMONIC, S, OTHER_AFFECTED) \
+ DEFINE_DECODER_ARM( \
+ NAME, MNEMONIC, info->op1.reg = (opcode >> 16) & 0xF; \
+ info->op2.reg = opcode & 0xF; info->op3.reg = (opcode >> 8) & 0xF; \
+ info->op4.reg = (opcode >> 12) & 0xF; \
+ info->operandFormat = ARM_OPERAND_REGISTER_1 | ARM_OPERAND_AFFECTED_1 | \
+ ARM_OPERAND_REGISTER_2 | ARM_OPERAND_REGISTER_3 | \
+ OTHER_AFFECTED; \
+ info->affectsCPSR = S; if (info->op1.reg == ARM_PC) { \
+ info->branchType = ARM_BRANCH_INDIRECT; \
+ })
+
+#define DEFINE_LONG_MULTIPLY_DECODER_EX_ARM(NAME, MNEMONIC, S) \
+ DEFINE_DECODER_ARM( \
+ NAME, MNEMONIC, info->op1.reg = (opcode >> 12) & 0xF; \
+ info->op2.reg = (opcode >> 16) & 0xF; info->op3.reg = opcode & 0xF; \
+ info->op4.reg = (opcode >> 8) & 0xF; \
+ info->operandFormat = ARM_OPERAND_REGISTER_1 | ARM_OPERAND_AFFECTED_1 | \
+ ARM_OPERAND_REGISTER_2 | ARM_OPERAND_AFFECTED_2 | \
+ ARM_OPERAND_REGISTER_3 | ARM_OPERAND_REGISTER_4; \
+ info->affectsCPSR = S; if (info->op1.reg == ARM_PC) { \
+ info->branchType = ARM_BRANCH_INDIRECT; \
+ })
+
+#define DEFINE_MULTIPLY_DECODER_ARM(NAME, OTHER_AFFECTED) \
+ DEFINE_MULTIPLY_DECODER_EX_ARM(NAME, NAME, 0, OTHER_AFFECTED) \
+ DEFINE_MULTIPLY_DECODER_EX_ARM(NAME##S, NAME, 1, OTHER_AFFECTED)
+
+#define DEFINE_LONG_MULTIPLY_DECODER_ARM(NAME) \
+ DEFINE_LONG_MULTIPLY_DECODER_EX_ARM(NAME, NAME, 0) \
+ DEFINE_LONG_MULTIPLY_DECODER_EX_ARM(NAME##S, NAME, 1)
+
+#define DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME, MNEMONIC, ADDRESSING_MODE, \
+ ADDRESSING_DECODING, CYCLES, TYPE) \
+ DEFINE_DECODER_ARM( \
+ NAME, MNEMONIC, info->op1.reg = (opcode >> 12) & 0xF; \
+ info->memory.baseReg = (opcode >> 16) & 0xF; info->memory.width = TYPE; \
+ info->operandFormat = \
+ ARM_OPERAND_REGISTER_1 | \
+ ARM_OPERAND_AFFECTED_1 | /* TODO: Remove this for STR */ \
+ ARM_OPERAND_MEMORY_2; \
+ info->memory.format = ARM_MEMORY_REGISTER_BASE | ADDRESSING_MODE; \
+ ADDRESSING_DECODING; CYCLES;)
+
+#define DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME, MNEMONIC, ADDRESSING_MODE, \
+ CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME, MNEMONIC, \
+ ARM_MEMORY_POST_INCREMENT | \
+ ARM_MEMORY_WRITEBACK | \
+ ARM_MEMORY_OFFSET_SUBTRACT, \
+ ADDRESSING_MODE, CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_DECODER_EX_ARM( \
+ NAME##U, MNEMONIC, ARM_MEMORY_POST_INCREMENT | ARM_MEMORY_WRITEBACK, \
+ ADDRESSING_MODE, CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME##P, MNEMONIC, \
+ ARM_MEMORY_OFFSET_SUBTRACT, \
+ ADDRESSING_MODE, CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME##PW, MNEMONIC, \
+ ARM_MEMORY_PRE_INCREMENT | \
+ ARM_MEMORY_WRITEBACK | \
+ ARM_MEMORY_OFFSET_SUBTRACT, \
+ ADDRESSING_MODE, CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME##PU, MNEMONIC, 0, ADDRESSING_MODE, \
+ CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME##PUW, MNEMONIC, ARM_MEMORY_WRITEBACK, \
+ ADDRESSING_MODE, CYCLES, TYPE)
+
+#define DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(NAME, MNEMONIC, CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME##_LSL_, MNEMONIC, ADDR_MODE_2_LSL, \
+ CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME##_LSR_, MNEMONIC, ADDR_MODE_2_LSR, \
+ CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME##_ASR_, MNEMONIC, ADDR_MODE_2_ASR, \
+ CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME##_ROR_, MNEMONIC, ADDR_MODE_2_ROR, \
+ CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME##I, MNEMONIC, ADDR_MODE_2_IMM, \
+ CYCLES, TYPE)
+
+#define DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(NAME, MNEMONIC, CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME, MNEMONIC, ADDR_MODE_3_REG, CYCLES, \
+ TYPE) \
+ DEFINE_LOAD_STORE_DECODER_SET_ARM(NAME##I, MNEMONIC, ADDR_MODE_3_IMM, \
+ CYCLES, TYPE)
+
+#define DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME, MNEMONIC, ADDRESSING_MODE, \
+ CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_DECODER_EX_ARM(NAME, MNEMONIC, \
+ ARM_MEMORY_POST_INCREMENT | \
+ ARM_MEMORY_WRITEBACK | \
+ ARM_MEMORY_OFFSET_SUBTRACT, \
+ ADDRESSING_MODE, CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_DECODER_EX_ARM( \
+ NAME##U, MNEMONIC, ARM_MEMORY_POST_INCREMENT | ARM_MEMORY_WRITEBACK, \
+ ADDRESSING_MODE, CYCLES, TYPE)
+
+#define DEFINE_LOAD_STORE_T_DECODER_ARM(NAME, MNEMONIC, CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME##_LSL_, MNEMONIC, ADDR_MODE_2_LSL, \
+ CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME##_LSR_, MNEMONIC, ADDR_MODE_2_LSR, \
+ CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME##_ASR_, MNEMONIC, ADDR_MODE_2_ASR, \
+ CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME##_ROR_, MNEMONIC, ADDR_MODE_2_ROR, \
+ CYCLES, TYPE) \
+ DEFINE_LOAD_STORE_T_DECODER_SET_ARM(NAME##I, MNEMONIC, ADDR_MODE_2_IMM, \
+ CYCLES, TYPE)
+
+#define DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME, MNEMONIC, DIRECTION, \
+ WRITEBACK) \
+ DEFINE_DECODER_ARM( \
+ NAME, MNEMONIC, info->memory.baseReg = (opcode >> 16) & 0xF; \
+ info->op1.immediate = opcode & 0x0000FFFF; \
+ if (info->op1.immediate & (1 << ARM_PC)) { \
+ info->branchType = ARM_BRANCH_INDIRECT; \
+ } info->operandFormat = ARM_OPERAND_MEMORY_1; \
+ info->memory.format = \
+ ARM_MEMORY_REGISTER_BASE | WRITEBACK | ARM_MEMORY_##DIRECTION;)
+
+#define DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(NAME) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME##DA, NAME, DECREMENT_AFTER, \
+ 0) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME##DAW, NAME, DECREMENT_AFTER, \
+ ARM_MEMORY_WRITEBACK) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME##DB, NAME, DECREMENT_BEFORE, \
+ 0) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME##DBW, NAME, DECREMENT_BEFORE, \
+ ARM_MEMORY_WRITEBACK) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME##IA, NAME, INCREMENT_AFTER, \
+ 0) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME##IAW, NAME, INCREMENT_AFTER, \
+ ARM_MEMORY_WRITEBACK) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME##IB, NAME, INCREMENT_BEFORE, \
+ 0) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME##IBW, NAME, INCREMENT_BEFORE, \
+ ARM_MEMORY_WRITEBACK) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME##SDA, NAME, DECREMENT_AFTER, \
+ ARM_MEMORY_SPSR_SWAP) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME##SDAW, NAME, DECREMENT_AFTER, \
+ ARM_MEMORY_WRITEBACK | \
+ ARM_MEMORY_SPSR_SWAP) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME##SDB, NAME, DECREMENT_BEFORE, \
+ ARM_MEMORY_SPSR_SWAP) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM( \
+ NAME##SDBW, NAME, DECREMENT_BEFORE, \
+ ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME##SIA, NAME, INCREMENT_AFTER, \
+ ARM_MEMORY_SPSR_SWAP) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME##SIAW, NAME, INCREMENT_AFTER, \
+ ARM_MEMORY_WRITEBACK | \
+ ARM_MEMORY_SPSR_SWAP) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM(NAME##SIB, NAME, INCREMENT_BEFORE, \
+ ARM_MEMORY_SPSR_SWAP) \
+ DEFINE_LOAD_STORE_MULTIPLE_DECODER_EX_ARM( \
+ NAME##SIBW, NAME, INCREMENT_BEFORE, \
+ ARM_MEMORY_WRITEBACK | ARM_MEMORY_SPSR_SWAP)
+
+#define DEFINE_SWP_DECODER_ARM(NAME, TYPE) \
+ DEFINE_DECODER_ARM( \
+ NAME, SWP, info->memory.baseReg = (opcode >> 16) & 0xF; \
+ info->op1.reg = (opcode >> 12) & 0xF; info->op2.reg = opcode & 0xF; \
+ info->operandFormat = ARM_OPERAND_REGISTER_1 | ARM_OPERAND_AFFECTED_1 | \
+ ARM_OPERAND_REGISTER_2 | ARM_OPERAND_MEMORY_3; \
+ info->memory.format = ARM_MEMORY_REGISTER_BASE; \
+ info->memory.width = TYPE;)
DEFINE_ALU_DECODER_ARM(ADD, 0)
DEFINE_ALU_DECODER_ARM(ADC, 0)
DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(LDR, LDR, LOAD_CYCLES, ARM_ACCESS_WORD)
DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(LDRB, LDR, LOAD_CYCLES, ARM_ACCESS_BYTE)
-DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRH, LDR, LOAD_CYCLES, ARM_ACCESS_HALFWORD)
-DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRSB, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_BYTE)
-DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRSH, LDR, LOAD_CYCLES, ARM_ACCESS_SIGNED_HALFWORD)
+DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRH, LDR, LOAD_CYCLES,
+ ARM_ACCESS_HALFWORD)
+DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRSB, LDR, LOAD_CYCLES,
+ ARM_ACCESS_SIGNED_BYTE)
+DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(LDRSH, LDR, LOAD_CYCLES,
+ ARM_ACCESS_SIGNED_HALFWORD)
DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(STR, STR, STORE_CYCLES, ARM_ACCESS_WORD)
DEFINE_LOAD_STORE_MODE_2_DECODER_ARM(STRB, STR, STORE_CYCLES, ARM_ACCESS_BYTE)
-DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(STRH, STR, STORE_CYCLES, ARM_ACCESS_HALFWORD)
-
-DEFINE_LOAD_STORE_T_DECODER_ARM(LDRBT, LDR, LOAD_CYCLES, ARM_ACCESS_TRANSLATED_BYTE)
-DEFINE_LOAD_STORE_T_DECODER_ARM(LDRT, LDR, LOAD_CYCLES, ARM_ACCESS_TRANSLATED_WORD)
-DEFINE_LOAD_STORE_T_DECODER_ARM(STRBT, STR, STORE_CYCLES, ARM_ACCESS_TRANSLATED_BYTE)
-DEFINE_LOAD_STORE_T_DECODER_ARM(STRT, STR, STORE_CYCLES, ARM_ACCESS_TRANSLATED_WORD)
+DEFINE_LOAD_STORE_MODE_3_DECODER_ARM(STRH, STR, STORE_CYCLES,
+ ARM_ACCESS_HALFWORD)
+
+DEFINE_LOAD_STORE_T_DECODER_ARM(LDRBT, LDR, LOAD_CYCLES,
+ ARM_ACCESS_TRANSLATED_BYTE)
+DEFINE_LOAD_STORE_T_DECODER_ARM(LDRT, LDR, LOAD_CYCLES,
+ ARM_ACCESS_TRANSLATED_WORD)
+DEFINE_LOAD_STORE_T_DECODER_ARM(STRBT, STR, STORE_CYCLES,
+ ARM_ACCESS_TRANSLATED_BYTE)
+DEFINE_LOAD_STORE_T_DECODER_ARM(STRT, STR, STORE_CYCLES,
+ ARM_ACCESS_TRANSLATED_WORD)
DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(LDM)
DEFINE_LOAD_STORE_MULTIPLE_DECODER_ARM(STM)
// Begin branch definitions
-DEFINE_DECODER_ARM(B, B,
- int32_t offset = opcode << 8;
- info->op1.immediate = offset >> 6;
- info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
- info->branchType = ARM_BRANCH;)
+DEFINE_DECODER_ARM(B, B, int32_t offset = opcode << 8;
+ info->op1.immediate = offset >> 6;
+ info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
+ info->branchType = ARM_BRANCH;)
-DEFINE_DECODER_ARM(BL, BL,
- int32_t offset = opcode << 8;
- info->op1.immediate = offset >> 6;
- info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
- info->branchType = ARM_BRANCH_LINKED;)
+DEFINE_DECODER_ARM(BL, BL, int32_t offset = opcode << 8;
+ info->op1.immediate = offset >> 6;
+ info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
+ info->branchType = ARM_BRANCH_LINKED;)
-DEFINE_DECODER_ARM(BX, BX,
- info->op1.reg = opcode & 0x0000000F;
- info->operandFormat = ARM_OPERAND_REGISTER_1;
- info->branchType = ARM_BRANCH_INDIRECT;)
+DEFINE_DECODER_ARM(BX, BX, info->op1.reg = opcode & 0x0000000F;
+ info->operandFormat = ARM_OPERAND_REGISTER_1;
+ info->branchType = ARM_BRANCH_INDIRECT;)
// End branch definitions
// Begin miscellaneous definitions
-DEFINE_DECODER_ARM(BKPT, BKPT,
- info->operandFormat = ARM_OPERAND_NONE;
- info->traps = 1;) // Not strictly in ARMv4T, but here for convenience
+DEFINE_DECODER_ARM(
+ BKPT, BKPT,
+ info->operandFormat = ARM_OPERAND_NONE;
+ info->traps = 1;) // Not strictly in ARMv4T, but here for convenience
DEFINE_DECODER_ARM(ILL, ILL,
- info->operandFormat = ARM_OPERAND_NONE;
- info->traps = 1;) // Illegal opcode
-
-DEFINE_DECODER_ARM(MSR, MSR,
- info->affectsCPSR = 1;
- info->op1.reg = ARM_CPSR;
- info->op1.psrBits = (opcode >> 16) & ARM_PSR_MASK;
- info->op2.reg = opcode & 0x0000000F;
- info->operandFormat = ARM_OPERAND_REGISTER_1 |
- ARM_OPERAND_AFFECTED_1 |
- ARM_OPERAND_REGISTER_2;)
-
-DEFINE_DECODER_ARM(MSRR, MSR,
- info->op1.reg = ARM_SPSR;
- info->op1.psrBits = (opcode >> 16) & ARM_PSR_MASK;
- info->op2.reg = opcode & 0x0000000F;
- info->operandFormat = ARM_OPERAND_REGISTER_1 |
- ARM_OPERAND_AFFECTED_1 |
- ARM_OPERAND_REGISTER_2;)
-
-DEFINE_DECODER_ARM(MRS, MRS,
- info->affectsCPSR = 1;
- info->op1.reg = (opcode >> 12) & 0xF;
- info->op2.reg = ARM_CPSR;
- info->op2.psrBits = 0;
- info->operandFormat = ARM_OPERAND_REGISTER_1 |
- ARM_OPERAND_AFFECTED_1 |
- ARM_OPERAND_REGISTER_2;)
-
-DEFINE_DECODER_ARM(MRSR, MRS,
- info->op1.reg = (opcode >> 12) & 0xF;
- info->op2.reg = ARM_SPSR;
- info->op2.psrBits = 0;
- info->operandFormat = ARM_OPERAND_REGISTER_1 |
- ARM_OPERAND_AFFECTED_1 |
- ARM_OPERAND_REGISTER_2;)
-
-DEFINE_DECODER_ARM(MSRI, MSR,
- int rotate = (opcode & 0x00000F00) >> 7;
- int32_t operand = ROR(opcode & 0x000000FF, rotate);
- info->affectsCPSR = 1;
- info->op1.reg = ARM_CPSR;
- info->op1.psrBits = (opcode >> 16) & ARM_PSR_MASK;
- info->op2.immediate = operand;
- info->operandFormat = ARM_OPERAND_REGISTER_1 |
- ARM_OPERAND_AFFECTED_1 |
- ARM_OPERAND_IMMEDIATE_2;)
-
-DEFINE_DECODER_ARM(MSRRI, MSR,
- int rotate = (opcode & 0x00000F00) >> 7;
- int32_t operand = ROR(opcode & 0x000000FF, rotate);
- info->op1.reg = ARM_SPSR;
- info->op1.psrBits = (opcode >> 16) & ARM_PSR_MASK;
- info->op2.immediate = operand;
- info->operandFormat = ARM_OPERAND_REGISTER_1 |
- ARM_OPERAND_AFFECTED_1 |
- ARM_OPERAND_IMMEDIATE_2;)
-
-DEFINE_DECODER_ARM(SWI, SWI,
- info->op1.immediate = opcode & 0xFFFFFF;
- info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
- info->traps = 1;)
+ info->operandFormat = ARM_OPERAND_NONE;
+ info->traps = 1;) // Illegal opcode
+
+DEFINE_DECODER_ARM(MSR, MSR, info->affectsCPSR = 1; info->op1.reg = ARM_CPSR;
+ info->op1.psrBits = (opcode >> 16) & ARM_PSR_MASK;
+ info->op2.reg = opcode & 0x0000000F;
+ info->operandFormat = ARM_OPERAND_REGISTER_1 |
+ ARM_OPERAND_AFFECTED_1 |
+ ARM_OPERAND_REGISTER_2;)
+
+DEFINE_DECODER_ARM(MSRR, MSR, info->op1.reg = ARM_SPSR;
+ info->op1.psrBits = (opcode >> 16) & ARM_PSR_MASK;
+ info->op2.reg = opcode & 0x0000000F;
+ info->operandFormat = ARM_OPERAND_REGISTER_1 |
+ ARM_OPERAND_AFFECTED_1 |
+ ARM_OPERAND_REGISTER_2;)
+
+DEFINE_DECODER_ARM(MRS, MRS, info->affectsCPSR = 1;
+ info->op1.reg = (opcode >> 12) & 0xF;
+ info->op2.reg = ARM_CPSR; info->op2.psrBits = 0;
+ info->operandFormat = ARM_OPERAND_REGISTER_1 |
+ ARM_OPERAND_AFFECTED_1 |
+ ARM_OPERAND_REGISTER_2;)
+
+DEFINE_DECODER_ARM(MRSR, MRS, info->op1.reg = (opcode >> 12) & 0xF;
+ info->op2.reg = ARM_SPSR; info->op2.psrBits = 0;
+ info->operandFormat = ARM_OPERAND_REGISTER_1 |
+ ARM_OPERAND_AFFECTED_1 |
+ ARM_OPERAND_REGISTER_2;)
+
+DEFINE_DECODER_ARM(MSRI, MSR, int rotate = (opcode & 0x00000F00) >> 7;
+ int32_t operand = ROR(opcode & 0x000000FF, rotate);
+ info->affectsCPSR = 1; info->op1.reg = ARM_CPSR;
+ info->op1.psrBits = (opcode >> 16) & ARM_PSR_MASK;
+ info->op2.immediate = operand;
+ info->operandFormat = ARM_OPERAND_REGISTER_1 |
+ ARM_OPERAND_AFFECTED_1 |
+ ARM_OPERAND_IMMEDIATE_2;)
+
+DEFINE_DECODER_ARM(MSRRI, MSR, int rotate = (opcode & 0x00000F00) >> 7;
+ int32_t operand = ROR(opcode & 0x000000FF, rotate);
+ info->op1.reg = ARM_SPSR;
+ info->op1.psrBits = (opcode >> 16) & ARM_PSR_MASK;
+ info->op2.immediate = operand;
+ info->operandFormat = ARM_OPERAND_REGISTER_1 |
+ ARM_OPERAND_AFFECTED_1 |
+ ARM_OPERAND_IMMEDIATE_2;)
+
+DEFINE_DECODER_ARM(SWI, SWI, info->op1.immediate = opcode & 0xFFFFFF;
+ info->operandFormat = ARM_OPERAND_IMMEDIATE_1;
+ info->traps = 1;)
typedef void (*ARMDecoder)(uint32_t opcode, struct ARMInstructionInfo* info);
static const ARMDecoder _armDecoderTable[0x1000] = {
- DECLARE_ARM_EMITTER_BLOCK(_ARMDecode)
-};
+ DECLARE_ARM_EMITTER_BLOCK(_ARMDecode)};
void ARMDecodeARM(uint32_t opcode, struct ARMInstructionInfo* info) {
- memset(info, 0, sizeof(*info));
- info->opcode = opcode;
- info->branchType = ARM_BRANCH_NONE;
- info->condition = opcode >> 28;
- info->sInstructionCycles = 1;
- ARMDecoder decoder = _armDecoderTable[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x00F)];
- decoder(opcode, info);
+ memset(info, 0, sizeof(*info));
+ info->opcode = opcode;
+ info->branchType = ARM_BRANCH_NONE;
+ info->condition = opcode >> 28;
+ info->sInstructionCycles = 1;
+ ARMDecoder decoder =
+ _armDecoderTable[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x00F)];
+ decoder(opcode, info);
}
#include <stdio.h>
#include <string.h>
-#define LOAD_CYCLES \
- info->iCycles = 1; \
- info->nDataCycles = 1;
+#define LOAD_CYCLES \
+ info->iCycles = 1; \
+ info->nDataCycles = 1;
-#define STORE_CYCLES \
- info->sInstructionCycles = 0; \
- info->nInstructionCycles = 1; \
- info->nDataCycles = 1;
+#define STORE_CYCLES \
+ info->sInstructionCycles = 0; \
+ info->nInstructionCycles = 1; \
+ info->nDataCycles = 1;
#endif
#include "decoder-inlines.h"
-#define ADVANCE(AMOUNT) \
- if (AMOUNT >= blen) { \
- buffer[blen - 1] = '\0'; \
- return total; \
- } \
- total += AMOUNT; \
- buffer += AMOUNT; \
- blen -= AMOUNT;
+#define ADVANCE(AMOUNT) \
+ if (AMOUNT >= blen) { \
+ buffer[blen - 1] = '\0'; \
+ return total; \
+ } \
+ total += AMOUNT; \
+ buffer += AMOUNT; \
+ blen -= AMOUNT;
static int _decodeRegister(int reg, char* buffer, int blen);
static int _decodeRegisterList(int list, char* buffer, int blen);
static int _decodePSR(int bits, char* buffer, int blen);
-static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen);
-static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen);
-static int _decodeShift(union ARMOperand operand, bool reg, char* buffer, int blen);
+static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer,
+ int blen);
+static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer,
+ int blen);
+static int _decodeShift(union ARMOperand operand, bool reg, char* buffer,
+ int blen);
-static const char* _armConditions[] = {
- "eq",
- "ne",
- "cs",
- "cc",
- "mi",
- "pl",
- "vs",
- "vc",
- "hi",
- "ls",
- "ge",
- "lt",
- "gt",
- "le",
- "al",
- "nv"
-};
+static const char* _armConditions[] = {"eq", "ne", "cs", "cc", "mi", "pl",
+ "vs", "vc", "hi", "ls", "ge", "lt",
+ "gt", "le", "al", "nv"};
static int _decodeRegister(int reg, char* buffer, int blen) {
- switch (reg) {
- case ARM_SP:
- strncpy(buffer, "sp", blen - 1);
- return 2;
- case ARM_LR:
- strncpy(buffer, "lr", blen - 1);
- return 2;
- case ARM_PC:
- strncpy(buffer, "pc", blen - 1);
- return 2;
- case ARM_CPSR:
- strncpy(buffer, "cpsr", blen - 1);
- return 4;
- case ARM_SPSR:
- strncpy(buffer, "spsr", blen - 1);
- return 4;
- default:
- return snprintf(buffer, blen - 1, "r%i", reg);
- }
+ switch (reg) {
+ case ARM_SP:
+ strncpy(buffer, "sp", blen - 1);
+ return 2;
+ case ARM_LR:
+ strncpy(buffer, "lr", blen - 1);
+ return 2;
+ case ARM_PC:
+ strncpy(buffer, "pc", blen - 1);
+ return 2;
+ case ARM_CPSR:
+ strncpy(buffer, "cpsr", blen - 1);
+ return 4;
+ case ARM_SPSR:
+ strncpy(buffer, "spsr", blen - 1);
+ return 4;
+ default:
+ return snprintf(buffer, blen - 1, "r%i", reg);
+ }
}
static int _decodeRegisterList(int list, char* buffer, int blen) {
- if (blen <= 0) {
- return 0;
- }
- int total = 0;
- strncpy(buffer, "{", blen - 1);
- ADVANCE(1);
- int i;
- int start = -1;
- int end = -1;
- int written;
- for (i = 0; i <= ARM_PC; ++i) {
- if (list & 1) {
- if (start < 0) {
- start = i;
- end = i;
- } else if (end + 1 == i) {
- end = i;
- } else {
- if (end > start) {
- written = _decodeRegister(start, buffer, blen);
- ADVANCE(written);
- strncpy(buffer, "-", blen - 1);
- ADVANCE(1);
- }
- written = _decodeRegister(end, buffer, blen);
- ADVANCE(written);
- strncpy(buffer, ",", blen - 1);
- ADVANCE(1);
- start = i;
- end = i;
- }
- }
- list >>= 1;
- }
- if (start >= 0) {
- if (end > start) {
- written = _decodeRegister(start, buffer, blen);
- ADVANCE(written);
- strncpy(buffer, "-", blen - 1);
- ADVANCE(1);
- }
- written = _decodeRegister(end, buffer, blen);
- ADVANCE(written);
- }
- strncpy(buffer, "}", blen - 1);
- ADVANCE(1);
- return total;
+ if (blen <= 0) {
+ return 0;
+ }
+ int total = 0;
+ strncpy(buffer, "{", blen - 1);
+ ADVANCE(1);
+ int i;
+ int start = -1;
+ int end = -1;
+ int written;
+ for (i = 0; i <= ARM_PC; ++i) {
+ if (list & 1) {
+ if (start < 0) {
+ start = i;
+ end = i;
+ } else if (end + 1 == i) {
+ end = i;
+ } else {
+ if (end > start) {
+ written = _decodeRegister(start, buffer, blen);
+ ADVANCE(written);
+ strncpy(buffer, "-", blen - 1);
+ ADVANCE(1);
+ }
+ written = _decodeRegister(end, buffer, blen);
+ ADVANCE(written);
+ strncpy(buffer, ",", blen - 1);
+ ADVANCE(1);
+ start = i;
+ end = i;
+ }
+ }
+ list >>= 1;
+ }
+ if (start >= 0) {
+ if (end > start) {
+ written = _decodeRegister(start, buffer, blen);
+ ADVANCE(written);
+ strncpy(buffer, "-", blen - 1);
+ ADVANCE(1);
+ }
+ written = _decodeRegister(end, buffer, blen);
+ ADVANCE(written);
+ }
+ strncpy(buffer, "}", blen - 1);
+ ADVANCE(1);
+ return total;
}
static int _decodePSR(int psrBits, char* buffer, int blen) {
- if (!psrBits) {
- return 0;
- }
- int total = 0;
- strncpy(buffer, "_", blen - 1);
- ADVANCE(1);
- if (psrBits & ARM_PSR_C) {
- strncpy(buffer, "c", blen - 1);
- ADVANCE(1);
- }
- if (psrBits & ARM_PSR_X) {
- strncpy(buffer, "x", blen - 1);
- ADVANCE(1);
- }
- if (psrBits & ARM_PSR_S) {
- strncpy(buffer, "s", blen - 1);
- ADVANCE(1);
- }
- if (psrBits & ARM_PSR_F) {
- strncpy(buffer, "f", blen - 1);
- ADVANCE(1);
- }
- return total;
+ if (!psrBits) {
+ return 0;
+ }
+ int total = 0;
+ strncpy(buffer, "_", blen - 1);
+ ADVANCE(1);
+ if (psrBits & ARM_PSR_C) {
+ strncpy(buffer, "c", blen - 1);
+ ADVANCE(1);
+ }
+ if (psrBits & ARM_PSR_X) {
+ strncpy(buffer, "x", blen - 1);
+ ADVANCE(1);
+ }
+ if (psrBits & ARM_PSR_S) {
+ strncpy(buffer, "s", blen - 1);
+ ADVANCE(1);
+ }
+ if (psrBits & ARM_PSR_F) {
+ strncpy(buffer, "f", blen - 1);
+ ADVANCE(1);
+ }
+ return total;
}
-static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen) {
- return snprintf(buffer, blen - 1, "$%08X", address + pc);
+static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer,
+ int blen) {
+ return snprintf(buffer, blen - 1, "$%08X", address + pc);
}
-static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen) {
- if (blen <= 1) {
- return 0;
- }
- int total = 0;
- strncpy(buffer, "[", blen - 1);
- ADVANCE(1);
- int written;
- if (memory.format & ARM_MEMORY_REGISTER_BASE) {
- if (memory.baseReg == ARM_PC && memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
- written = _decodePCRelative(memory.format & ARM_MEMORY_OFFSET_SUBTRACT ? -memory.offset.immediate : memory.offset.immediate, pc & 0xFFFFFFFC, buffer, blen);
- ADVANCE(written);
- } else {
- written = _decodeRegister(memory.baseReg, buffer, blen);
- ADVANCE(written);
- if (memory.format & (ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_IMMEDIATE_OFFSET) && !(memory.format & ARM_MEMORY_POST_INCREMENT)) {
- strncpy(buffer, ", ", blen - 1);
- ADVANCE(2);
- }
- }
- }
- if (memory.format & ARM_MEMORY_POST_INCREMENT) {
- strncpy(buffer, "], ", blen - 1);
- ADVANCE(3);
- }
- if (memory.format & ARM_MEMORY_IMMEDIATE_OFFSET && memory.baseReg != ARM_PC) {
- if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
- written = snprintf(buffer, blen - 1, "#-%i", memory.offset.immediate);
- ADVANCE(written);
- } else {
- written = snprintf(buffer, blen - 1, "#%i", memory.offset.immediate);
- ADVANCE(written);
- }
- } else if (memory.format & ARM_MEMORY_REGISTER_OFFSET) {
- if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
- strncpy(buffer, "-", blen - 1);
- ADVANCE(1);
- }
- written = _decodeRegister(memory.offset.reg, buffer, blen);
- ADVANCE(written);
- }
- if (memory.format & ARM_MEMORY_SHIFTED_OFFSET) {
- written = _decodeShift(memory.offset, false, buffer, blen);
- ADVANCE(written);
- }
+static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer,
+ int blen) {
+ if (blen <= 1) {
+ return 0;
+ }
+ int total = 0;
+ strncpy(buffer, "[", blen - 1);
+ ADVANCE(1);
+ int written;
+ if (memory.format & ARM_MEMORY_REGISTER_BASE) {
+ if (memory.baseReg == ARM_PC &&
+ memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
+ written = _decodePCRelative(memory.format & ARM_MEMORY_OFFSET_SUBTRACT
+ ? -memory.offset.immediate
+ : memory.offset.immediate,
+ pc & 0xFFFFFFFC, buffer, blen);
+ ADVANCE(written);
+ } else {
+ written = _decodeRegister(memory.baseReg, buffer, blen);
+ ADVANCE(written);
+ if (memory.format &
+ (ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_IMMEDIATE_OFFSET) &&
+ !(memory.format & ARM_MEMORY_POST_INCREMENT)) {
+ strncpy(buffer, ", ", blen - 1);
+ ADVANCE(2);
+ }
+ }
+ }
+ if (memory.format & ARM_MEMORY_POST_INCREMENT) {
+ strncpy(buffer, "], ", blen - 1);
+ ADVANCE(3);
+ }
+ if (memory.format & ARM_MEMORY_IMMEDIATE_OFFSET && memory.baseReg != ARM_PC) {
+ if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
+ written = snprintf(buffer, blen - 1, "#-%i", memory.offset.immediate);
+ ADVANCE(written);
+ } else {
+ written = snprintf(buffer, blen - 1, "#%i", memory.offset.immediate);
+ ADVANCE(written);
+ }
+ } else if (memory.format & ARM_MEMORY_REGISTER_OFFSET) {
+ if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
+ strncpy(buffer, "-", blen - 1);
+ ADVANCE(1);
+ }
+ written = _decodeRegister(memory.offset.reg, buffer, blen);
+ ADVANCE(written);
+ }
+ if (memory.format & ARM_MEMORY_SHIFTED_OFFSET) {
+ written = _decodeShift(memory.offset, false, buffer, blen);
+ ADVANCE(written);
+ }
- if (!(memory.format & ARM_MEMORY_POST_INCREMENT)) {
- strncpy(buffer, "]", blen - 1);
- ADVANCE(1);
- }
- if ((memory.format & (ARM_MEMORY_PRE_INCREMENT | ARM_MEMORY_WRITEBACK)) == (ARM_MEMORY_PRE_INCREMENT | ARM_MEMORY_WRITEBACK)) {
- strncpy(buffer, "!", blen - 1);
- ADVANCE(1);
- }
- return total;
+ if (!(memory.format & ARM_MEMORY_POST_INCREMENT)) {
+ strncpy(buffer, "]", blen - 1);
+ ADVANCE(1);
+ }
+ if ((memory.format & (ARM_MEMORY_PRE_INCREMENT | ARM_MEMORY_WRITEBACK)) ==
+ (ARM_MEMORY_PRE_INCREMENT | ARM_MEMORY_WRITEBACK)) {
+ strncpy(buffer, "!", blen - 1);
+ ADVANCE(1);
+ }
+ return total;
}
static int _decodeShift(union ARMOperand op, bool reg, char* buffer, int blen) {
- if (blen <= 1) {
- return 0;
- }
- int total = 0;
- strncpy(buffer, ", ", blen - 1);
- ADVANCE(2);
- int written;
- switch (op.shifterOp) {
- case ARM_SHIFT_LSL:
- strncpy(buffer, "lsl ", blen - 1);
- ADVANCE(4);
- break;
- case ARM_SHIFT_LSR:
- strncpy(buffer, "lsr ", blen - 1);
- ADVANCE(4);
- break;
- case ARM_SHIFT_ASR:
- strncpy(buffer, "asr ", blen - 1);
- ADVANCE(4);
- break;
- case ARM_SHIFT_ROR:
- strncpy(buffer, "ror ", blen - 1);
- ADVANCE(4);
- break;
- case ARM_SHIFT_RRX:
- strncpy(buffer, "rrx", blen - 1);
- ADVANCE(3);
- return total;
- }
- if (!reg) {
- written = snprintf(buffer, blen - 1, "#%i", op.shifterImm);
- } else {
- written = _decodeRegister(op.shifterReg, buffer, blen);
- }
- ADVANCE(written);
- return total;
+ if (blen <= 1) {
+ return 0;
+ }
+ int total = 0;
+ strncpy(buffer, ", ", blen - 1);
+ ADVANCE(2);
+ int written;
+ switch (op.shifterOp) {
+ case ARM_SHIFT_LSL:
+ strncpy(buffer, "lsl ", blen - 1);
+ ADVANCE(4);
+ break;
+ case ARM_SHIFT_LSR:
+ strncpy(buffer, "lsr ", blen - 1);
+ ADVANCE(4);
+ break;
+ case ARM_SHIFT_ASR:
+ strncpy(buffer, "asr ", blen - 1);
+ ADVANCE(4);
+ break;
+ case ARM_SHIFT_ROR:
+ strncpy(buffer, "ror ", blen - 1);
+ ADVANCE(4);
+ break;
+ case ARM_SHIFT_RRX:
+ strncpy(buffer, "rrx", blen - 1);
+ ADVANCE(3);
+ return total;
+ }
+ if (!reg) {
+ written = snprintf(buffer, blen - 1, "#%i", op.shifterImm);
+ } else {
+ written = _decodeRegister(op.shifterReg, buffer, blen);
+ }
+ ADVANCE(written);
+ return total;
}
static const char* _armMnemonicStrings[] = {
- "ill",
- "adc",
- "add",
- "and",
- "asr",
- "b",
- "bic",
- "bkpt",
- "bl",
- "bx",
- "cmn",
- "cmp",
- "eor",
- "ldm",
- "ldr",
- "lsl",
- "lsr",
- "mla",
- "mov",
- "mrs",
- "msr",
- "mul",
- "mvn",
- "neg",
- "orr",
- "ror",
- "rsb",
- "rsc",
- "sbc",
- "smlal",
- "smull",
- "stm",
- "str",
- "sub",
- "swi",
- "swp",
- "teq",
- "tst",
- "umlal",
- "umull",
+ "ill", "adc", "add", "and", "asr", "b", "bic", "bkpt", "bl", "bx",
+ "cmn", "cmp", "eor", "ldm", "ldr", "lsl", "lsr", "mla", "mov", "mrs",
+ "msr", "mul", "mvn", "neg", "orr", "ror", "rsb", "rsc", "sbc", "smlal",
+ "smull", "stm", "str", "sub", "swi", "swp", "teq", "tst", "umlal", "umull",
- "ill"
-};
+ "ill"};
-static const char* _armDirectionStrings[] = {
- "da",
- "ia",
- "db",
- "ib"
-};
+static const char* _armDirectionStrings[] = {"da", "ia", "db", "ib"};
static const char* _armAccessTypeStrings[] = {
- "",
- "b",
- "h",
- "",
- "",
- "",
- "",
- "",
+ "", "b", "h", "", "", "", "", "",
- "",
- "sb",
- "sh",
- "",
- "",
- "",
- "",
- "",
+ "", "sb", "sh", "", "", "", "", "",
- "",
- "bt",
- "",
- "",
- "t",
- "",
- "",
- ""
-};
+ "", "bt", "", "", "t", "", "", ""};
-int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, int blen) {
- const char* mnemonic = _armMnemonicStrings[info->mnemonic];
- int written;
- int total = 0;
- const char* cond = "";
- if (info->condition != ARM_CONDITION_AL && info->condition < ARM_CONDITION_NV) {
- cond = _armConditions[info->condition];
- }
- const char* flags = "";
- switch (info->mnemonic) {
- case ARM_MN_LDM:
- case ARM_MN_STM:
- flags = _armDirectionStrings[MEMORY_FORMAT_TO_DIRECTION(info->memory.format)];
- break;
- case ARM_MN_LDR:
- case ARM_MN_STR:
- case ARM_MN_SWP:
- flags = _armAccessTypeStrings[info->memory.width];
- break;
- case ARM_MN_ADD:
- case ARM_MN_ADC:
- case ARM_MN_AND:
- case ARM_MN_BIC:
- case ARM_MN_EOR:
- case ARM_MN_MOV:
- case ARM_MN_MVN:
- case ARM_MN_ORR:
- case ARM_MN_RSB:
- case ARM_MN_RSC:
- case ARM_MN_SBC:
- case ARM_MN_SUB:
- if (info->affectsCPSR) {
- flags = "s";
- }
- break;
- default:
- break;
- }
- written = snprintf(buffer, blen - 1, "%s%s%s ", mnemonic, cond, flags);
- ADVANCE(written);
+int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer,
+ int blen) {
+ const char* mnemonic = _armMnemonicStrings[info->mnemonic];
+ int written;
+ int total = 0;
+ const char* cond = "";
+ if (info->condition != ARM_CONDITION_AL &&
+ info->condition < ARM_CONDITION_NV) {
+ cond = _armConditions[info->condition];
+ }
+ const char* flags = "";
+ switch (info->mnemonic) {
+ case ARM_MN_LDM:
+ case ARM_MN_STM:
+ flags =
+ _armDirectionStrings[MEMORY_FORMAT_TO_DIRECTION(info->memory.format)];
+ break;
+ case ARM_MN_LDR:
+ case ARM_MN_STR:
+ case ARM_MN_SWP:
+ flags = _armAccessTypeStrings[info->memory.width];
+ break;
+ case ARM_MN_ADD:
+ case ARM_MN_ADC:
+ case ARM_MN_AND:
+ case ARM_MN_BIC:
+ case ARM_MN_EOR:
+ case ARM_MN_MOV:
+ case ARM_MN_MVN:
+ case ARM_MN_ORR:
+ case ARM_MN_RSB:
+ case ARM_MN_RSC:
+ case ARM_MN_SBC:
+ case ARM_MN_SUB:
+ if (info->affectsCPSR) {
+ flags = "s";
+ }
+ break;
+ default:
+ break;
+ }
+ written = snprintf(buffer, blen - 1, "%s%s%s ", mnemonic, cond, flags);
+ ADVANCE(written);
- switch (info->mnemonic) {
- case ARM_MN_LDM:
- case ARM_MN_STM:
- written = _decodeRegister(info->memory.baseReg, buffer, blen);
- ADVANCE(written);
- if (info->memory.format & ARM_MEMORY_WRITEBACK) {
- strncpy(buffer, "!", blen - 1);
- ADVANCE(1);
- }
- strncpy(buffer, ", ", blen - 1);
- ADVANCE(2);
- written = _decodeRegisterList(info->op1.immediate, buffer, blen);
- ADVANCE(written);
- if (info->memory.format & ARM_MEMORY_SPSR_SWAP) {
- strncpy(buffer, "^", blen - 1);
- ADVANCE(1);
- }
- break;
- case ARM_MN_B:
- case ARM_MN_BL:
- if (info->operandFormat & ARM_OPERAND_IMMEDIATE_1) {
- written = _decodePCRelative(info->op1.immediate, pc, buffer, blen);
- ADVANCE(written);
- }
- break;
- default:
- if (info->operandFormat & ARM_OPERAND_IMMEDIATE_1) {
- written = snprintf(buffer, blen - 1, "#%i", info->op1.immediate);
- ADVANCE(written);
- } else if (info->operandFormat & ARM_OPERAND_MEMORY_1) {
- written = _decodeMemory(info->memory, pc, buffer, blen);
- ADVANCE(written);
- } else if (info->operandFormat & ARM_OPERAND_REGISTER_1) {
- written = _decodeRegister(info->op1.reg, buffer, blen);
- ADVANCE(written);
- if (info->op1.reg > ARM_PC) {
- written = _decodePSR(info->op1.psrBits, buffer, blen);
- ADVANCE(written);
- }
- }
- if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_1) {
- written = _decodeShift(info->op1, true, buffer, blen);
- ADVANCE(written);
- } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_1) {
- written = _decodeShift(info->op1, false, buffer, blen);
- ADVANCE(written);
- }
- if (info->operandFormat & ARM_OPERAND_2) {
- strncpy(buffer, ", ", blen);
- ADVANCE(2);
- }
- if (info->operandFormat & ARM_OPERAND_IMMEDIATE_2) {
- written = snprintf(buffer, blen - 1, "#%i", info->op2.immediate);
- ADVANCE(written);
- } else if (info->operandFormat & ARM_OPERAND_MEMORY_2) {
- written = _decodeMemory(info->memory, pc, buffer, blen);
- ADVANCE(written);
- } else if (info->operandFormat & ARM_OPERAND_REGISTER_2) {
- written = _decodeRegister(info->op2.reg, buffer, blen);
- ADVANCE(written);
- }
- if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_2) {
- written = _decodeShift(info->op2, true, buffer, blen);
- ADVANCE(written);
- } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_2) {
- written = _decodeShift(info->op2, false, buffer, blen);
- ADVANCE(written);
- }
- if (info->operandFormat & ARM_OPERAND_3) {
- strncpy(buffer, ", ", blen - 1);
- ADVANCE(2);
- }
- if (info->operandFormat & ARM_OPERAND_IMMEDIATE_3) {
- written = snprintf(buffer, blen - 1, "#%i", info->op3.immediate);
- ADVANCE(written);
- } else if (info->operandFormat & ARM_OPERAND_MEMORY_3) {
- written = _decodeMemory(info->memory, pc, buffer, blen);
- ADVANCE(written);
- } else if (info->operandFormat & ARM_OPERAND_REGISTER_3) {
- written = _decodeRegister(info->op3.reg, buffer, blen);
- ADVANCE(written);
- }
- if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_3) {
- written = _decodeShift(info->op3, true, buffer, blen);
- ADVANCE(written);
- } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_3) {
- written = _decodeShift(info->op3, false, buffer, blen);
- ADVANCE(written);
- }
- if (info->operandFormat & ARM_OPERAND_4) {
- strncpy(buffer, ", ", blen - 1);
- ADVANCE(2);
- }
- if (info->operandFormat & ARM_OPERAND_IMMEDIATE_4) {
- written = snprintf(buffer, blen - 1, "#%i", info->op4.immediate);
- ADVANCE(written);
- } else if (info->operandFormat & ARM_OPERAND_MEMORY_4) {
- written = _decodeMemory(info->memory, pc, buffer, blen);
- ADVANCE(written);
- } else if (info->operandFormat & ARM_OPERAND_REGISTER_4) {
- written = _decodeRegister(info->op4.reg, buffer, blen);
- ADVANCE(written);
- }
- if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_4) {
- written = _decodeShift(info->op4, true, buffer, blen);
- ADVANCE(written);
- } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_4) {
- written = _decodeShift(info->op4, false, buffer, blen);
- ADVANCE(written);
- }
- break;
- }
- buffer[blen - 1] = '\0';
- return total;
+ switch (info->mnemonic) {
+ case ARM_MN_LDM:
+ case ARM_MN_STM:
+ written = _decodeRegister(info->memory.baseReg, buffer, blen);
+ ADVANCE(written);
+ if (info->memory.format & ARM_MEMORY_WRITEBACK) {
+ strncpy(buffer, "!", blen - 1);
+ ADVANCE(1);
+ }
+ strncpy(buffer, ", ", blen - 1);
+ ADVANCE(2);
+ written = _decodeRegisterList(info->op1.immediate, buffer, blen);
+ ADVANCE(written);
+ if (info->memory.format & ARM_MEMORY_SPSR_SWAP) {
+ strncpy(buffer, "^", blen - 1);
+ ADVANCE(1);
+ }
+ break;
+ case ARM_MN_B:
+ case ARM_MN_BL:
+ if (info->operandFormat & ARM_OPERAND_IMMEDIATE_1) {
+ written = _decodePCRelative(info->op1.immediate, pc, buffer, blen);
+ ADVANCE(written);
+ }
+ break;
+ default:
+ if (info->operandFormat & ARM_OPERAND_IMMEDIATE_1) {
+ written = snprintf(buffer, blen - 1, "#%i", info->op1.immediate);
+ ADVANCE(written);
+ } else if (info->operandFormat & ARM_OPERAND_MEMORY_1) {
+ written = _decodeMemory(info->memory, pc, buffer, blen);
+ ADVANCE(written);
+ } else if (info->operandFormat & ARM_OPERAND_REGISTER_1) {
+ written = _decodeRegister(info->op1.reg, buffer, blen);
+ ADVANCE(written);
+ if (info->op1.reg > ARM_PC) {
+ written = _decodePSR(info->op1.psrBits, buffer, blen);
+ ADVANCE(written);
+ }
+ }
+ if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_1) {
+ written = _decodeShift(info->op1, true, buffer, blen);
+ ADVANCE(written);
+ } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_1) {
+ written = _decodeShift(info->op1, false, buffer, blen);
+ ADVANCE(written);
+ }
+ if (info->operandFormat & ARM_OPERAND_2) {
+ strncpy(buffer, ", ", blen);
+ ADVANCE(2);
+ }
+ if (info->operandFormat & ARM_OPERAND_IMMEDIATE_2) {
+ written = snprintf(buffer, blen - 1, "#%i", info->op2.immediate);
+ ADVANCE(written);
+ } else if (info->operandFormat & ARM_OPERAND_MEMORY_2) {
+ written = _decodeMemory(info->memory, pc, buffer, blen);
+ ADVANCE(written);
+ } else if (info->operandFormat & ARM_OPERAND_REGISTER_2) {
+ written = _decodeRegister(info->op2.reg, buffer, blen);
+ ADVANCE(written);
+ }
+ if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_2) {
+ written = _decodeShift(info->op2, true, buffer, blen);
+ ADVANCE(written);
+ } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_2) {
+ written = _decodeShift(info->op2, false, buffer, blen);
+ ADVANCE(written);
+ }
+ if (info->operandFormat & ARM_OPERAND_3) {
+ strncpy(buffer, ", ", blen - 1);
+ ADVANCE(2);
+ }
+ if (info->operandFormat & ARM_OPERAND_IMMEDIATE_3) {
+ written = snprintf(buffer, blen - 1, "#%i", info->op3.immediate);
+ ADVANCE(written);
+ } else if (info->operandFormat & ARM_OPERAND_MEMORY_3) {
+ written = _decodeMemory(info->memory, pc, buffer, blen);
+ ADVANCE(written);
+ } else if (info->operandFormat & ARM_OPERAND_REGISTER_3) {
+ written = _decodeRegister(info->op3.reg, buffer, blen);
+ ADVANCE(written);
+ }
+ if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_3) {
+ written = _decodeShift(info->op3, true, buffer, blen);
+ ADVANCE(written);
+ } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_3) {
+ written = _decodeShift(info->op3, false, buffer, blen);
+ ADVANCE(written);
+ }
+ if (info->operandFormat & ARM_OPERAND_4) {
+ strncpy(buffer, ", ", blen - 1);
+ ADVANCE(2);
+ }
+ if (info->operandFormat & ARM_OPERAND_IMMEDIATE_4) {
+ written = snprintf(buffer, blen - 1, "#%i", info->op4.immediate);
+ ADVANCE(written);
+ } else if (info->operandFormat & ARM_OPERAND_MEMORY_4) {
+ written = _decodeMemory(info->memory, pc, buffer, blen);
+ ADVANCE(written);
+ } else if (info->operandFormat & ARM_OPERAND_REGISTER_4) {
+ written = _decodeRegister(info->op4.reg, buffer, blen);
+ ADVANCE(written);
+ }
+ if (info->operandFormat & ARM_OPERAND_SHIFT_REGISTER_4) {
+ written = _decodeShift(info->op4, true, buffer, blen);
+ ADVANCE(written);
+ } else if (info->operandFormat & ARM_OPERAND_SHIFT_IMMEDIATE_4) {
+ written = _decodeShift(info->op4, false, buffer, blen);
+ ADVANCE(written);
+ }
+ break;
+ }
+ buffer[blen - 1] = '\0';
+ return total;
}
// Bit 3: the destination of this operand is affected by this opcode
// Bit 4: this operand is shifted by a register
// Bit 5: this operand is shifted by an immediate
-#define ARM_OPERAND_NONE 0x00000000
-#define ARM_OPERAND_REGISTER_1 0x00000001
-#define ARM_OPERAND_IMMEDIATE_1 0x00000002
-#define ARM_OPERAND_MEMORY_1 0x00000004
-#define ARM_OPERAND_AFFECTED_1 0x00000008
-#define ARM_OPERAND_SHIFT_REGISTER_1 0x00000010
-#define ARM_OPERAND_SHIFT_IMMEDIATE_1 0x00000020
-#define ARM_OPERAND_1 0x000000FF
-
-#define ARM_OPERAND_REGISTER_2 0x00000100
-#define ARM_OPERAND_IMMEDIATE_2 0x00000200
-#define ARM_OPERAND_MEMORY_2 0x00000400
-#define ARM_OPERAND_AFFECTED_2 0x00000800
-#define ARM_OPERAND_SHIFT_REGISTER_2 0x00001000
-#define ARM_OPERAND_SHIFT_IMMEDIATE_2 0x00002000
-#define ARM_OPERAND_2 0x0000FF00
-
-#define ARM_OPERAND_REGISTER_3 0x00010000
-#define ARM_OPERAND_IMMEDIATE_3 0x00020000
-#define ARM_OPERAND_MEMORY_3 0x00040000
-#define ARM_OPERAND_AFFECTED_3 0x00080000
-#define ARM_OPERAND_SHIFT_REGISTER_3 0x00100000
-#define ARM_OPERAND_SHIFT_IMMEDIATE_3 0x00200000
-#define ARM_OPERAND_3 0x00FF0000
-
-#define ARM_OPERAND_REGISTER_4 0x01000000
-#define ARM_OPERAND_IMMEDIATE_4 0x02000000
-#define ARM_OPERAND_MEMORY_4 0x04000000
-#define ARM_OPERAND_AFFECTED_4 0x08000000
-#define ARM_OPERAND_SHIFT_REGISTER_4 0x10000000
-#define ARM_OPERAND_SHIFT_IMMEDIATE_4 0x20000000
-#define ARM_OPERAND_4 0xFF000000
-
-#define ARM_OPERAND_MEMORY (ARM_OPERAND_MEMORY_1 | ARM_OPERAND_MEMORY_2 | ARM_OPERAND_MEMORY_3 | ARM_OPERAND_MEMORY_4)
-
-#define ARM_MEMORY_REGISTER_BASE 0x0001
-#define ARM_MEMORY_IMMEDIATE_OFFSET 0x0002
-#define ARM_MEMORY_REGISTER_OFFSET 0x0004
-#define ARM_MEMORY_SHIFTED_OFFSET 0x0008
-#define ARM_MEMORY_PRE_INCREMENT 0x0010
-#define ARM_MEMORY_POST_INCREMENT 0x0020
-#define ARM_MEMORY_OFFSET_SUBTRACT 0x0040
-#define ARM_MEMORY_WRITEBACK 0x0080
-#define ARM_MEMORY_DECREMENT_AFTER 0x0000
-#define ARM_MEMORY_INCREMENT_AFTER 0x0100
-#define ARM_MEMORY_DECREMENT_BEFORE 0x0200
-#define ARM_MEMORY_INCREMENT_BEFORE 0x0300
-#define ARM_MEMORY_SPSR_SWAP 0x0400
+#define ARM_OPERAND_NONE 0x00000000
+#define ARM_OPERAND_REGISTER_1 0x00000001
+#define ARM_OPERAND_IMMEDIATE_1 0x00000002
+#define ARM_OPERAND_MEMORY_1 0x00000004
+#define ARM_OPERAND_AFFECTED_1 0x00000008
+#define ARM_OPERAND_SHIFT_REGISTER_1 0x00000010
+#define ARM_OPERAND_SHIFT_IMMEDIATE_1 0x00000020
+#define ARM_OPERAND_1 0x000000FF
+
+#define ARM_OPERAND_REGISTER_2 0x00000100
+#define ARM_OPERAND_IMMEDIATE_2 0x00000200
+#define ARM_OPERAND_MEMORY_2 0x00000400
+#define ARM_OPERAND_AFFECTED_2 0x00000800
+#define ARM_OPERAND_SHIFT_REGISTER_2 0x00001000
+#define ARM_OPERAND_SHIFT_IMMEDIATE_2 0x00002000
+#define ARM_OPERAND_2 0x0000FF00
+
+#define ARM_OPERAND_REGISTER_3 0x00010000
+#define ARM_OPERAND_IMMEDIATE_3 0x00020000
+#define ARM_OPERAND_MEMORY_3 0x00040000
+#define ARM_OPERAND_AFFECTED_3 0x00080000
+#define ARM_OPERAND_SHIFT_REGISTER_3 0x00100000
+#define ARM_OPERAND_SHIFT_IMMEDIATE_3 0x00200000
+#define ARM_OPERAND_3 0x00FF0000
+
+#define ARM_OPERAND_REGISTER_4 0x01000000
+#define ARM_OPERAND_IMMEDIATE_4 0x02000000
+#define ARM_OPERAND_MEMORY_4 0x04000000
+#define ARM_OPERAND_AFFECTED_4 0x08000000
+#define ARM_OPERAND_SHIFT_REGISTER_4 0x10000000
+#define ARM_OPERAND_SHIFT_IMMEDIATE_4 0x20000000
+#define ARM_OPERAND_4 0xFF000000
+
+#define ARM_OPERAND_MEMORY \
+ (ARM_OPERAND_MEMORY_1 | ARM_OPERAND_MEMORY_2 | ARM_OPERAND_MEMORY_3 | \
+ ARM_OPERAND_MEMORY_4)
+
+#define ARM_MEMORY_REGISTER_BASE 0x0001
+#define ARM_MEMORY_IMMEDIATE_OFFSET 0x0002
+#define ARM_MEMORY_REGISTER_OFFSET 0x0004
+#define ARM_MEMORY_SHIFTED_OFFSET 0x0008
+#define ARM_MEMORY_PRE_INCREMENT 0x0010
+#define ARM_MEMORY_POST_INCREMENT 0x0020
+#define ARM_MEMORY_OFFSET_SUBTRACT 0x0040
+#define ARM_MEMORY_WRITEBACK 0x0080
+#define ARM_MEMORY_DECREMENT_AFTER 0x0000
+#define ARM_MEMORY_INCREMENT_AFTER 0x0100
+#define ARM_MEMORY_DECREMENT_BEFORE 0x0200
+#define ARM_MEMORY_INCREMENT_BEFORE 0x0300
+#define ARM_MEMORY_SPSR_SWAP 0x0400
#define ARM_PSR_C 1
#define ARM_PSR_X 2
#define MEMORY_FORMAT_TO_DIRECTION(F) (((F) >> 8) & 0x3)
enum ARMCondition {
- ARM_CONDITION_EQ = 0x0,
- ARM_CONDITION_NE = 0x1,
- ARM_CONDITION_CS = 0x2,
- ARM_CONDITION_CC = 0x3,
- ARM_CONDITION_MI = 0x4,
- ARM_CONDITION_PL = 0x5,
- ARM_CONDITION_VS = 0x6,
- ARM_CONDITION_VC = 0x7,
- ARM_CONDITION_HI = 0x8,
- ARM_CONDITION_LS = 0x9,
- ARM_CONDITION_GE = 0xA,
- ARM_CONDITION_LT = 0xB,
- ARM_CONDITION_GT = 0xC,
- ARM_CONDITION_LE = 0xD,
- ARM_CONDITION_AL = 0xE,
- ARM_CONDITION_NV = 0xF
+ ARM_CONDITION_EQ = 0x0,
+ ARM_CONDITION_NE = 0x1,
+ ARM_CONDITION_CS = 0x2,
+ ARM_CONDITION_CC = 0x3,
+ ARM_CONDITION_MI = 0x4,
+ ARM_CONDITION_PL = 0x5,
+ ARM_CONDITION_VS = 0x6,
+ ARM_CONDITION_VC = 0x7,
+ ARM_CONDITION_HI = 0x8,
+ ARM_CONDITION_LS = 0x9,
+ ARM_CONDITION_GE = 0xA,
+ ARM_CONDITION_LT = 0xB,
+ ARM_CONDITION_GT = 0xC,
+ ARM_CONDITION_LE = 0xD,
+ ARM_CONDITION_AL = 0xE,
+ ARM_CONDITION_NV = 0xF
};
enum ARMShifterOperation {
- ARM_SHIFT_NONE = 0,
- ARM_SHIFT_LSL,
- ARM_SHIFT_LSR,
- ARM_SHIFT_ASR,
- ARM_SHIFT_ROR,
- ARM_SHIFT_RRX
+ ARM_SHIFT_NONE = 0,
+ ARM_SHIFT_LSL,
+ ARM_SHIFT_LSR,
+ ARM_SHIFT_ASR,
+ ARM_SHIFT_ROR,
+ ARM_SHIFT_RRX
};
union ARMOperand {
- struct {
- uint8_t reg;
- uint8_t shifterOp;
- union {
- uint8_t shifterReg;
- uint8_t shifterImm;
- uint8_t psrBits;
- };
- };
- int32_t immediate;
+ struct {
+ uint8_t reg;
+ uint8_t shifterOp;
+ union {
+ uint8_t shifterReg;
+ uint8_t shifterImm;
+ uint8_t psrBits;
+ };
+ };
+ int32_t immediate;
};
enum ARMMemoryAccessType {
- ARM_ACCESS_WORD = 4,
- ARM_ACCESS_HALFWORD = 2,
- ARM_ACCESS_SIGNED_HALFWORD = 10,
- ARM_ACCESS_BYTE = 1,
- ARM_ACCESS_SIGNED_BYTE = 9,
- ARM_ACCESS_TRANSLATED_WORD = 20,
- ARM_ACCESS_TRANSLATED_BYTE = 17
+ ARM_ACCESS_WORD = 4,
+ ARM_ACCESS_HALFWORD = 2,
+ ARM_ACCESS_SIGNED_HALFWORD = 10,
+ ARM_ACCESS_BYTE = 1,
+ ARM_ACCESS_SIGNED_BYTE = 9,
+ ARM_ACCESS_TRANSLATED_WORD = 20,
+ ARM_ACCESS_TRANSLATED_BYTE = 17
};
enum ARMBranchType {
- ARM_BRANCH_NONE = 0,
- ARM_BRANCH = 1,
- ARM_BRANCH_INDIRECT = 2,
- ARM_BRANCH_LINKED = 4
+ ARM_BRANCH_NONE = 0,
+ ARM_BRANCH = 1,
+ ARM_BRANCH_INDIRECT = 2,
+ ARM_BRANCH_LINKED = 4
};
struct ARMMemoryAccess {
- uint8_t baseReg;
- uint8_t width;
- uint16_t format;
- union ARMOperand offset;
+ uint8_t baseReg;
+ uint8_t width;
+ uint16_t format;
+ union ARMOperand offset;
};
enum ARMMnemonic {
- ARM_MN_ILL = 0,
- ARM_MN_ADC,
- ARM_MN_ADD,
- ARM_MN_AND,
- ARM_MN_ASR,
- ARM_MN_B,
- ARM_MN_BIC,
- ARM_MN_BKPT,
- ARM_MN_BL,
- ARM_MN_BX,
- ARM_MN_CMN,
- ARM_MN_CMP,
- ARM_MN_EOR,
- ARM_MN_LDM,
- ARM_MN_LDR,
- ARM_MN_LSL,
- ARM_MN_LSR,
- ARM_MN_MLA,
- ARM_MN_MOV,
- ARM_MN_MRS,
- ARM_MN_MSR,
- ARM_MN_MUL,
- ARM_MN_MVN,
- ARM_MN_NEG,
- ARM_MN_ORR,
- ARM_MN_ROR,
- ARM_MN_RSB,
- ARM_MN_RSC,
- ARM_MN_SBC,
- ARM_MN_SMLAL,
- ARM_MN_SMULL,
- ARM_MN_STM,
- ARM_MN_STR,
- ARM_MN_SUB,
- ARM_MN_SWI,
- ARM_MN_SWP,
- ARM_MN_TEQ,
- ARM_MN_TST,
- ARM_MN_UMLAL,
- ARM_MN_UMULL,
-
- ARM_MN_MAX
+ ARM_MN_ILL = 0,
+ ARM_MN_ADC,
+ ARM_MN_ADD,
+ ARM_MN_AND,
+ ARM_MN_ASR,
+ ARM_MN_B,
+ ARM_MN_BIC,
+ ARM_MN_BKPT,
+ ARM_MN_BL,
+ ARM_MN_BX,
+ ARM_MN_CMN,
+ ARM_MN_CMP,
+ ARM_MN_EOR,
+ ARM_MN_LDM,
+ ARM_MN_LDR,
+ ARM_MN_LSL,
+ ARM_MN_LSR,
+ ARM_MN_MLA,
+ ARM_MN_MOV,
+ ARM_MN_MRS,
+ ARM_MN_MSR,
+ ARM_MN_MUL,
+ ARM_MN_MVN,
+ ARM_MN_NEG,
+ ARM_MN_ORR,
+ ARM_MN_ROR,
+ ARM_MN_RSB,
+ ARM_MN_RSC,
+ ARM_MN_SBC,
+ ARM_MN_SMLAL,
+ ARM_MN_SMULL,
+ ARM_MN_STM,
+ ARM_MN_STR,
+ ARM_MN_SUB,
+ ARM_MN_SWI,
+ ARM_MN_SWP,
+ ARM_MN_TEQ,
+ ARM_MN_TST,
+ ARM_MN_UMLAL,
+ ARM_MN_UMULL,
+
+ ARM_MN_MAX
};
-enum {
- ARM_SP = 13,
- ARM_LR = 14,
- ARM_PC = 15,
- ARM_CPSR = 16,
- ARM_SPSR = 17
-};
+enum { ARM_SP = 13, ARM_LR = 14, ARM_PC = 15, ARM_CPSR = 16, ARM_SPSR = 17 };
struct ARMInstructionInfo {
- uint32_t opcode;
- union ARMOperand op1;
- union ARMOperand op2;
- union ARMOperand op3;
- union ARMOperand op4;
- struct ARMMemoryAccess memory;
- int operandFormat;
- bool traps : 1;
- bool affectsCPSR : 1;
- unsigned branchType : 3;
- unsigned condition : 4;
- unsigned mnemonic : 6;
- unsigned iCycles : 3;
- unsigned cCycles : 4;
- unsigned sInstructionCycles : 4;
- unsigned nInstructionCycles : 4;
- unsigned sDataCycles : 10;
- unsigned nDataCycles : 10;
+ uint32_t opcode;
+ union ARMOperand op1;
+ union ARMOperand op2;
+ union ARMOperand op3;
+ union ARMOperand op4;
+ struct ARMMemoryAccess memory;
+ int operandFormat;
+ bool traps : 1;
+ bool affectsCPSR : 1;
+ unsigned branchType : 3;
+ unsigned condition : 4;
+ unsigned mnemonic : 6;
+ unsigned iCycles : 3;
+ unsigned cCycles : 4;
+ unsigned sInstructionCycles : 4;
+ unsigned nInstructionCycles : 4;
+ unsigned sDataCycles : 10;
+ unsigned nDataCycles : 10;
};
void ARMDecodeARM(uint32_t opcode, struct ARMInstructionInfo* info);
-int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, int blen);
+int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer,
+ int blen);
CXX_GUARD_END
#include "emitter-inlines.h"
-#define DECLARE_INSTRUCTION_ARM(EMITTER, NAME) \
- EMITTER ## NAME
+#define DECLARE_INSTRUCTION_ARM(EMITTER, NAME) EMITTER##NAME
-#define DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ALU) \
- DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## I)), \
- DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## I))
+#define DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ALU) \
+ DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, ALU##I)), \
+ DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, ALU##I))
-#define DECLARE_ARM_ALU_BLOCK(EMITTER, ALU, EX1, EX2, EX3, EX4) \
- DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSR), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSR), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ASR), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ASR), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ROR), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ROR), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, EX1), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _LSR), \
- DECLARE_INSTRUCTION_ARM(EMITTER, EX2), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ASR), \
- DECLARE_INSTRUCTION_ARM(EMITTER, EX3), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ALU ## _ROR), \
- DECLARE_INSTRUCTION_ARM(EMITTER, EX4)
+#define DECLARE_ARM_ALU_BLOCK(EMITTER, ALU, EX1, EX2, EX3, EX4) \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ALU##_LSL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ALU##_LSL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ALU##_LSR), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ALU##_LSR), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ALU##_ASR), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ALU##_ASR), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ALU##_ROR), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ALU##_ROR), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ALU##_LSL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, EX1), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ALU##_LSR), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, EX2), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ALU##_ASR), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, EX3), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ALU##_ROR), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, EX4)
-#define DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, NAME, P, U, W) \
- DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## I ## P ## U ## W)), \
- DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## I ## P ## U ## W))
+#define DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, NAME, P, U, W) \
+ DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME##I##P##U##W)), \
+ DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME##I##P##U##W))
-#define DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, NAME, P, U, W) \
- DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _LSL_ ## P ## U ## W), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _LSR_ ## P ## U ## W), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _ASR_ ## P ## U ## W), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _ROR_ ## P ## U ## W), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _LSL_ ## P ## U ## W), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _LSR_ ## P ## U ## W), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _ASR_ ## P ## U ## W), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## _ROR_ ## P ## U ## W), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL)
+#define DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, NAME, P, U, W) \
+ DECLARE_INSTRUCTION_ARM(EMITTER, NAME##_LSL_##P##U##W), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, NAME##_LSR_##P##U##W), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, NAME##_ASR_##P##U##W), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, NAME##_ROR_##P##U##W), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, NAME##_LSL_##P##U##W), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, NAME##_LSR_##P##U##W), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, NAME##_ASR_##P##U##W), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, NAME##_ROR_##P##U##W), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL)
-#define DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, NAME, MODE, W) \
- DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## MODE ## W)), \
- DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME ## MODE ## W))
+#define DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, NAME, MODE, W) \
+ DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME##MODE##W)), \
+ DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME##MODE##W))
-#define DECLARE_ARM_BRANCH_BLOCK(EMITTER, NAME) \
- DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, NAME))
+#define DECLARE_ARM_BRANCH_BLOCK(EMITTER, NAME) \
+ DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, NAME))
// TODO: Support coprocessors
-#define DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, NAME, P, U, N, W) \
- DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME)), \
- DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME))
+#define DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, NAME, P, U, N, W) \
+ DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME)), \
+ DO_8(DECLARE_INSTRUCTION_ARM(EMITTER, NAME))
-#define DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, NAME1, NAME2) \
- DO_8(DO_8(DO_INTERLACE(DECLARE_INSTRUCTION_ARM(EMITTER, NAME1), DECLARE_INSTRUCTION_ARM(EMITTER, NAME2))))
+#define DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, NAME1, NAME2) \
+ DO_8(DO_8(DO_INTERLACE(DECLARE_INSTRUCTION_ARM(EMITTER, NAME1), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, NAME2))))
-#define DECLARE_ARM_SWI_BLOCK(EMITTER) \
- DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, SWI))
+#define DECLARE_ARM_SWI_BLOCK(EMITTER) \
+ DO_256(DECLARE_INSTRUCTION_ARM(EMITTER, SWI))
-#define DECLARE_ARM_EMITTER_BLOCK(EMITTER) \
- DECLARE_ARM_ALU_BLOCK(EMITTER, AND, MUL, STRH, ILL, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, ANDS, MULS, LDRH, LDRSB, LDRSH), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, EOR, MLA, STRH, ILL, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, EORS, MLAS, LDRH, LDRSB, LDRSH), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, SUB, ILL, STRHI, ILL, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, SUBS, ILL, LDRHI, LDRSBI, LDRSHI), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, RSB, ILL, STRHI, ILL, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, RSBS, ILL, LDRHI, LDRSBI, LDRSHI), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, ADD, UMULL, STRHU, ILL, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, ADDS, UMULLS, LDRHU, LDRSBU, LDRSHU), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, ADC, UMLAL, STRHU, ILL, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, ADCS, UMLALS, LDRHU, LDRSBU, LDRSHU), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, SBC, SMULL, STRHIU, ILL, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, SBCS, SMULLS, LDRHIU, LDRSBIU, LDRSHIU), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, RSC, SMLAL, STRHIU, ILL, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, RSCS, SMLALS, LDRHIU, LDRSBIU, LDRSHIU), \
- DECLARE_INSTRUCTION_ARM(EMITTER, MRS), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, SWP), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, STRHP), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, TST, ILL, LDRHP, LDRSBP, LDRSHP), \
- DECLARE_INSTRUCTION_ARM(EMITTER, MSR), \
- DECLARE_INSTRUCTION_ARM(EMITTER, BX), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, BKPT), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, STRHPW), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, TEQ, ILL, LDRHPW, LDRSBPW, LDRSHPW), \
- DECLARE_INSTRUCTION_ARM(EMITTER, MRSR), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, SWPB), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, STRHIP), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, CMP, ILL, LDRHIP, LDRSBIP, LDRSHIP), \
- DECLARE_INSTRUCTION_ARM(EMITTER, MSRR), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, STRHIPW), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, CMN, ILL, LDRHIPW, LDRSBIPW, LDRSHIPW), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, ORR, SMLAL, STRHPU, ILL, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, ORRS, SMLALS, LDRHPU, LDRSBPU, LDRSHPU), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, MOV, SMLAL, STRHPUW, ILL, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, MOVS, SMLALS, LDRHPUW, LDRSBPUW, LDRSHPUW), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, BIC, SMLAL, STRHIPU, ILL, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, BICS, SMLALS, LDRHIPU, LDRSBIPU, LDRSHIPU), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, MVN, SMLAL, STRHIPUW, ILL, ILL), \
- DECLARE_ARM_ALU_BLOCK(EMITTER, MVNS, SMLALS, LDRHIPUW, LDRSBIPUW, LDRSHIPUW), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, AND), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ANDS), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, EOR), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, EORS), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SUB), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SUBS), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSB), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSBS), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADD), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADDS), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADC), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADCS), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SBC), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SBCS), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSC), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSCS), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TST), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TST), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MSR), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TEQ), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMP), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMP), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MSRR), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMN), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ORR), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ORRS), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MOV), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MOVS), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, BIC), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, BICS), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MVN), \
- DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MVNS), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, , , ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, , , ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRT, , , ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRT, , , ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, , , ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, , , ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRBT, , , ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRBT, , , ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, , U, ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, , U, ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRT, , U, ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRT, , U, ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, , U, ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, , U, ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRBT, , U, ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRBT, , U, ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, , ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, , ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, , W), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, , W), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, , ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, , ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, , W), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, , W), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, U, ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, U, ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, U, W), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, U, W), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, U, ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, U, ), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, U, W), \
- DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, U, W), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, , , ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, , , ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRT, , , ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRT, , , ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, , , ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, , , ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRBT, , , ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRBT, , , ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, , U, ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, , U, ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRT, , U, ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRT, , U, ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, , U, ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, , U, ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRBT, , U, ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRBT, , U, ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, , ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, , ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, , W), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, , W), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, , ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, , ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, , W), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, , W), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, U, ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, U, ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, U, W), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, U, W), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, U, ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, U, ), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, U, W), \
- DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, U, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DA, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DA, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DA, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DA, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DA, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DA, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DA, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DA, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IA, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IA, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IA, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IA, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IA, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IA, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IA, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IA, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DB, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DB, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DB, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DB, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DB, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DB, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DB, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DB, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IB, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IB, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IB, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IB, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IB, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IB, ), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IB, W), \
- DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IB, W), \
- DECLARE_ARM_BRANCH_BLOCK(EMITTER, B), \
- DECLARE_ARM_BRANCH_BLOCK(EMITTER, BL), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , , ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , , ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , , W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , , W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , N, ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , N, ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , N, W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , N, W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, , ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, , ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, , W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, , W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, N, ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, N, ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, N, W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, N, W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , , ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , , ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , , W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , , W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , N, ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , N, ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , N, W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , N, W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, ), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, W), \
- DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, W), \
- DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, CDP, MCR), \
- DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, CDP, MRC), \
- DECLARE_ARM_SWI_BLOCK(EMITTER)
+#define DECLARE_ARM_EMITTER_BLOCK(EMITTER) \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, AND, MUL, STRH, ILL, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, ANDS, MULS, LDRH, LDRSB, LDRSH), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, EOR, MLA, STRH, ILL, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, EORS, MLAS, LDRH, LDRSB, LDRSH), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, SUB, ILL, STRHI, ILL, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, SUBS, ILL, LDRHI, LDRSBI, LDRSHI), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, RSB, ILL, STRHI, ILL, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, RSBS, ILL, LDRHI, LDRSBI, LDRSHI), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, ADD, UMULL, STRHU, ILL, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, ADDS, UMULLS, LDRHU, LDRSBU, LDRSHU), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, ADC, UMLAL, STRHU, ILL, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, ADCS, UMLALS, LDRHU, LDRSBU, LDRSHU), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, SBC, SMULL, STRHIU, ILL, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, SBCS, SMULLS, LDRHIU, LDRSBIU, LDRSHIU), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, RSC, SMLAL, STRHIU, ILL, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, RSCS, SMLALS, LDRHIU, LDRSBIU, LDRSHIU), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, MRS), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, SWP), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, STRHP), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, TST, ILL, LDRHP, LDRSBP, LDRSHP), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, MSR), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, BX), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, BKPT), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, STRHPW), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, TEQ, ILL, LDRHPW, LDRSBPW, LDRSHPW), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, MRSR), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, SWPB), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, STRHIP), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, CMP, ILL, LDRHIP, LDRSBIP, LDRSHIP), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, MSRR), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, STRHIPW), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_INSTRUCTION_ARM(EMITTER, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, CMN, ILL, LDRHIPW, LDRSBIPW, LDRSHIPW), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, ORR, SMLAL, STRHPU, ILL, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, ORRS, SMLALS, LDRHPU, LDRSBPU, LDRSHPU), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, MOV, SMLAL, STRHPUW, ILL, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, MOVS, SMLALS, LDRHPUW, LDRSBPUW, \
+ LDRSHPUW), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, BIC, SMLAL, STRHIPU, ILL, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, BICS, SMLALS, LDRHIPU, LDRSBIPU, \
+ LDRSHIPU), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, MVN, SMLAL, STRHIPUW, ILL, ILL), \
+ DECLARE_ARM_ALU_BLOCK(EMITTER, MVNS, SMLALS, LDRHIPUW, LDRSBIPUW, \
+ LDRSHIPUW), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, AND), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ANDS), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, EOR), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, EORS), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SUB), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SUBS), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSB), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSBS), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADD), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADDS), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADC), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ADCS), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SBC), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, SBCS), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSC), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, RSCS), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TST), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TST), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MSR), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, TEQ), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMP), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMP), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MSRR), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, CMN), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ORR), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, ORRS), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MOV), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MOVS), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, BIC), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, BICS), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MVN), \
+ DECLARE_ARM_ALU_IMMEDIATE_BLOCK(EMITTER, MVNS), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, , , ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, , , ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRT, , , ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRT, , , ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, , , ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, , , ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRBT, , , ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRBT, , , ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, , U, ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, , U, ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRT, , U, ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRT, , U, ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, , U, ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, , U, ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRBT, , U, ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRBT, , U, ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, , ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, , ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, , W), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, , W), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, , ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, , ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, , W), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, , W), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, U, ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, U, ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STR, P, U, W), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDR, P, U, W), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, U, ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, U, ), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, STRB, P, U, W), \
+ DECLARE_ARM_LOAD_STORE_IMMEDIATE_BLOCK(EMITTER, LDRB, P, U, W), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, , , ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, , , ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRT, , , ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRT, , , ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, , , ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, , , ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRBT, , , ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRBT, , , ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, , U, ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, , U, ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRT, , U, ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRT, , U, ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, , U, ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, , U, ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRBT, , U, ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRBT, , U, ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, , ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, , ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, , W), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, , W), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, , ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, , ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, , W), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, , W), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, U, ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, U, ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STR, P, U, W), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDR, P, U, W), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, U, ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, U, ), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, STRB, P, U, W), \
+ DECLARE_ARM_LOAD_STORE_BLOCK(EMITTER, LDRB, P, U, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DA, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DA, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DA, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DA, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DA, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DA, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DA, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DA, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IA, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IA, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IA, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IA, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IA, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IA, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IA, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IA, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DB, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DB, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, DB, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, DB, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DB, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DB, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, DB, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, DB, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IB, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IB, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STM, IB, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDM, IB, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IB, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IB, ), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, STMS, IB, W), \
+ DECLARE_ARM_LOAD_STORE_MULTIPLE_BLOCK(EMITTER, LDMS, IB, W), \
+ DECLARE_ARM_BRANCH_BLOCK(EMITTER, B), \
+ DECLARE_ARM_BRANCH_BLOCK(EMITTER, BL), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , , ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , , ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , , W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , , W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , N, ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , N, ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , , N, W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , , N, W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, , ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, , ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, , W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, , W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, N, ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, N, ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, , U, N, W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, , U, N, W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , , ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , , ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , , W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , , W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , N, ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , N, ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, , N, W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, , N, W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, ), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, STC, P, U, N, W), \
+ DECLARE_ARM_LOAD_STORE_COPROCESSOR_BLOCK(EMITTER, LDC, P, U, N, W), \
+ DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, CDP, MCR), \
+ DECLARE_ARM_COPROCESSOR_BLOCK(EMITTER, CDP, MRC), \
+ DECLARE_ARM_SWI_BLOCK(EMITTER)
#endif
#ifndef EMITTER_INLINES_H
#define EMITTER_INLINES_H
-#define DO_4(DIRECTIVE) \
- DIRECTIVE, \
- DIRECTIVE, \
- DIRECTIVE, \
- DIRECTIVE
+#define DO_4(DIRECTIVE) DIRECTIVE, DIRECTIVE, DIRECTIVE, DIRECTIVE
-#define DO_8(DIRECTIVE) \
- DIRECTIVE, \
- DIRECTIVE, \
- DIRECTIVE, \
- DIRECTIVE, \
- DIRECTIVE, \
- DIRECTIVE, \
- DIRECTIVE, \
- DIRECTIVE
+#define DO_8(DIRECTIVE) \
+ DIRECTIVE, DIRECTIVE, DIRECTIVE, DIRECTIVE, DIRECTIVE, DIRECTIVE, DIRECTIVE, \
+ DIRECTIVE
-#define DO_256(DIRECTIVE) \
- DO_4(DO_8(DO_8(DIRECTIVE)))
+#define DO_256(DIRECTIVE) DO_4(DO_8(DO_8(DIRECTIVE)))
-#define DO_INTERLACE(LEFT, RIGHT) \
- LEFT, \
- RIGHT
+#define DO_INTERLACE(LEFT, RIGHT) LEFT, RIGHT
#endif
#include <unordered_set>
enum EpocKey {
- EStdKeyDial = 161,
- EStdKeyOff = 160,
- EStdKeyHelp = 159,
- EStdKeyDictaphoneRecord = 158,
- EStdKeyDictaphoneStop = 157,
- EStdKeyDictaphonePlay = 156,
- EStdKeySliderUp = 155,
- EStdKeySliderDown = 154,
- EStdKeyDecContrast = 153,
- EStdKeyIncContrast = 152,
- EStdKeyBacklightToggle = 151,
- EStdKeyBacklightOff = 150,
- EStdKeyBacklightOn = 149,
- EStdKeyMenu = 148,
- EStdKeyNkpFullStop = 147,
- EStdKeyNkp0 = 146,
- EStdKeyNkp9 = 145,
- EStdKeyNkp8 = 144,
- EStdKeyNkp7 = 143,
- EStdKeyNkp6 = 142,
- EStdKeyNkp5 = 141,
- EStdKeyNkp4 = 140,
- EStdKeyNkp3 = 139,
- EStdKeyNkp2 = 138,
- EStdKeyNkp1 = 137,
- EStdKeyNkpEnter = 136,
- EStdKeyNkpPlus = 135,
- EStdKeyNkpMinus = 134,
- EStdKeyNkpAsterisk = 133,
- EStdKeyNkpForwardSlash = 132,
- EStdKeyEquals = 131,
- EStdKeyMinus = 130,
- EStdKeySquareBracketRight = 129,
- EStdKeySquareBracketLeft = 128,
- EStdKeyHash = 127,
- EStdKeySingleQuote = 126,
- EStdKeySemiColon = 125,
- EStdKeyBackSlash = 124,
- EStdKeyForwardSlash = 123,
- EStdKeyFullStop = 122,
- EStdKeyComma = 121,
- EStdKeyXXX = 120,
- EStdKeyF24 = 119,
- EStdKeyF23 = 118,
- EStdKeyF22 = 117,
- EStdKeyF21 = 116,
- EStdKeyF20 = 115,
- EStdKeyF19 = 114,
- EStdKeyF18 = 113,
- EStdKeyF17 = 112,
- EStdKeyF16 = 111,
- EStdKeyF15 = 110,
- EStdKeyF14 = 109,
- EStdKeyF13 = 108,
- EStdKeyF12 = 107,
- EStdKeyF11 = 106,
- EStdKeyF10 = 105,
- EStdKeyF9 = 104,
- EStdKeyF8 = 103,
- EStdKeyF7 = 102,
- EStdKeyF6 = 101,
- EStdKeyF5 = 100,
- EStdKeyF4 = 99,
- EStdKeyF3 = 98,
- EStdKeyF2 = 97,
- EStdKeyF1 = 96,
- EStdKeyScrollLock = 28,
- EStdKeyNumLock = 27,
- EStdKeyCapsLock = 26,
- EStdKeyRightFunc = 25,
- EStdKeyLeftFunc = 24,
- EStdKeyRightCtrl = 23,
- EStdKeyLeftCtrl = 22,
- EStdKeyRightAlt = 21,
- EStdKeyLeftAlt = 20,
- EStdKeyRightShift = 19,
- EStdKeyLeftShift = 18,
- EStdKeyDownArrow = 17,
- EStdKeyUpArrow = 16,
- EStdKeyRightArrow = 15,
- EStdKeyLeftArrow = 14,
- EStdKeyDelete = 13,
- EStdKeyInsert = 12,
- EStdKeyPageDown = 11,
- EStdKeyPageUp = 10,
- EStdKeyEnd = 9,
- EStdKeyHome = 8,
- EStdKeyPause = 7,
- EStdKeyPrintScreen = 6,
- EStdKeySpace = 5,
- EStdKeyEscape = 4,
- EStdKeyEnter = 3,
- EStdKeyTab = 2,
- EStdKeyBackspace = 1,
- EStdKeyNull = 0
+ EStdKeyDial = 161,
+ EStdKeyOff = 160,
+ EStdKeyHelp = 159,
+ EStdKeyDictaphoneRecord = 158,
+ EStdKeyDictaphoneStop = 157,
+ EStdKeyDictaphonePlay = 156,
+ EStdKeySliderUp = 155,
+ EStdKeySliderDown = 154,
+ EStdKeyDecContrast = 153,
+ EStdKeyIncContrast = 152,
+ EStdKeyBacklightToggle = 151,
+ EStdKeyBacklightOff = 150,
+ EStdKeyBacklightOn = 149,
+ EStdKeyMenu = 148,
+ EStdKeyNkpFullStop = 147,
+ EStdKeyNkp0 = 146,
+ EStdKeyNkp9 = 145,
+ EStdKeyNkp8 = 144,
+ EStdKeyNkp7 = 143,
+ EStdKeyNkp6 = 142,
+ EStdKeyNkp5 = 141,
+ EStdKeyNkp4 = 140,
+ EStdKeyNkp3 = 139,
+ EStdKeyNkp2 = 138,
+ EStdKeyNkp1 = 137,
+ EStdKeyNkpEnter = 136,
+ EStdKeyNkpPlus = 135,
+ EStdKeyNkpMinus = 134,
+ EStdKeyNkpAsterisk = 133,
+ EStdKeyNkpForwardSlash = 132,
+ EStdKeyEquals = 131,
+ EStdKeyMinus = 130,
+ EStdKeySquareBracketRight = 129,
+ EStdKeySquareBracketLeft = 128,
+ EStdKeyHash = 127,
+ EStdKeySingleQuote = 126,
+ EStdKeySemiColon = 125,
+ EStdKeyBackSlash = 124,
+ EStdKeyForwardSlash = 123,
+ EStdKeyFullStop = 122,
+ EStdKeyComma = 121,
+ EStdKeyXXX = 120,
+ EStdKeyF24 = 119,
+ EStdKeyF23 = 118,
+ EStdKeyF22 = 117,
+ EStdKeyF21 = 116,
+ EStdKeyF20 = 115,
+ EStdKeyF19 = 114,
+ EStdKeyF18 = 113,
+ EStdKeyF17 = 112,
+ EStdKeyF16 = 111,
+ EStdKeyF15 = 110,
+ EStdKeyF14 = 109,
+ EStdKeyF13 = 108,
+ EStdKeyF12 = 107,
+ EStdKeyF11 = 106,
+ EStdKeyF10 = 105,
+ EStdKeyF9 = 104,
+ EStdKeyF8 = 103,
+ EStdKeyF7 = 102,
+ EStdKeyF6 = 101,
+ EStdKeyF5 = 100,
+ EStdKeyF4 = 99,
+ EStdKeyF3 = 98,
+ EStdKeyF2 = 97,
+ EStdKeyF1 = 96,
+ EStdKeyScrollLock = 28,
+ EStdKeyNumLock = 27,
+ EStdKeyCapsLock = 26,
+ EStdKeyRightFunc = 25,
+ EStdKeyLeftFunc = 24,
+ EStdKeyRightCtrl = 23,
+ EStdKeyLeftCtrl = 22,
+ EStdKeyRightAlt = 21,
+ EStdKeyLeftAlt = 20,
+ EStdKeyRightShift = 19,
+ EStdKeyLeftShift = 18,
+ EStdKeyDownArrow = 17,
+ EStdKeyUpArrow = 16,
+ EStdKeyRightArrow = 15,
+ EStdKeyLeftArrow = 14,
+ EStdKeyDelete = 13,
+ EStdKeyInsert = 12,
+ EStdKeyPageDown = 11,
+ EStdKeyPageUp = 10,
+ EStdKeyEnd = 9,
+ EStdKeyHome = 8,
+ EStdKeyPause = 7,
+ EStdKeyPrintScreen = 6,
+ EStdKeySpace = 5,
+ EStdKeyEscape = 4,
+ EStdKeyEnter = 3,
+ EStdKeyTab = 2,
+ EStdKeyBackspace = 1,
+ EStdKeyNull = 0
};
-class EmuBase : public ARM710
-{
+class EmuBase : public ARM710 {
protected:
#ifndef __EMSCRIPTEN__
- std::unordered_set<uint32_t> _breakpoints;
+ std::unordered_set<uint32_t> _breakpoints;
#endif
- int64_t passedCycles = 0;
- int64_t nextTickAt = 0;
- uint8_t readKeyboard(int kScan);
+ int64_t passedCycles = 0;
+ int64_t nextTickAt = 0;
+ uint8_t readKeyboard(int kScan);
public:
- EmuBase(bool isTVersion) : ARM710(isTVersion) { }
+ EmuBase(bool isTVersion) : ARM710(isTVersion) {}
- virtual uint8_t *getROMBuffer() = 0;
- virtual size_t getROMSize() = 0;
- virtual void loadROM(uint8_t *buffer, size_t size) = 0;
- virtual void executeUntil(int64_t cycles) = 0;
- virtual int32_t getClockSpeed() const = 0;
- virtual const char *getDeviceName() const = 0;
- virtual int getDigitiserWidth() const = 0;
- virtual int getDigitiserHeight() const = 0;
- virtual int getLCDOffsetX() const = 0;
- virtual int getLCDOffsetY() const = 0;
- virtual int getLCDWidth() const = 0;
- virtual int getLCDHeight() const = 0;
- virtual void readLCDIntoBuffer(uint8_t **lines, bool is32BitOutput) const = 0;
- virtual void setKeyboardKey(EpocKey key, bool value) = 0;
- virtual void updateTouchInput(int32_t x, int32_t y, bool down) = 0;
+ virtual uint8_t* getROMBuffer() = 0;
+ virtual size_t getROMSize() = 0;
+ virtual void loadROM(uint8_t* buffer, size_t size) = 0;
+ virtual void executeUntil(int64_t cycles) = 0;
+ virtual int32_t getClockSpeed() const = 0;
+ virtual const char* getDeviceName() const = 0;
+ virtual int getDigitiserWidth() const = 0;
+ virtual int getDigitiserHeight() const = 0;
+ virtual int getLCDOffsetX() const = 0;
+ virtual int getLCDOffsetY() const = 0;
+ virtual int getLCDWidth() const = 0;
+ virtual int getLCDHeight() const = 0;
+ virtual void readLCDIntoBuffer(uint8_t** lines, bool is32BitOutput) const = 0;
+ virtual void setKeyboardKey(EpocKey key, bool value) = 0;
+ virtual void updateTouchInput(int32_t x, int32_t y, bool down) = 0;
#ifndef __EMSCRIPTEN__
- std::unordered_set<uint32_t> &breakpoints() { return _breakpoints; }
+ std::unordered_set<uint32_t>& breakpoints() { return _breakpoints; }
#endif
- uint64_t currentCycles() const { return passedCycles; }
+ uint64_t currentCycles() const { return passedCycles; }
};
-
#include <string.h>
enum EtnaReg {
- regUnk0 = 0,
- regUnk1 = 1,
- regUartIntStatus = 2,
- regUartIntMask = 3,
- regUartBaudRateLo8 = 4,
- regUartBaudRateHi4 = 5,
- regPcCdIntStatus = 6,
- regPcCdIntMask = 7,
- regIntClear = 8,
- regSktVarA0 = 9,
- regSktVarA1 = 0xA,
- regSktCtrl = 0xB,
- regWake1 = 0xC,
- regSktVarB0 = 0xD,
- regSktVarB1 = 0xE,
- regWake2 = 0xF
+ regUnk0 = 0,
+ regUnk1 = 1,
+ regUartIntStatus = 2,
+ regUartIntMask = 3,
+ regUartBaudRateLo8 = 4,
+ regUartBaudRateHi4 = 5,
+ regPcCdIntStatus = 6,
+ regPcCdIntMask = 7,
+ regIntClear = 8,
+ regSktVarA0 = 9,
+ regSktVarA1 = 0xA,
+ regSktCtrl = 0xB,
+ regWake1 = 0xC,
+ regSktVarB0 = 0xD,
+ regSktVarB1 = 0xE,
+ regWake2 = 0xF
};
-static const char *nameReg(uint32_t reg) {
- switch (reg) {
- case regUnk0: return "unk0";
- case regUnk1: return "unk1";
- case regUartIntStatus: return "UartIntStatus";
- case regUartIntMask: return "UartIntMask";
- case regUartBaudRateLo8: return "UartBaudRateLo8";
- case regUartBaudRateHi4: return "UartBaudRateHi4";
- case regPcCdIntStatus: return "PcCdIntStatus";
- case regPcCdIntMask: return "PcCdIntMask";
- case regIntClear: return "IntClear";
- case regSktVarA0: return "SktVarA0";
- case regSktVarA1: return "SktVarA1";
- case regSktCtrl: return "SktCtrl";
- case regWake1: return "wake1";
- case regSktVarB0: return "SktVarB0";
- case regSktVarB1: return "SktVarB1";
- case regWake2: return "wake2";
- }
- return nullptr;
+static const char* nameReg(uint32_t reg) {
+ switch (reg) {
+ case regUnk0:
+ return "unk0";
+ case regUnk1:
+ return "unk1";
+ case regUartIntStatus:
+ return "UartIntStatus";
+ case regUartIntMask:
+ return "UartIntMask";
+ case regUartBaudRateLo8:
+ return "UartBaudRateLo8";
+ case regUartBaudRateHi4:
+ return "UartBaudRateHi4";
+ case regPcCdIntStatus:
+ return "PcCdIntStatus";
+ case regPcCdIntMask:
+ return "PcCdIntMask";
+ case regIntClear:
+ return "IntClear";
+ case regSktVarA0:
+ return "SktVarA0";
+ case regSktVarA1:
+ return "SktVarA1";
+ case regSktCtrl:
+ return "SktCtrl";
+ case regWake1:
+ return "wake1";
+ case regSktVarB0:
+ return "SktVarB0";
+ case regSktVarB1:
+ return "SktVarB1";
+ case regWake2:
+ return "wake2";
+ }
+ return nullptr;
}
-
-Etna::Etna(ARM710 *owner) {
- this->owner = owner;
-
- for (int i = 0; i < 0x80; i++)
- prom[i] = 0;
-
- // defaults expected by the touchscreen code
- prom[0xA] = 20;
- prom[0xB] = 20;
- prom[0xC] = 20;
- prom[0xD] = 30;
-
- // some basic stuff to begin with
- // set up the Psion's unique ID
- prom[0x1B] = 0xDE;
- prom[0x1A] = 0xAD;
- prom[0x19] = 0xBE;
- prom[0x18] = 0xEF;
-
- // give ourselves a neat custom device name
- const char *key = "PSIONPSIONPSION";
- const char *name = "WindEmu!";
- prom[0x28] = strlen(name);
- if (prom[0x28] > 15)
- prom[0x28] = 15;
- for (int i = 0; i < prom[0x28]; i++)
- prom[0x29 + i] = name[i] ^ key[i];
-
- // calculate the checksum
- uint8_t chk = 0;
- for (int i = 0; i < 0x7F; i++)
- chk ^= prom[i];
-
- // EPOC is expecting 66
- prom[0x7F] = chk ^ 66;
+Etna::Etna(ARM710* owner) {
+ this->owner = owner;
+
+ for (int i = 0; i < 0x80; i++)
+ prom[i] = 0;
+
+ // defaults expected by the touchscreen code
+ prom[0xA] = 20;
+ prom[0xB] = 20;
+ prom[0xC] = 20;
+ prom[0xD] = 30;
+
+ // some basic stuff to begin with
+ // set up the Psion's unique ID
+ prom[0x1B] = 0xDE;
+ prom[0x1A] = 0xAD;
+ prom[0x19] = 0xBE;
+ prom[0x18] = 0xEF;
+
+ // give ourselves a neat custom device name
+ const char* key = "PSIONPSIONPSION";
+ const char* name = "WindEmu!";
+ prom[0x28] = strlen(name);
+ if (prom[0x28] > 15)
+ prom[0x28] = 15;
+ for (int i = 0; i < prom[0x28]; i++)
+ prom[0x29 + i] = name[i] ^ key[i];
+
+ // calculate the checksum
+ uint8_t chk = 0;
+ for (int i = 0; i < 0x7F; i++)
+ chk ^= prom[i];
+
+ // EPOC is expecting 66
+ prom[0x7F] = chk ^ 66;
}
-
-uint32_t Etna::readReg8(uint32_t reg)
-{
-// if (!promReadActive)
-// owner->log("ETNA readReg8: reg=%s @ pc=%08x,lr=%08x", nameReg(reg), owner->getGPR(15) - 4, owner->getGPR(14));
- switch (reg) {
- case regIntClear: return 0;
- case regSktVarA0: return 1; // will store some status flags
- case regSktVarA1: return 0; // will store some more status flags
- case regWake1: return wake1;
- case regWake2: return wake2;
- }
- return 0xFF;
+uint32_t Etna::readReg8(uint32_t reg) {
+ // if (!promReadActive)
+ // owner->log("ETNA readReg8: reg=%s @ pc=%08x,lr=%08x",
+ // nameReg(reg), owner->getGPR(15) - 4, owner->getGPR(14));
+ switch (reg) {
+ case regIntClear:
+ return 0;
+ case regSktVarA0:
+ return 1; // will store some status flags
+ case regSktVarA1:
+ return 0; // will store some more status flags
+ case regWake1:
+ return wake1;
+ case regWake2:
+ return wake2;
+ }
+ return 0xFF;
}
-uint32_t Etna::readReg32(uint32_t reg)
-{
- // may be able to remove this, p. sure Etna is byte addressing only
- owner->log("ETNA readReg32: reg=%x", reg);
- return 0xFFFFFFFF;
-}
-
-void Etna::writeReg8(uint32_t reg, uint8_t value)
-{
- if (!promReadActive)
- owner->log("ETNA writeReg8: reg=%s value=%02x @ pc=%08x,lr=%08x", nameReg(reg), value, owner->getGPR(15) - 4, owner->getGPR(14));
- switch (reg) {
- case regIntClear: pendingInterrupts &= ~value; break;
- case regWake1: wake1 = value; break;
- case regWake2: wake2 = value; break;
- }
+uint32_t Etna::readReg32(uint32_t reg) {
+ // may be able to remove this, p. sure Etna is byte addressing only
+ owner->log("ETNA readReg32: reg=%x", reg);
+ return 0xFFFFFFFF;
}
-void Etna::writeReg32(uint32_t reg, uint32_t value)
-{
- // may be able to remove this, p. sure Etna is byte addressing only
- owner->log("ETNA writeReg32: reg=%x value=%08x", reg, value);
+void Etna::writeReg8(uint32_t reg, uint8_t value) {
+ if (!promReadActive)
+ owner->log("ETNA writeReg8: reg=%s value=%02x @ pc=%08x,lr=%08x",
+ nameReg(reg), value, owner->getGPR(15) - 4, owner->getGPR(14));
+ switch (reg) {
+ case regIntClear:
+ pendingInterrupts &= ~value;
+ break;
+ case regWake1:
+ wake1 = value;
+ break;
+ case regWake2:
+ wake2 = value;
+ break;
+ }
}
-void Etna::setPromBit0High()
-{
- // begin reading a word
- promReadAddress = 0;
- promReadValue = 0;
- promAddressBitsReceived = 0;
- promReadActive = true;
+void Etna::writeReg32(uint32_t reg, uint32_t value) {
+ // may be able to remove this, p. sure Etna is byte addressing only
+ owner->log("ETNA writeReg32: reg=%x value=%08x", reg, value);
}
-void Etna::setPromBit0Low()
-{
- promReadActive = false;
+void Etna::setPromBit0High() {
+ // begin reading a word
+ promReadAddress = 0;
+ promReadValue = 0;
+ promAddressBitsReceived = 0;
+ promReadActive = true;
}
-void Etna::setPromBit1High()
-{
- if (promAddressBitsReceived < 10) {
- // we're still receiving the address
- promReadAddress <<= 1;
- promReadAddress |= ((wake1 & 4) >> 2);
- if (++promAddressBitsReceived == 10) {
- // we can fetch the value now
- int addressInBytes = promReadAddress * 2;
- addressInBytes %= sizeof(prom);
- promReadValue = prom[addressInBytes] | (prom[addressInBytes + 1] << 8);
- }
- } else {
- wake1 &= ~8;
- if (promReadValue & 0x8000)
- wake1 |= 8;
- promReadValue <<= 1;
+void Etna::setPromBit0Low() { promReadActive = false; }
+
+void Etna::setPromBit1High() {
+ if (promAddressBitsReceived < 10) {
+ // we're still receiving the address
+ promReadAddress <<= 1;
+ promReadAddress |= ((wake1 & 4) >> 2);
+ if (++promAddressBitsReceived == 10) {
+ // we can fetch the value now
+ int addressInBytes = promReadAddress * 2;
+ addressInBytes %= sizeof(prom);
+ promReadValue = prom[addressInBytes] | (prom[addressInBytes + 1] << 8);
}
+ } else {
+ wake1 &= ~8;
+ if (promReadValue & 0x8000)
+ wake1 |= 8;
+ promReadValue <<= 1;
+ }
}
class ARM710;
class Etna {
- uint8_t prom[0x80] = {};
- uint16_t promReadAddress = 0, promReadValue = 0;
- bool promReadActive = false;
- int promAddressBitsReceived = 0;
+ uint8_t prom[0x80] = {};
+ uint16_t promReadAddress = 0, promReadValue = 0;
+ bool promReadActive = false;
+ int promAddressBitsReceived = 0;
- uint8_t pendingInterrupts = 0, interruptMask = 0;
- uint8_t wake1 = 0, wake2 = 0;
+ uint8_t pendingInterrupts = 0, interruptMask = 0;
+ uint8_t wake1 = 0, wake2 = 0;
- ARM710 *owner;
+ ARM710* owner;
public:
- Etna(ARM710 *owner);
+ Etna(ARM710* owner);
- uint32_t readReg8(uint32_t reg);
- uint32_t readReg32(uint32_t reg);
- void writeReg8(uint32_t reg, uint8_t value);
- void writeReg32(uint32_t reg, uint32_t value);
+ uint32_t readReg8(uint32_t reg);
+ uint32_t readReg32(uint32_t reg);
+ void writeReg8(uint32_t reg, uint8_t value);
+ void writeReg32(uint32_t reg, uint32_t value);
- // PROM
- void setPromBit0High(); // port B, bit 0
- void setPromBit0Low(); // port B, bit 0
- void setPromBit1High(); // port B, bit 1
+ // PROM
+ void setPromBit0High(); // port B, bit 0
+ void setPromBit0Low(); // port B, bit 0
+ void setPromBit1High(); // port B, bit 1
};
#include <stdio.h>
struct Timer {
- ARM710 *cpu;
+ ARM710* cpu;
- enum {
- MODE_512KHZ = 1<<3,
- PERIODIC = 1<<6,
- ENABLED = 1<<7
- };
- int64_t nextTickAt;
- uint8_t config;
- uint32_t interval;
- int32_t value;
- int clockSpeed;
+ enum { MODE_512KHZ = 1 << 3, PERIODIC = 1 << 6, ENABLED = 1 << 7 };
+ int64_t nextTickAt;
+ uint8_t config;
+ uint32_t interval;
+ int32_t value;
+ int clockSpeed;
- int tickInterval() const {
- return (config & MODE_512KHZ) ? (clockSpeed / 512000) : (clockSpeed / 2000);
- }
- void load(uint32_t lval) {
- interval = lval;
- value = lval;
- }
- void setConfig(uint8_t cval) {
- nextTickAt -= tickInterval();
- config = cval;
- nextTickAt += tickInterval();
- }
- bool tick(int64_t cycles) {
- if (cycles >= nextTickAt) {
- nextTickAt += tickInterval();
+ int tickInterval() const {
+ return (config & MODE_512KHZ) ? (clockSpeed / 512000) : (clockSpeed / 2000);
+ }
+ void load(uint32_t lval) {
+ interval = lval;
+ value = lval;
+ }
+ void setConfig(uint8_t cval) {
+ nextTickAt -= tickInterval();
+ config = cval;
+ nextTickAt += tickInterval();
+ }
+ bool tick(int64_t cycles) {
+ if (cycles >= nextTickAt) {
+ nextTickAt += tickInterval();
- if (config & ENABLED) {
- --value;
- if (value == 0) {
- if (config & PERIODIC)
- value = interval;
- return true;
- }
- }
- }
- return false;
- }
- void dump() {
- printf("enabled=%s periodic=%s interval=%d value=%d\n",
- (config & ENABLED) ? "true" : "false",
- (config & PERIODIC) ? "true" : "false",
- interval, value
- );
- }
+ if (config & ENABLED) {
+ --value;
+ if (value == 0) {
+ if (config & PERIODIC)
+ value = interval;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ void dump() {
+ printf("enabled=%s periodic=%s interval=%d value=%d\n",
+ (config & ENABLED) ? "true" : "false",
+ (config & PERIODIC) ? "true" : "false", interval, value);
+ }
};
enum UartRegs {
- UART0DATA = 0x600,
- UART0FCR = 0x604,
- UART0LCR = 0x608,
- UART0CON = 0x60C,
- UART0FLG = 0x610,
- UART0INT = 0x614,
- UART0INTM = 0x618,
- UART0INTR = 0x61C,
- UART0TEST1 = 0x620,
- UART0TEST2 = 0x624,
- UART0TEST3 = 0x628,
- UART1DATA = 0x700,
- UART1FCR = 0x704,
- UART1LCR = 0x708,
- UART1CON = 0x70C,
- UART1FLG = 0x710,
- UART1INT = 0x714,
- UART1INTM = 0x718,
- UART1INTR = 0x71C,
- UART1TEST1 = 0x720,
- UART1TEST2 = 0x724,
- UART1TEST3 = 0x728,
+ UART0DATA = 0x600,
+ UART0FCR = 0x604,
+ UART0LCR = 0x608,
+ UART0CON = 0x60C,
+ UART0FLG = 0x610,
+ UART0INT = 0x614,
+ UART0INTM = 0x618,
+ UART0INTR = 0x61C,
+ UART0TEST1 = 0x620,
+ UART0TEST2 = 0x624,
+ UART0TEST3 = 0x628,
+ UART1DATA = 0x700,
+ UART1FCR = 0x704,
+ UART1LCR = 0x708,
+ UART1CON = 0x70C,
+ UART1FLG = 0x710,
+ UART1INT = 0x714,
+ UART1INTM = 0x718,
+ UART1INTR = 0x71C,
+ UART1TEST1 = 0x720,
+ UART1TEST2 = 0x724,
+ UART1TEST3 = 0x728,
};
struct UART {
- ARM710 *cpu;
+ ARM710* cpu;
- enum {
- IntRx = 1,
- IntTx = 2,
- IntModemStatus = 4,
- PortCtrlEnable = 1,
- PortCtrlSirEnable = 2,
- PortCtrlIrdaTx = 4,
- FrameCtrlBreak = 1,
- FrameCtrlParityEnable = 2,
- FrameCtrlEvenParity = 4,
- FrameCtrlExtraStopBit = 8,
- FrameCtrlUFifoEn = 0x10,
- FrameCtrlWrdLenMask = 0x60,
- FrameCtrlWlen5 = 0,
- FrameCtrlWlen6 = 0x20,
- FrameCtrlWlen7 = 0x40,
- FrameCtrlWlen8 = 0x60,
- RecvFrameError = 0x100,
- RecvParityError = 0x200,
- RecvOverrunError = 0x400,
- FlagClearToSend = 1,
- FlagDataSetReady = 2,
- FlagDataCarrierDetect = 4,
- FlagBusy = 8,
- FlagReceiveFifoEmpty = 0x10,
- FlagTransmitFifoFull = 0x20
- };
- uint8_t portControl = 0;
- uint8_t frameControl = 0;
- uint8_t interrupts = 0, interruptMask = 0;
+ enum {
+ IntRx = 1,
+ IntTx = 2,
+ IntModemStatus = 4,
+ PortCtrlEnable = 1,
+ PortCtrlSirEnable = 2,
+ PortCtrlIrdaTx = 4,
+ FrameCtrlBreak = 1,
+ FrameCtrlParityEnable = 2,
+ FrameCtrlEvenParity = 4,
+ FrameCtrlExtraStopBit = 8,
+ FrameCtrlUFifoEn = 0x10,
+ FrameCtrlWrdLenMask = 0x60,
+ FrameCtrlWlen5 = 0,
+ FrameCtrlWlen6 = 0x20,
+ FrameCtrlWlen7 = 0x40,
+ FrameCtrlWlen8 = 0x60,
+ RecvFrameError = 0x100,
+ RecvParityError = 0x200,
+ RecvOverrunError = 0x400,
+ FlagClearToSend = 1,
+ FlagDataSetReady = 2,
+ FlagDataCarrierDetect = 4,
+ FlagBusy = 8,
+ FlagReceiveFifoEmpty = 0x10,
+ FlagTransmitFifoFull = 0x20
+ };
+ uint8_t portControl = 0;
+ uint8_t frameControl = 0;
+ uint8_t interrupts = 0, interruptMask = 0;
- // UART0DATA = 0x600, byte write, long read
- // UART0FCR = 0x604, long
- // UART0LCR = 0x608, long
- // UART0CON = 0x60C, byte
- // UART0FLG = 0x610, byte
- // UART0INT = 0x614, long write, byte read
- // UART0INTM = 0x618, byte
- // UART0INTR = 0x61C, byte
- // UART0TEST1 = 0x620,
- // UART0TEST2 = 0x624,
- // UART0TEST3 = 0x628,
- uint32_t readReg8(uint32_t reg) {
- // UART0DATA
- if (reg == (UART0CON & 0xFF)) {
- return portControl;
- } else if (reg == (UART0FLG & 0xFF)) {
- // we pretend we are never busy, never have full fifo
- return FlagReceiveFifoEmpty;
- // UART0INT?
- // UART0INTM?
- // UART0INTR?
- } else {
- printf("unhandled 8bit uart read %x at pc=%08x lr=%08x\n", reg, cpu->getGPR(15), cpu->getGPR(14));
- return 0xFF;
- }
- }
- uint32_t readReg32(uint32_t reg) {
- // UART0DATA
- if (reg == (UART0FCR & 0xFF)) {
- return frameControl;
- // UART0LCR
- } else if (reg == (UART0FLG & 0xFF)) {
- // we pretend we are never busy, never have full fifo
- return FlagReceiveFifoEmpty;
- } else {
- printf("unhandled 32bit uart read %x at pc=%08x lr=%08x\n", reg, cpu->getGPR(15), cpu->getGPR(14));
- return 0xFFFFFFFF;
- }
- }
- void writeReg8(uint32_t reg, uint8_t value) {
- // UART0DATA
- if (reg == (UART0CON & 0xFF)) {
- portControl = value;
- printf("portcon updated: enable=%d sirenable=%d irdatx=%d\n", value&1, value&2, value&4);
- } else if (reg == (UART0INTM & 0xFF)) {
- interruptMask = value;
- printf("uart interruptmask updated: %d\n", value);
- // UART0INTR?
- } else {
- printf("unhandled 8bit uart write %x value %02x at pc=%08x lr=%08x\n", reg, value, cpu->getGPR(15), cpu->getGPR(14));
- }
- }
- void writeReg32(uint32_t reg, uint32_t value) {
- if (reg == (UART0FCR & 0xFF)) {
- frameControl = value;
- printf("frameControl updated: break=%d parityEn=%d evenParity=%d extraStop=%d ufifoEn=%d wrdLen=%d\n",
- value&1,
- value&2,
- value&4,
- value&8,
- value&0x10,
- ((value&0x60)>>5)+5);
- } else if (reg == (UART0LCR & 0xFF)) {
- printf("** uart writing lcr %x **\n", value);
- } else if (reg == (UART0INT & 0xFF)) {
- printf("uart interrupts %x -> %x\n", interrupts, value);
- interrupts = value;
- } else {
- printf("unhandled 32bit uart write %x value %08x at pc=%08x lr=%08x\n", reg, value, cpu->getGPR(15), cpu->getGPR(14));
- }
- }
+ // UART0DATA = 0x600, byte write, long read
+ // UART0FCR = 0x604, long
+ // UART0LCR = 0x608, long
+ // UART0CON = 0x60C, byte
+ // UART0FLG = 0x610, byte
+ // UART0INT = 0x614, long write, byte read
+ // UART0INTM = 0x618, byte
+ // UART0INTR = 0x61C, byte
+ // UART0TEST1 = 0x620,
+ // UART0TEST2 = 0x624,
+ // UART0TEST3 = 0x628,
+ uint32_t readReg8(uint32_t reg) {
+ // UART0DATA
+ if (reg == (UART0CON & 0xFF)) {
+ return portControl;
+ } else if (reg == (UART0FLG & 0xFF)) {
+ // we pretend we are never busy, never have full fifo
+ return FlagReceiveFifoEmpty;
+ // UART0INT?
+ // UART0INTM?
+ // UART0INTR?
+ } else {
+ printf("unhandled 8bit uart read %x at pc=%08x lr=%08x\n", reg,
+ cpu->getGPR(15), cpu->getGPR(14));
+ return 0xFF;
+ }
+ }
+ uint32_t readReg32(uint32_t reg) {
+ // UART0DATA
+ if (reg == (UART0FCR & 0xFF)) {
+ return frameControl;
+ // UART0LCR
+ } else if (reg == (UART0FLG & 0xFF)) {
+ // we pretend we are never busy, never have full fifo
+ return FlagReceiveFifoEmpty;
+ } else {
+ printf("unhandled 32bit uart read %x at pc=%08x lr=%08x\n", reg,
+ cpu->getGPR(15), cpu->getGPR(14));
+ return 0xFFFFFFFF;
+ }
+ }
+ void writeReg8(uint32_t reg, uint8_t value) {
+ // UART0DATA
+ if (reg == (UART0CON & 0xFF)) {
+ portControl = value;
+ printf("portcon updated: enable=%d sirenable=%d irdatx=%d\n", value & 1,
+ value & 2, value & 4);
+ } else if (reg == (UART0INTM & 0xFF)) {
+ interruptMask = value;
+ printf("uart interruptmask updated: %d\n", value);
+ // UART0INTR?
+ } else {
+ printf("unhandled 8bit uart write %x value %02x at pc=%08x lr=%08x\n",
+ reg, value, cpu->getGPR(15), cpu->getGPR(14));
+ }
+ }
+ void writeReg32(uint32_t reg, uint32_t value) {
+ if (reg == (UART0FCR & 0xFF)) {
+ frameControl = value;
+ printf("frameControl updated: break=%d parityEn=%d evenParity=%d "
+ "extraStop=%d ufifoEn=%d wrdLen=%d\n",
+ value & 1, value & 2, value & 4, value & 8, value & 0x10,
+ ((value & 0x60) >> 5) + 5);
+ } else if (reg == (UART0LCR & 0xFF)) {
+ printf("** uart writing lcr %x **\n", value);
+ } else if (reg == (UART0INT & 0xFF)) {
+ printf("uart interrupts %x -> %x\n", interrupts, value);
+ interrupts = value;
+ } else {
+ printf("unhandled 32bit uart write %x value %08x at pc=%08x lr=%08x\n",
+ reg, value, cpu->getGPR(15), cpu->getGPR(14));
+ }
+ }
};
#include "macros.h"
#define ARM_SIGN(I) ((I) >> 31)
-#define ARM_SXT_8(I) (((int8_t) (I) << 24) >> 24)
-#define ARM_SXT_16(I) (((int16_t) (I) << 16) >> 16)
-#define ARM_UXT_64(I) (uint64_t)(uint32_t) (I)
+#define ARM_SXT_8(I) (((int8_t)(I) << 24) >> 24)
+#define ARM_SXT_16(I) (((int16_t)(I) << 16) >> 16)
+#define ARM_UXT_64(I) (uint64_t)(uint32_t)(I)
-#define ARM_CARRY_FROM(M, N, D) (((uint32_t) (M) >> 31) + ((uint32_t) (N) >> 31) > ((uint32_t) (D) >> 31))
-#define ARM_BORROW_FROM(M, N, D) (((uint32_t) (M)) >= ((uint32_t) (N)))
-#define ARM_BORROW_FROM_CARRY(M, N, D, C) (ARM_UXT_64(M) >= (ARM_UXT_64(N)) + (uint64_t) (C))
-#define ARM_V_ADDITION(M, N, D) (!(ARM_SIGN((M) ^ (N))) && (ARM_SIGN((M) ^ (D))))
-#define ARM_V_SUBTRACTION(M, N, D) ((ARM_SIGN((M) ^ (N))) && (ARM_SIGN((M) ^ (D))))
+#define ARM_CARRY_FROM(M, N, D) \
+ (((uint32_t)(M) >> 31) + ((uint32_t)(N) >> 31) > ((uint32_t)(D) >> 31))
+#define ARM_BORROW_FROM(M, N, D) (((uint32_t)(M)) >= ((uint32_t)(N)))
+#define ARM_BORROW_FROM_CARRY(M, N, D, C) \
+ (ARM_UXT_64(M) >= (ARM_UXT_64(N)) + (uint64_t)(C))
+#define ARM_V_ADDITION(M, N, D) \
+ (!(ARM_SIGN((M) ^ (N))) && (ARM_SIGN((M) ^ (D))))
+#define ARM_V_SUBTRACTION(M, N, D) \
+ ((ARM_SIGN((M) ^ (N))) && (ARM_SIGN((M) ^ (D))))
#endif
#include <stdint.h>
namespace Windermere {
-enum {
- CLOCK_SPEED = 0x9000*1000,
- TICK_INTERVAL = CLOCK_SPEED / 64
-};
+enum { CLOCK_SPEED = 0x9000 * 1000, TICK_INTERVAL = CLOCK_SPEED / 64 };
enum Interrupt {
- EXTFIQ = 0, // FiqExternal
- BLINT = 1, // FiqBatLow
- WEINT = 2, // FiqWatchDog
- MCINT = 3, // FiqMediaChg
- CSINT = 4, // IrqCodec
- EINT1 = 5, // IrqExt1
- EINT2 = 6, // IrqExt2
- EINT3 = 7, // IrqExt3
- TC1OI = 8, // IrqTimer1
- TC2OI = 9, // IrqTimer2
- RTCMI = 10, // IrqRtcMatch
- TINT = 11, // IrqTick
- UART1 = 12, // IrqUart1
- UART2 = 13, // IrqUart1
- LCDINT = 14, // IrqLcd
- SSEOTI = 15, // IrqSpi
- FIQ_INTERRUPTS = 0x000F,
- IRQ_INTERRUPTS = 0xFFF0
+ EXTFIQ = 0, // FiqExternal
+ BLINT = 1, // FiqBatLow
+ WEINT = 2, // FiqWatchDog
+ MCINT = 3, // FiqMediaChg
+ CSINT = 4, // IrqCodec
+ EINT1 = 5, // IrqExt1
+ EINT2 = 6, // IrqExt2
+ EINT3 = 7, // IrqExt3
+ TC1OI = 8, // IrqTimer1
+ TC2OI = 9, // IrqTimer2
+ RTCMI = 10, // IrqRtcMatch
+ TINT = 11, // IrqTick
+ UART1 = 12, // IrqUart1
+ UART2 = 13, // IrqUart1
+ LCDINT = 14, // IrqLcd
+ SSEOTI = 15, // IrqSpi
+ FIQ_INTERRUPTS = 0x000F,
+ IRQ_INTERRUPTS = 0xFFF0
};
enum Register {
- MEMCFG1 = 0,
- MEMCFG2 = 4,
- DRAM_CFG = 0x100,
- LCDCTL = 0x200,
- LCDST = 0x204,
- LCD_DBAR1 = 0x210,
- LCDT0 = 0x220,
- LCDT1 = 0x224,
- LCDT2 = 0x228,
- PWRSR = 0x400,
- PWRCNT = 0x404,
- HALT = 0x408,
- STBY = 0x40C,
- BLEOI = 0x410,
- MCEOI = 0x414,
- TEOI = 0x418,
- STFCLR = 0x41C,
- E2EOI = 0x420,
- INTSR = 0x500,
- INTRSR = 0x504,
- INTENS = 0x508,
- INTENC = 0x50C,
- INTTEST1 = 0x514,
- INTTEST2 = 0x518,
- PUMPCON = 0x900,
- CODR = 0xA00,
- CONFG = 0xA04,
- COLFG = 0xA08,
- COEOI = 0xA0C,
- COTEST = 0xA10,
- SSCR0 = 0xB00,
- SSCR1 = 0xB04,
- SSDR = 0xB0C,
- SSSR = 0xB14,
- TC1LOAD = 0xC00,
- TC1VAL = 0xC04,
- TC1CTRL = 0xC08,
- TC1EOI = 0xC0C,
- TC2LOAD = 0xC20,
- TC2VAL = 0xC24,
- TC2CTRL = 0xC28,
- TC2EOI = 0xC2C,
- BZCONT = 0xC40,
- RTCDRL = 0xD00,
- RTCDRU = 0xD04,
- RTCMRL = 0xD08,
- RTCMRU = 0xD0C,
- RTCEOI = 0xD10,
- PADR = 0xE00,
- PBDR = 0xE04,
- PCDR = 0xE08,
- PDDR = 0xE0C,
- PADDR = 0xE10,
- PBDDR = 0xE14,
- PCDDR = 0xE18,
- PDDDR = 0xE1C,
- PEDR = 0xE20,
- PEDDR = 0xE24,
- KSCAN = 0xE28,
- LCDMUX = 0xE2C
+ MEMCFG1 = 0,
+ MEMCFG2 = 4,
+ DRAM_CFG = 0x100,
+ LCDCTL = 0x200,
+ LCDST = 0x204,
+ LCD_DBAR1 = 0x210,
+ LCDT0 = 0x220,
+ LCDT1 = 0x224,
+ LCDT2 = 0x228,
+ PWRSR = 0x400,
+ PWRCNT = 0x404,
+ HALT = 0x408,
+ STBY = 0x40C,
+ BLEOI = 0x410,
+ MCEOI = 0x414,
+ TEOI = 0x418,
+ STFCLR = 0x41C,
+ E2EOI = 0x420,
+ INTSR = 0x500,
+ INTRSR = 0x504,
+ INTENS = 0x508,
+ INTENC = 0x50C,
+ INTTEST1 = 0x514,
+ INTTEST2 = 0x518,
+ PUMPCON = 0x900,
+ CODR = 0xA00,
+ CONFG = 0xA04,
+ COLFG = 0xA08,
+ COEOI = 0xA0C,
+ COTEST = 0xA10,
+ SSCR0 = 0xB00,
+ SSCR1 = 0xB04,
+ SSDR = 0xB0C,
+ SSSR = 0xB14,
+ TC1LOAD = 0xC00,
+ TC1VAL = 0xC04,
+ TC1CTRL = 0xC08,
+ TC1EOI = 0xC0C,
+ TC2LOAD = 0xC20,
+ TC2VAL = 0xC24,
+ TC2CTRL = 0xC28,
+ TC2EOI = 0xC2C,
+ BZCONT = 0xC40,
+ RTCDRL = 0xD00,
+ RTCDRU = 0xD04,
+ RTCMRL = 0xD08,
+ RTCMRU = 0xD0C,
+ RTCEOI = 0xD10,
+ PADR = 0xE00,
+ PBDR = 0xE04,
+ PCDR = 0xE08,
+ PDDR = 0xE0C,
+ PADDR = 0xE10,
+ PBDDR = 0xE14,
+ PCDDR = 0xE18,
+ PDDDR = 0xE1C,
+ PEDR = 0xE20,
+ PEDDR = 0xE24,
+ KSCAN = 0xE28,
+ LCDMUX = 0xE2C
};
-}
+} // namespace Windermere
#include "windermere.h"
-#include "wind_defs.h"
+#include "common.h"
#include "hardware.h"
+#include "wind_defs.h"
#include <time.h>
-#include "common.h"
-
-//#define INCLUDE_D
-//#define INCLUDE_BANK1
+// #define INCLUDE_D
+// #define INCLUDE_BANK1
namespace Windermere {
-Emulator::Emulator() : EmuBase(true), etna(this) {
-}
-
-
-uint32_t Emulator::getRTC() {
- return time(nullptr) - 946684800;
-}
+Emulator::Emulator() : EmuBase(true), etna(this) {}
+uint32_t Emulator::getRTC() { return time(nullptr) - 946684800; }
uint32_t Emulator::readReg8(uint32_t reg) {
- if ((reg & 0xF00) == 0x600) {
- return uart1.readReg8(reg & 0xFF);
- } else if ((reg & 0xF00) == 0x700) {
- return uart2.readReg8(reg & 0xFF);
- } else if (reg == TC1CTRL) {
- return tc1.config;
- } else if (reg == TC2CTRL) {
- return tc2.config;
- } else if (reg == PADR) {
- return readKeyboard();
- } else if (reg == PBDR) {
- return (portValues >> 16) & 0xFF;
- } else if (reg == PCDR) {
- return (portValues >> 8) & 0xFF;
- } else if (reg == PDDR) {
- return portValues & 0xFF;
- } else if (reg == PADDR) {
- return (portDirections >> 24) & 0xFF;
- } else if (reg == PBDDR) {
- return (portDirections >> 16) & 0xFF;
- } else if (reg == PCDDR) {
- return (portDirections >> 8) & 0xFF;
- } else if (reg == PDDDR) {
- return portDirections & 0xFF;
- } else {
-// printf("RegRead8 unknown:: pc=%08x lr=%08x reg=%03x\n", getGPR(15)-4, getGPR(14), reg);
- return 0xFF;
- }
+ if ((reg & 0xF00) == 0x600) {
+ return uart1.readReg8(reg & 0xFF);
+ } else if ((reg & 0xF00) == 0x700) {
+ return uart2.readReg8(reg & 0xFF);
+ } else if (reg == TC1CTRL) {
+ return tc1.config;
+ } else if (reg == TC2CTRL) {
+ return tc2.config;
+ } else if (reg == PADR) {
+ return readKeyboard();
+ } else if (reg == PBDR) {
+ return (portValues >> 16) & 0xFF;
+ } else if (reg == PCDR) {
+ return (portValues >> 8) & 0xFF;
+ } else if (reg == PDDR) {
+ return portValues & 0xFF;
+ } else if (reg == PADDR) {
+ return (portDirections >> 24) & 0xFF;
+ } else if (reg == PBDDR) {
+ return (portDirections >> 16) & 0xFF;
+ } else if (reg == PCDDR) {
+ return (portDirections >> 8) & 0xFF;
+ } else if (reg == PDDDR) {
+ return portDirections & 0xFF;
+ } else {
+ // printf("RegRead8 unknown:: pc=%08x lr=%08x reg=%03x\n",
+ // getGPR(15)-4, getGPR(14), reg);
+ return 0xFF;
+ }
}
uint32_t Emulator::readReg32(uint32_t reg) {
- if (reg == LCDCTL) {
- printf("LCD control read pc=%08x lr=%08x !!!\n", getGPR(15), getGPR(14));
- return lcdControl;
- } else if (reg == LCDST) {
- printf("LCD state read pc=%08x lr=%08x !!!\n", getGPR(15), getGPR(14));
- return 0xFFFFFFFF;
- } else if (reg == PWRSR) {
-// printf("!!! PWRSR read pc=%08x lr=%08x !!!\n", getGPR(15), getGPR(14));
- return pwrsr;
- } else if (reg == INTSR) {
- return pendingInterrupts & interruptMask;
- } else if (reg == INTRSR) {
- return pendingInterrupts;
- } else if (reg == INTENS) {
- return interruptMask;
- } else if ((reg & 0xF00) == 0x600) {
- return uart1.readReg32(reg & 0xFF);
- } else if ((reg & 0xF00) == 0x700) {
- return uart2.readReg32(reg & 0xFF);
- } else if (reg == TC1VAL) {
- return tc1.value;
- } else if (reg == TC2VAL) {
- return tc2.value;
- } else if (reg == SSDR) {
- // as per 5000A7B0 in 5mx rom
- uint16_t ssiValue = 0;
- switch (lastSSIRequest) {
- case 0xD0D3: ssiValue = (uint16_t)(50 + (touchX * 5.7)); break;
- case 0x9093: ssiValue = (uint16_t)(3834 - (touchY * 13.225)); break;
- case 0xA4A4: ssiValue = 3100; break; // MainBattery
- case 0xE4E4: ssiValue = 3100; break; // BackupBattery
- }
-
- uint32_t ret = 0;
- if (ssiReadCounter == 4) ret = (ssiValue >> 5) & 0x7F;
- if (ssiReadCounter == 5) ret = (ssiValue << 3) & 0xF8;
- ssiReadCounter++;
- if (ssiReadCounter == 6) ssiReadCounter = 0;
-
- // by hardware we should be clearing SSEOTI here, i think
- // but we just leave it on to simplify things
- return ret;
- } else if (reg == SSSR) {
- return 0;
- } else if (reg == RTCDRL) {
- uint16_t v = rtc & 0xFFFF;
-// log("RTCDRL: %04x", v);
- return v;
- } else if (reg == RTCDRU) {
- uint16_t v = rtc >> 16;
-// log("RTCDRU: %04x", v);
- return v;
- } else if (reg == KSCAN) {
- return kScan;
- } else {
-// printf("RegRead32 unknown:: pc=%08x lr=%08x reg=%03x\n", getGPR(15)-4, getGPR(14), reg);
- return 0xFFFFFFFF;
- }
+ if (reg == LCDCTL) {
+ printf("LCD control read pc=%08x lr=%08x !!!\n", getGPR(15), getGPR(14));
+ return lcdControl;
+ } else if (reg == LCDST) {
+ printf("LCD state read pc=%08x lr=%08x !!!\n", getGPR(15), getGPR(14));
+ return 0xFFFFFFFF;
+ } else if (reg == PWRSR) {
+ // printf("!!! PWRSR read pc=%08x lr=%08x !!!\n", getGPR(15),
+ // getGPR(14));
+ return pwrsr;
+ } else if (reg == INTSR) {
+ return pendingInterrupts & interruptMask;
+ } else if (reg == INTRSR) {
+ return pendingInterrupts;
+ } else if (reg == INTENS) {
+ return interruptMask;
+ } else if ((reg & 0xF00) == 0x600) {
+ return uart1.readReg32(reg & 0xFF);
+ } else if ((reg & 0xF00) == 0x700) {
+ return uart2.readReg32(reg & 0xFF);
+ } else if (reg == TC1VAL) {
+ return tc1.value;
+ } else if (reg == TC2VAL) {
+ return tc2.value;
+ } else if (reg == SSDR) {
+ // as per 5000A7B0 in 5mx rom
+ uint16_t ssiValue = 0;
+ switch (lastSSIRequest) {
+ case 0xD0D3:
+ ssiValue = (uint16_t)(50 + (touchX * 5.7));
+ break;
+ case 0x9093:
+ ssiValue = (uint16_t)(3834 - (touchY * 13.225));
+ break;
+ case 0xA4A4:
+ ssiValue = 3100;
+ break; // MainBattery
+ case 0xE4E4:
+ ssiValue = 3100;
+ break; // BackupBattery
+ }
+
+ uint32_t ret = 0;
+ if (ssiReadCounter == 4)
+ ret = (ssiValue >> 5) & 0x7F;
+ if (ssiReadCounter == 5)
+ ret = (ssiValue << 3) & 0xF8;
+ ssiReadCounter++;
+ if (ssiReadCounter == 6)
+ ssiReadCounter = 0;
+
+ // by hardware we should be clearing SSEOTI here, i think
+ // but we just leave it on to simplify things
+ return ret;
+ } else if (reg == SSSR) {
+ return 0;
+ } else if (reg == RTCDRL) {
+ uint16_t v = rtc & 0xFFFF;
+ // log("RTCDRL: %04x", v);
+ return v;
+ } else if (reg == RTCDRU) {
+ uint16_t v = rtc >> 16;
+ // log("RTCDRU: %04x", v);
+ return v;
+ } else if (reg == KSCAN) {
+ return kScan;
+ } else {
+ // printf("RegRead32 unknown:: pc=%08x lr=%08x reg=%03x\n",
+ // getGPR(15)-4, getGPR(14), reg);
+ return 0xFFFFFFFF;
+ }
}
void Emulator::writeReg8(uint32_t reg, uint8_t value) {
- if ((reg & 0xF00) == 0x600) {
- uart1.writeReg8(reg & 0xFF, value);
- } else if ((reg & 0xF00) == 0x700) {
- uart2.writeReg8(reg & 0xFF, value);
- } else if (reg == TC1CTRL) {
- tc1.setConfig(value);
- } else if (reg == TC2CTRL) {
- tc2.setConfig(value);
- } else if (reg == PADR) {
- uint32_t oldPorts = portValues;
- portValues &= 0x00FFFFFF;
- portValues |= (uint32_t)value << 24;
- diffPorts(oldPorts, portValues);
- } else if (reg == PBDR) {
- uint32_t oldPorts = portValues;
- portValues &= 0xFF00FFFF;
- portValues |= (uint32_t)value << 16;
- if ((portValues & 0x10000) && !(oldPorts & 0x10000))
- etna.setPromBit0High();
- else if (!(portValues & 0x10000) && (oldPorts & 0x10000))
- etna.setPromBit0Low();
- if ((portValues & 0x20000) && !(oldPorts & 0x20000))
- etna.setPromBit1High();
- diffPorts(oldPorts, portValues);
- } else if (reg == PCDR) {
- uint32_t oldPorts = portValues;
- portValues &= 0xFFFF00FF;
- portValues |= (uint32_t)value << 8;
- diffPorts(oldPorts, portValues);
- } else if (reg == PDDR) {
- uint32_t oldPorts = portValues;
- portValues &= 0xFFFFFF00;
- portValues |= (uint32_t)value;
- diffPorts(oldPorts, portValues);
- } else if (reg == PADDR) {
- portDirections &= 0x00FFFFFF;
- portDirections |= (uint32_t)value << 24;
- } else if (reg == PBDDR) {
- portDirections &= 0xFF00FFFF;
- portDirections |= (uint32_t)value << 16;
- } else if (reg == PCDDR) {
- portDirections &= 0xFFFF00FF;
- portDirections |= (uint32_t)value << 8;
- } else if (reg == PDDDR) {
- portDirections &= 0xFFFFFF00;
- portDirections |= (uint32_t)value;
- } else if (reg == KSCAN) {
- kScan = value;
- } else {
-// printf("RegWrite8 unknown:: pc=%08x reg=%03x value=%02x\n", getGPR(15)-4, reg, value);
- }
+ if ((reg & 0xF00) == 0x600) {
+ uart1.writeReg8(reg & 0xFF, value);
+ } else if ((reg & 0xF00) == 0x700) {
+ uart2.writeReg8(reg & 0xFF, value);
+ } else if (reg == TC1CTRL) {
+ tc1.setConfig(value);
+ } else if (reg == TC2CTRL) {
+ tc2.setConfig(value);
+ } else if (reg == PADR) {
+ uint32_t oldPorts = portValues;
+ portValues &= 0x00FFFFFF;
+ portValues |= (uint32_t)value << 24;
+ diffPorts(oldPorts, portValues);
+ } else if (reg == PBDR) {
+ uint32_t oldPorts = portValues;
+ portValues &= 0xFF00FFFF;
+ portValues |= (uint32_t)value << 16;
+ if ((portValues & 0x10000) && !(oldPorts & 0x10000))
+ etna.setPromBit0High();
+ else if (!(portValues & 0x10000) && (oldPorts & 0x10000))
+ etna.setPromBit0Low();
+ if ((portValues & 0x20000) && !(oldPorts & 0x20000))
+ etna.setPromBit1High();
+ diffPorts(oldPorts, portValues);
+ } else if (reg == PCDR) {
+ uint32_t oldPorts = portValues;
+ portValues &= 0xFFFF00FF;
+ portValues |= (uint32_t)value << 8;
+ diffPorts(oldPorts, portValues);
+ } else if (reg == PDDR) {
+ uint32_t oldPorts = portValues;
+ portValues &= 0xFFFFFF00;
+ portValues |= (uint32_t)value;
+ diffPorts(oldPorts, portValues);
+ } else if (reg == PADDR) {
+ portDirections &= 0x00FFFFFF;
+ portDirections |= (uint32_t)value << 24;
+ } else if (reg == PBDDR) {
+ portDirections &= 0xFF00FFFF;
+ portDirections |= (uint32_t)value << 16;
+ } else if (reg == PCDDR) {
+ portDirections &= 0xFFFF00FF;
+ portDirections |= (uint32_t)value << 8;
+ } else if (reg == PDDDR) {
+ portDirections &= 0xFFFFFF00;
+ portDirections |= (uint32_t)value;
+ } else if (reg == KSCAN) {
+ kScan = value;
+ } else {
+ // printf("RegWrite8 unknown:: pc=%08x reg=%03x value=%02x\n",
+ // getGPR(15)-4, reg, value);
+ }
}
void Emulator::writeReg32(uint32_t reg, uint32_t value) {
- if (reg == LCDCTL) {
- printf("LCD: ctl write %08x\n", value);
- lcdControl = value;
- } else if (reg == LCD_DBAR1) {
- printf("LCD: address write %08x\n", value);
- lcdAddress = value;
- } else if (reg == LCDT0) {
- printf("LCD: horz timing write %08x\n", value);
- } else if (reg == LCDT1) {
- printf("LCD: vert timing write %08x\n", value);
- } else if (reg == LCDT2) {
- printf("LCD: clocks write %08x\n", value);
- } else if (reg == INTENS) {
-// diffInterrupts(interruptMask, interruptMask | value);
- interruptMask |= value;
- } else if (reg == INTENC) {
-// diffInterrupts(interruptMask, interruptMask &~ value);
- interruptMask &= ~value;
- } else if (reg == HALT) {
- halted = true;
- // BLEOI = 0x410,
- // MCEOI = 0x414,
- } else if (reg == TEOI) {
- pendingInterrupts &= ~(1 << TINT);
- // TEOI = 0x418,
- // STFCLR = 0x41C,
- // E2EOI = 0x420,
- } else if ((reg & 0xF00) == 0x600) {
- uart1.writeReg32(reg & 0xFF, value);
- } else if ((reg & 0xF00) == 0x700) {
- uart2.writeReg32(reg & 0xFF, value);
- } else if (reg == SSDR) {
- if (value != 0)
- lastSSIRequest = (lastSSIRequest >> 8) | (value & 0xFF00);
- } else if (reg == TC1LOAD) {
- tc1.load(value);
- } else if (reg == TC1EOI) {
- pendingInterrupts &= ~(1 << TC1OI);
- } else if (reg == TC2LOAD) {
- tc2.load(value);
- } else if (reg == TC2EOI) {
- pendingInterrupts &= ~(1 << TC2OI);
- } else if (reg == RTCDRL) {
- rtc &= 0xFFFF0000;
- rtc |= (value & 0xFFFF);
- log("RTC write lower: %04x", value);
- } else if (reg == RTCDRU) {
- rtc &= 0x0000FFFF;
- rtc |= (value & 0xFFFF) << 16;
- log("RTC write upper: %04x", value);
- } else {
-// printf("RegWrite32 unknown:: pc=%08x reg=%03x value=%08x\n", getGPR(15)-4, reg, value);
- }
+ if (reg == LCDCTL) {
+ printf("LCD: ctl write %08x\n", value);
+ lcdControl = value;
+ } else if (reg == LCD_DBAR1) {
+ printf("LCD: address write %08x\n", value);
+ lcdAddress = value;
+ } else if (reg == LCDT0) {
+ printf("LCD: horz timing write %08x\n", value);
+ } else if (reg == LCDT1) {
+ printf("LCD: vert timing write %08x\n", value);
+ } else if (reg == LCDT2) {
+ printf("LCD: clocks write %08x\n", value);
+ } else if (reg == INTENS) {
+ // diffInterrupts(interruptMask, interruptMask | value);
+ interruptMask |= value;
+ } else if (reg == INTENC) {
+ // diffInterrupts(interruptMask, interruptMask &~ value);
+ interruptMask &= ~value;
+ } else if (reg == HALT) {
+ halted = true;
+ // BLEOI = 0x410,
+ // MCEOI = 0x414,
+ } else if (reg == TEOI) {
+ pendingInterrupts &= ~(1 << TINT);
+ // TEOI = 0x418,
+ // STFCLR = 0x41C,
+ // E2EOI = 0x420,
+ } else if ((reg & 0xF00) == 0x600) {
+ uart1.writeReg32(reg & 0xFF, value);
+ } else if ((reg & 0xF00) == 0x700) {
+ uart2.writeReg32(reg & 0xFF, value);
+ } else if (reg == SSDR) {
+ if (value != 0)
+ lastSSIRequest = (lastSSIRequest >> 8) | (value & 0xFF00);
+ } else if (reg == TC1LOAD) {
+ tc1.load(value);
+ } else if (reg == TC1EOI) {
+ pendingInterrupts &= ~(1 << TC1OI);
+ } else if (reg == TC2LOAD) {
+ tc2.load(value);
+ } else if (reg == TC2EOI) {
+ pendingInterrupts &= ~(1 << TC2OI);
+ } else if (reg == RTCDRL) {
+ rtc &= 0xFFFF0000;
+ rtc |= (value & 0xFFFF);
+ log("RTC write lower: %04x", value);
+ } else if (reg == RTCDRU) {
+ rtc &= 0x0000FFFF;
+ rtc |= (value & 0xFFFF) << 16;
+ log("RTC write upper: %04x", value);
+ } else {
+ // printf("RegWrite32 unknown:: pc=%08x reg=%03x value=%08x\n",
+ // getGPR(15)-4, reg, value);
+ }
}
MaybeU32 Emulator::readPhysical(uint32_t physAddr, ValueSize valueSize) {
- uint8_t region = (physAddr >> 24) & 0xF1;
- if (valueSize == V8) {
- if (region == 0)
- return ROM[physAddr & 0xFFFFFF];
- else if (region == 0x10)
- return ROM2[physAddr & 0x3FFFF];
- else if (region == 0x20 && physAddr <= 0x20000FFF)
- return etna.readReg8(physAddr & 0xFFF);
- else if (region == 0x80 && physAddr <= 0x80000FFF)
- return readReg8(physAddr & 0xFFF);
+ uint8_t region = (physAddr >> 24) & 0xF1;
+ if (valueSize == V8) {
+ if (region == 0)
+ return ROM[physAddr & 0xFFFFFF];
+ else if (region == 0x10)
+ return ROM2[physAddr & 0x3FFFF];
+ else if (region == 0x20 && physAddr <= 0x20000FFF)
+ return etna.readReg8(physAddr & 0xFFF);
+ else if (region == 0x80 && physAddr <= 0x80000FFF)
+ return readReg8(physAddr & 0xFFF);
#if defined(INCLUDE_BANK1)
- else if (region == 0xC0)
- return MemoryBlockC0[physAddr & MemoryBlockMask];
- else if (region == 0xC1)
- return MemoryBlockC1[physAddr & MemoryBlockMask];
- else if (region == 0xD0)
- return MemoryBlockD0[physAddr & MemoryBlockMask];
- else if (region == 0xD1)
- return MemoryBlockD1[physAddr & MemoryBlockMask];
+ else if (region == 0xC0)
+ return MemoryBlockC0[physAddr & MemoryBlockMask];
+ else if (region == 0xC1)
+ return MemoryBlockC1[physAddr & MemoryBlockMask];
+ else if (region == 0xD0)
+ return MemoryBlockD0[physAddr & MemoryBlockMask];
+ else if (region == 0xD1)
+ return MemoryBlockD1[physAddr & MemoryBlockMask];
#elif defined(INCLUDE_D)
- else if (region == 0xC0 || region == 0xC1)
- return MemoryBlockC0[physAddr & MemoryBlockMask];
- else if (region == 0xD0 || region == 0xD1)
- return MemoryBlockD0[physAddr & MemoryBlockMask];
+ else if (region == 0xC0 || region == 0xC1)
+ return MemoryBlockC0[physAddr & MemoryBlockMask];
+ else if (region == 0xD0 || region == 0xD1)
+ return MemoryBlockD0[physAddr & MemoryBlockMask];
#else
- else if (region == 0xC0 || region == 0xC1 || region == 0xD0 || region == 0xD1)
- return MemoryBlockC0[physAddr & MemoryBlockMask];
+ else if (region == 0xC0 || region == 0xC1 || region == 0xD0 ||
+ region == 0xD1)
+ return MemoryBlockC0[physAddr & MemoryBlockMask];
#endif
- else if (region >= 0xC0)
- return 0xFF; // just throw accesses to unmapped RAM away
- } else {
- uint32_t result;
- if (region == 0)
- LOAD_32LE(result, physAddr & 0xFFFFFF, ROM);
- else if (region == 0x10)
- LOAD_32LE(result, physAddr & 0x3FFFF, ROM2);
- else if (region == 0x20 && physAddr <= 0x20000FFF)
- result = etna.readReg32(physAddr & 0xFFF);
- else if (region == 0x80 && physAddr <= 0x80000FFF)
- result = readReg32(physAddr & 0xFFF);
+ else if (region >= 0xC0)
+ return 0xFF; // just throw accesses to unmapped RAM away
+ } else {
+ uint32_t result;
+ if (region == 0)
+ LOAD_32LE(result, physAddr & 0xFFFFFF, ROM);
+ else if (region == 0x10)
+ LOAD_32LE(result, physAddr & 0x3FFFF, ROM2);
+ else if (region == 0x20 && physAddr <= 0x20000FFF)
+ result = etna.readReg32(physAddr & 0xFFF);
+ else if (region == 0x80 && physAddr <= 0x80000FFF)
+ result = readReg32(physAddr & 0xFFF);
#if defined(INCLUDE_BANK1)
- else if (region == 0xC0)
- LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockC0);
- else if (region == 0xC1)
- LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockC1);
- else if (region == 0xD0)
- LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockD0);
- else if (region == 0xD1)
- LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockD1);
+ else if (region == 0xC0)
+ LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockC0);
+ else if (region == 0xC1)
+ LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockC1);
+ else if (region == 0xD0)
+ LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockD0);
+ else if (region == 0xD1)
+ LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockD1);
#elif defined(INCLUDE_D)
- else if (region == 0xC0 || region == 0xC1)
- LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockC0);
- else if (region == 0xD0 || region == 0xD1)
- LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockD0);
+ else if (region == 0xC0 || region == 0xC1)
+ LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockC0);
+ else if (region == 0xD0 || region == 0xD1)
+ LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockD0);
#else
- else if (region == 0xC0 || region == 0xC1 || region == 0xD0 || region == 0xD1)
- LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockC0);
+ else if (region == 0xC0 || region == 0xC1 || region == 0xD0 ||
+ region == 0xD1)
+ LOAD_32LE(result, physAddr & MemoryBlockMask, MemoryBlockC0);
#endif
- else if (region >= 0xC0)
- return 0xFFFFFFFF; // just throw accesses to unmapped RAM away
- else
- return {};
- return result;
- }
-
- return {};
+ else if (region >= 0xC0)
+ return 0xFFFFFFFF; // just throw accesses to unmapped RAM away
+ else
+ return {};
+ return result;
+ }
+
+ return {};
}
-bool Emulator::writePhysical(uint32_t value, uint32_t physAddr, ValueSize valueSize) {
- uint8_t region = (physAddr >> 24) & 0xF1;
- if (valueSize == V8) {
+bool Emulator::writePhysical(uint32_t value, uint32_t physAddr,
+ ValueSize valueSize) {
+ uint8_t region = (physAddr >> 24) & 0xF1;
+ if (valueSize == V8) {
#if defined(INCLUDE_BANK1)
- if (region == 0xC0)
- MemoryBlockC0[physAddr & MemoryBlockMask] = (uint8_t)value;
- else if (region == 0xC1)
- MemoryBlockC1[physAddr & MemoryBlockMask] = (uint8_t)value;
- else if (region == 0xD0)
- MemoryBlockD0[physAddr & MemoryBlockMask] = (uint8_t)value;
- else if (region == 0xD1)
- MemoryBlockD1[physAddr & MemoryBlockMask] = (uint8_t)value;
+ if (region == 0xC0)
+ MemoryBlockC0[physAddr & MemoryBlockMask] = (uint8_t)value;
+ else if (region == 0xC1)
+ MemoryBlockC1[physAddr & MemoryBlockMask] = (uint8_t)value;
+ else if (region == 0xD0)
+ MemoryBlockD0[physAddr & MemoryBlockMask] = (uint8_t)value;
+ else if (region == 0xD1)
+ MemoryBlockD1[physAddr & MemoryBlockMask] = (uint8_t)value;
#elif defined(INCLUDE_D)
- if (region == 0xC0 || region == 0xC1)
- MemoryBlockC0[physAddr & MemoryBlockMask] = (uint8_t)value;
- else if (region == 0xD0 || region == 0xD1)
- MemoryBlockD0[physAddr & MemoryBlockMask] = (uint8_t)value;
+ if (region == 0xC0 || region == 0xC1)
+ MemoryBlockC0[physAddr & MemoryBlockMask] = (uint8_t)value;
+ else if (region == 0xD0 || region == 0xD1)
+ MemoryBlockD0[physAddr & MemoryBlockMask] = (uint8_t)value;
#else
- if (region == 0xC0 || region == 0xC1 || region == 0xD0 || region == 0xD1)
- MemoryBlockC0[physAddr & MemoryBlockMask] = (uint8_t)value;
+ if (region == 0xC0 || region == 0xC1 || region == 0xD0 || region == 0xD1)
+ MemoryBlockC0[physAddr & MemoryBlockMask] = (uint8_t)value;
#endif
- else if (region >= 0xC0)
- return true; // just throw accesses to unmapped RAM away
- else if (region == 0x20 && physAddr <= 0x20000FFF)
- etna.writeReg8(physAddr & 0xFFF, value);
- else if (region == 0x80 && physAddr <= 0x80000FFF)
- writeReg8(physAddr & 0xFFF, value);
- else
- return false;
- } else {
- uint8_t region = (physAddr >> 24) & 0xF1;
+ else if (region >= 0xC0)
+ return true; // just throw accesses to unmapped RAM away
+ else if (region == 0x20 && physAddr <= 0x20000FFF)
+ etna.writeReg8(physAddr & 0xFFF, value);
+ else if (region == 0x80 && physAddr <= 0x80000FFF)
+ writeReg8(physAddr & 0xFFF, value);
+ else
+ return false;
+ } else {
+ uint8_t region = (physAddr >> 24) & 0xF1;
#if defined(INCLUDE_BANK1)
- if (region == 0xC0)
- STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockC0);
- else if (region == 0xC1)
- STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockC1);
- else if (region == 0xD0)
- STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockD0);
- else if (region == 0xD1)
- STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockD1);
+ if (region == 0xC0)
+ STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockC0);
+ else if (region == 0xC1)
+ STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockC1);
+ else if (region == 0xD0)
+ STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockD0);
+ else if (region == 0xD1)
+ STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockD1);
#elif defined(INCLUDE_D)
- if (region == 0xC0 || region == 0xC1)
- STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockC0);
- else if (region == 0xD0 || region == 0xD1)
- STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockD0);
+ if (region == 0xC0 || region == 0xC1)
+ STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockC0);
+ else if (region == 0xD0 || region == 0xD1)
+ STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockD0);
#else
- if (region == 0xC0 || region == 0xC1 || region == 0xD0 || region == 0x01)
- STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockC0);
+ if (region == 0xC0 || region == 0xC1 || region == 0xD0 || region == 0x01)
+ STORE_32LE(value, physAddr & MemoryBlockMask, MemoryBlockC0);
#endif
- else if (region >= 0xC0)
- return true; // just throw accesses to unmapped RAM away
- else if (region == 0x20 && physAddr <= 0x20000FFF)
- etna.writeReg32(physAddr & 0xFFF, value);
- else if (region == 0x80 && physAddr <= 0x80000FFF)
- writeReg32(physAddr & 0xFFF, value);
- else
- return false;
- }
- return true;
+ else if (region >= 0xC0)
+ return true; // just throw accesses to unmapped RAM away
+ else if (region == 0x20 && physAddr <= 0x20000FFF)
+ etna.writeReg32(physAddr & 0xFFF, value);
+ else if (region == 0x80 && physAddr <= 0x80000FFF)
+ writeReg32(physAddr & 0xFFF, value);
+ else
+ return false;
+ }
+ return true;
}
-
-
void Emulator::configure() {
- if (configured) return;
- configured = true;
+ if (configured)
+ return;
+ configured = true;
- srand(1000);
+ srand(1000);
- uart1.cpu = this;
- uart2.cpu = this;
- memset(&tc1, 0, sizeof(tc1));
- memset(&tc2, 0, sizeof(tc1));
- tc1.clockSpeed = CLOCK_SPEED;
- tc2.clockSpeed = CLOCK_SPEED;
+ uart1.cpu = this;
+ uart2.cpu = this;
+ memset(&tc1, 0, sizeof(tc1));
+ memset(&tc2, 0, sizeof(tc1));
+ tc1.clockSpeed = CLOCK_SPEED;
+ tc2.clockSpeed = CLOCK_SPEED;
- nextTickAt = TICK_INTERVAL;
- tc1.nextTickAt = tc1.tickInterval();
- tc2.nextTickAt = tc2.tickInterval();
- rtc = getRTC();
+ nextTickAt = TICK_INTERVAL;
+ tc1.nextTickAt = tc1.tickInterval();
+ tc2.nextTickAt = tc2.tickInterval();
+ rtc = getRTC();
- reset();
+ reset();
}
-uint8_t *Emulator::getROMBuffer() {
- return ROM;
-}
-size_t Emulator::getROMSize() {
- return sizeof(ROM);
-}
-void Emulator::loadROM(uint8_t *buffer, size_t size) {
- memcpy(ROM, buffer, min(size, sizeof(ROM)));
+uint8_t* Emulator::getROMBuffer() { return ROM; }
+size_t Emulator::getROMSize() { return sizeof(ROM); }
+void Emulator::loadROM(uint8_t* buffer, size_t size) {
+ memcpy(ROM, buffer, min(size, sizeof(ROM)));
}
void Emulator::executeUntil(int64_t cycles) {
- if (!configured)
- configure();
-
- while (!asleep && passedCycles < cycles) {
- if (passedCycles >= nextTickAt) {
- // increment RTCDIV
- if ((pwrsr & 0x3F) == 0x3F) {
- rtc++;
- pwrsr &= ~0x3F;
- } else {
- pwrsr++;
- }
-
- nextTickAt += TICK_INTERVAL;
- pendingInterrupts |= (1<<TINT);
- }
- if (tc1.tick(passedCycles))
- pendingInterrupts |= (1<<TC1OI);
- if (tc2.tick(passedCycles))
- pendingInterrupts |= (1<<TC2OI);
-
- if ((pendingInterrupts & interruptMask & FIQ_INTERRUPTS) != 0 && canAcceptFIQ()) {
- requestFIQ();
- halted = false;
- }
- if ((pendingInterrupts & interruptMask & IRQ_INTERRUPTS) != 0 && canAcceptIRQ()) {
- requestIRQ();
- halted = false;
- }
-
- // what's running?
- if (halted) {
- // keep the clock moving
- // when does the next earliest thing happen?
- // this stops us from spinning needlessly
- int64_t nextEvent = nextTickAt;
- if (tc1.nextTickAt < nextEvent) nextEvent = tc1.nextTickAt;
- if (tc2.nextTickAt < nextEvent) nextEvent = tc2.nextTickAt;
- if (cycles < nextEvent) nextEvent = cycles;
- passedCycles = nextEvent;
- } else {
- if (auto v = virtToPhys(getGPR(15) - 0xC); v.has_value() && instructionReady())
- debugPC(v.value());
- passedCycles += tick();
+ if (!configured)
+ configure();
+
+ while (!asleep && passedCycles < cycles) {
+ if (passedCycles >= nextTickAt) {
+ // increment RTCDIV
+ if ((pwrsr & 0x3F) == 0x3F) {
+ rtc++;
+ pwrsr &= ~0x3F;
+ } else {
+ pwrsr++;
+ }
+
+ nextTickAt += TICK_INTERVAL;
+ pendingInterrupts |= (1 << TINT);
+ }
+ if (tc1.tick(passedCycles))
+ pendingInterrupts |= (1 << TC1OI);
+ if (tc2.tick(passedCycles))
+ pendingInterrupts |= (1 << TC2OI);
+
+ if ((pendingInterrupts & interruptMask & FIQ_INTERRUPTS) != 0 &&
+ canAcceptFIQ()) {
+ requestFIQ();
+ halted = false;
+ }
+ if ((pendingInterrupts & interruptMask & IRQ_INTERRUPTS) != 0 &&
+ canAcceptIRQ()) {
+ requestIRQ();
+ halted = false;
+ }
+
+ // what's running?
+ if (halted) {
+ // keep the clock moving
+ // when does the next earliest thing happen?
+ // this stops us from spinning needlessly
+ int64_t nextEvent = nextTickAt;
+ if (tc1.nextTickAt < nextEvent)
+ nextEvent = tc1.nextTickAt;
+ if (tc2.nextTickAt < nextEvent)
+ nextEvent = tc2.nextTickAt;
+ if (cycles < nextEvent)
+ nextEvent = cycles;
+ passedCycles = nextEvent;
+ } else {
+ if (auto v = virtToPhys(getGPR(15) - 0xC);
+ v.has_value() && instructionReady())
+ debugPC(v.value());
+ passedCycles += tick();
#ifndef __EMSCRIPTEN__
- uint32_t new_pc = getGPR(15) - 0xC;
- if (_breakpoints.find(new_pc) != _breakpoints.end()) {
- log("⚠️ Breakpoint triggered at %08x!", new_pc);
- return;
- }
+ uint32_t new_pc = getGPR(15) - 0xC;
+ if (_breakpoints.find(new_pc) != _breakpoints.end()) {
+ log("⚠️ Breakpoint triggered at %08x!", new_pc);
+ return;
+ }
#endif
- }
- }
+ }
+ }
}
-
-const char *Emulator::identifyObjectCon(uint32_t ptr) {
- if (ptr == readVirtualDebug(0x80000980, V32).value()) return "process";
- if (ptr == readVirtualDebug(0x80000984, V32).value()) return "thread";
- if (ptr == readVirtualDebug(0x80000988, V32).value()) return "chunk";
-// if (ptr == readVirtualDebug(0x8000098C, V32).value()) return "semaphore";
-// if (ptr == readVirtualDebug(0x80000990, V32).value()) return "mutex";
- if (ptr == readVirtualDebug(0x80000994, V32).value()) return "logicaldevice";
- if (ptr == readVirtualDebug(0x80000998, V32).value()) return "physicaldevice";
- if (ptr == readVirtualDebug(0x8000099C, V32).value()) return "channel";
- if (ptr == readVirtualDebug(0x800009A0, V32).value()) return "server";
-// if (ptr == readVirtualDebug(0x800009A4, V32).value()) return "unk9A4"; // name always null
- if (ptr == readVirtualDebug(0x800009AC, V32).value()) return "library";
-// if (ptr == readVirtualDebug(0x800009B0, V32).value()) return "unk9B0"; // name always null
-// if (ptr == readVirtualDebug(0x800009B4, V32).value()) return "unk9B4"; // name always null
- return NULL;
+const char* Emulator::identifyObjectCon(uint32_t ptr) {
+ if (ptr == readVirtualDebug(0x80000980, V32).value())
+ return "process";
+ if (ptr == readVirtualDebug(0x80000984, V32).value())
+ return "thread";
+ if (ptr == readVirtualDebug(0x80000988, V32).value())
+ return "chunk";
+ // if (ptr == readVirtualDebug(0x8000098C, V32).value()) return
+ //"semaphore"; if (ptr == readVirtualDebug(0x80000990, V32).value())
+ //return "mutex";
+ if (ptr == readVirtualDebug(0x80000994, V32).value())
+ return "logicaldevice";
+ if (ptr == readVirtualDebug(0x80000998, V32).value())
+ return "physicaldevice";
+ if (ptr == readVirtualDebug(0x8000099C, V32).value())
+ return "channel";
+ if (ptr == readVirtualDebug(0x800009A0, V32).value())
+ return "server";
+ // if (ptr == readVirtualDebug(0x800009A4, V32).value()) return "unk9A4";
+ //// name always null
+ if (ptr == readVirtualDebug(0x800009AC, V32).value())
+ return "library";
+ // if (ptr == readVirtualDebug(0x800009B0, V32).value()) return "unk9B0";
+ //// name always null if (ptr == readVirtualDebug(0x800009B4,
+ ///V32).value())
+ // return "unk9B4"; // name always null
+ return NULL;
}
-void Emulator::fetchStr(uint32_t str, char *buf) {
- if (str == 0) {
- strcpy(buf, "<NULL>");
- return;
- }
- int size = readVirtualDebug(str, V32).value();
- for (int i = 0; i < size; i++) {
- buf[i] = readVirtualDebug(str + 4 + i, V8).value();
- }
- buf[size] = 0;
+void Emulator::fetchStr(uint32_t str, char* buf) {
+ if (str == 0) {
+ strcpy(buf, "<NULL>");
+ return;
+ }
+ int size = readVirtualDebug(str, V32).value();
+ for (int i = 0; i < size; i++) {
+ buf[i] = readVirtualDebug(str + 4 + i, V8).value();
+ }
+ buf[size] = 0;
}
-void Emulator::fetchName(uint32_t obj, char *buf) {
- fetchStr(readVirtualDebug(obj + 0x10, V32).value(), buf);
+void Emulator::fetchName(uint32_t obj, char* buf) {
+ fetchStr(readVirtualDebug(obj + 0x10, V32).value(), buf);
}
-void Emulator::fetchProcessFilename(uint32_t obj, char *buf) {
- fetchStr(readVirtualDebug(obj + 0x3C, V32).value(), buf);
+void Emulator::fetchProcessFilename(uint32_t obj, char* buf) {
+ fetchStr(readVirtualDebug(obj + 0x3C, V32).value(), buf);
}
void Emulator::debugPC(uint32_t pc) {
- char objName[1000];
- if (pc == 0x2CBC4) {
- // CObjectCon::AddL()
- uint32_t container = getGPR(0);
- uint32_t obj = getGPR(1);
- const char *wut = identifyObjectCon(container);
- if (wut) {
- fetchName(obj, objName);
- if (strcmp(wut, "process") == 0) {
- char procName[1000];
- fetchProcessFilename(obj, procName);
- log("OBJS: added %s at %08x <%s> <%s>", wut, obj, objName, procName);
- } else {
- log("OBJS: added %s at %08x <%s>", wut, obj, objName);
- }
- }
- }
-
- if (pc == 0x6D8) {
- uint32_t virtAddr = getGPR(0);
- uint32_t physAddr = getGPR(1);
- uint32_t btIndex = getGPR(2);
- uint32_t regionSize = getGPR(3);
- log("KERNEL MMU SECTION: v:%08x p:%08x size:%08x idx:%02x",
- virtAddr, physAddr, regionSize, btIndex);
- }
- if (pc == 0x710) {
- uint32_t virtAddr = getGPR(0);
- uint32_t physAddr = getGPR(1);
- uint32_t btIndex = getGPR(2);
- uint32_t regionSize = getGPR(3);
- uint32_t pageTableA = getGPR(4);
- uint32_t pageTableB = getGPR(5);
- log("KERNEL MMU PAGES: v:%08x p:%08x size:%08x idx:%02x tableA:%08x tableB:%08x",
- virtAddr, physAddr, regionSize, btIndex, pageTableA, pageTableB);
- }
-
- if (pc == 0x1576C) {
- uint32_t rawEvent = getGPR(0);
- uint32_t evtType = readVirtualDebug(rawEvent, V32).value_or(0);
- uint32_t evtTick = readVirtualDebug(rawEvent + 4, V32).value_or(0);
- uint32_t evtParamA = readVirtualDebug(rawEvent + 8, V32).value_or(0);
- uint32_t evtParamB = readVirtualDebug(rawEvent + 0xC, V32).value_or(0);
- const char *n = "???";
- switch (evtType) {
- case 0: n = "ENone"; break;
- case 1: n = "EPointerMove"; break;
- case 2: n = "EPointerSwitchOn"; break;
- case 3: n = "EKeyDown"; break;
- case 4: n = "EKeyUp"; break;
- case 5: n = "ERedraw"; break;
- case 6: n = "ESwitchOn"; break;
- case 7: n = "EActive"; break;
- case 8: n = "EInactive"; break;
- case 9: n = "EUpdateModifiers"; break;
- case 10: n = "EButton1Down"; break;
- case 11: n = "EButton1Up"; break;
- case 12: n = "EButton2Down"; break;
- case 13: n = "EButton2Up"; break;
- case 14: n = "EButton3Down"; break;
- case 15: n = "EButton3Up"; break;
- case 16: n = "ESwitchOff"; break;
- }
- log("EVENT %s: tick=%d params=%d,%d", n, evtTick, evtParamA, evtParamB);
- }
+ char objName[1000];
+ if (pc == 0x2CBC4) {
+ // CObjectCon::AddL()
+ uint32_t container = getGPR(0);
+ uint32_t obj = getGPR(1);
+ const char* wut = identifyObjectCon(container);
+ if (wut) {
+ fetchName(obj, objName);
+ if (strcmp(wut, "process") == 0) {
+ char procName[1000];
+ fetchProcessFilename(obj, procName);
+ log("OBJS: added %s at %08x <%s> <%s>", wut, obj, objName, procName);
+ } else {
+ log("OBJS: added %s at %08x <%s>", wut, obj, objName);
+ }
+ }
+ }
+
+ if (pc == 0x6D8) {
+ uint32_t virtAddr = getGPR(0);
+ uint32_t physAddr = getGPR(1);
+ uint32_t btIndex = getGPR(2);
+ uint32_t regionSize = getGPR(3);
+ log("KERNEL MMU SECTION: v:%08x p:%08x size:%08x idx:%02x", virtAddr,
+ physAddr, regionSize, btIndex);
+ }
+ if (pc == 0x710) {
+ uint32_t virtAddr = getGPR(0);
+ uint32_t physAddr = getGPR(1);
+ uint32_t btIndex = getGPR(2);
+ uint32_t regionSize = getGPR(3);
+ uint32_t pageTableA = getGPR(4);
+ uint32_t pageTableB = getGPR(5);
+ log("KERNEL MMU PAGES: v:%08x p:%08x size:%08x idx:%02x tableA:%08x "
+ "tableB:%08x",
+ virtAddr, physAddr, regionSize, btIndex, pageTableA, pageTableB);
+ }
+
+ if (pc == 0x1576C) {
+ uint32_t rawEvent = getGPR(0);
+ uint32_t evtType = readVirtualDebug(rawEvent, V32).value_or(0);
+ uint32_t evtTick = readVirtualDebug(rawEvent + 4, V32).value_or(0);
+ uint32_t evtParamA = readVirtualDebug(rawEvent + 8, V32).value_or(0);
+ uint32_t evtParamB = readVirtualDebug(rawEvent + 0xC, V32).value_or(0);
+ const char* n = "???";
+ switch (evtType) {
+ case 0:
+ n = "ENone";
+ break;
+ case 1:
+ n = "EPointerMove";
+ break;
+ case 2:
+ n = "EPointerSwitchOn";
+ break;
+ case 3:
+ n = "EKeyDown";
+ break;
+ case 4:
+ n = "EKeyUp";
+ break;
+ case 5:
+ n = "ERedraw";
+ break;
+ case 6:
+ n = "ESwitchOn";
+ break;
+ case 7:
+ n = "EActive";
+ break;
+ case 8:
+ n = "EInactive";
+ break;
+ case 9:
+ n = "EUpdateModifiers";
+ break;
+ case 10:
+ n = "EButton1Down";
+ break;
+ case 11:
+ n = "EButton1Up";
+ break;
+ case 12:
+ n = "EButton2Down";
+ break;
+ case 13:
+ n = "EButton2Up";
+ break;
+ case 14:
+ n = "EButton3Down";
+ break;
+ case 15:
+ n = "EButton3Up";
+ break;
+ case 16:
+ n = "ESwitchOff";
+ break;
+ }
+ log("EVENT %s: tick=%d params=%d,%d", n, evtTick, evtParamA, evtParamB);
+ }
}
-
-const char *Emulator::getDeviceName() const { return "Series 5mx"; }
-int Emulator::getDigitiserWidth() const { return 695; }
+const char* Emulator::getDeviceName() const { return "Series 5mx"; }
+int Emulator::getDigitiserWidth() const { return 695; }
int Emulator::getDigitiserHeight() const { return 280; }
-int Emulator::getLCDOffsetX() const { return 45; }
-int Emulator::getLCDOffsetY() const { return 5; }
-int Emulator::getLCDWidth() const { return 640; }
-int Emulator::getLCDHeight() const { return 240; }
+int Emulator::getLCDOffsetX() const { return 45; }
+int Emulator::getLCDOffsetY() const { return 5; }
+int Emulator::getLCDWidth() const { return 640; }
+int Emulator::getLCDHeight() const { return 240; }
// TODO move this elsewhere
static bool initRgbValues = false;
static uint32_t rgbValues[16];
-void Emulator::readLCDIntoBuffer(uint8_t **lines, bool is32BitOutput) const {
- if (!initRgbValues) {
- initRgbValues = true;
- for (int i = 0; i < 16; i++) {
- int r = (0x99 * i) / 15;
- int g = (0xAA * i) / 15;
- int b = (0x88 * i) / 15;
- rgbValues[15 - i] = r | (g << 8) | (b << 16) | 0xFF000000;
- }
- }
-
- if ((lcdAddress >> 24) == 0xC0) {
- const uint8_t *lcdBuf = &MemoryBlockC0[lcdAddress & MemoryBlockMask];
- int width = 640, height = 240;
-
- // fetch palette
- int bpp = 1 << (lcdBuf[1] >> 4);
- int ppb = 8 / bpp;
- uint16_t palette[16];
- for (int i = 0; i < 16; i++)
- palette[i] = lcdBuf[i*2] | ((lcdBuf[i*2+1] << 8) & 0xF00);
-
- // build our image out
- int lineWidth = (width * bpp) / 8;
- for (int y = 0; y < height; y++) {
- int lineOffs = 0x20 + (lineWidth * y);
- for (int x = 0; x < width; x++) {
- uint8_t byte = lcdBuf[lineOffs + (x / ppb)];
- int shift = (x & (ppb - 1)) * bpp;
- int mask = (1 << bpp) - 1;
- int palIdx = (byte >> shift) & mask;
- int palValue = palette[palIdx];
-
- if (is32BitOutput) {
- auto line = (uint32_t *)lines[y];
- line[x] = rgbValues[palValue];
- } else {
- palValue |= (palValue << 4);
- lines[y][x] = palValue ^ 0xFF;
- }
- }
- }
- }
+void Emulator::readLCDIntoBuffer(uint8_t** lines, bool is32BitOutput) const {
+ if (!initRgbValues) {
+ initRgbValues = true;
+ for (int i = 0; i < 16; i++) {
+ int r = (0x99 * i) / 15;
+ int g = (0xAA * i) / 15;
+ int b = (0x88 * i) / 15;
+ rgbValues[15 - i] = r | (g << 8) | (b << 16) | 0xFF000000;
+ }
+ }
+
+ if ((lcdAddress >> 24) == 0xC0) {
+ const uint8_t* lcdBuf = &MemoryBlockC0[lcdAddress & MemoryBlockMask];
+ int width = 640, height = 240;
+
+ // fetch palette
+ int bpp = 1 << (lcdBuf[1] >> 4);
+ int ppb = 8 / bpp;
+ uint16_t palette[16];
+ for (int i = 0; i < 16; i++)
+ palette[i] = lcdBuf[i * 2] | ((lcdBuf[i * 2 + 1] << 8) & 0xF00);
+
+ // build our image out
+ int lineWidth = (width * bpp) / 8;
+ for (int y = 0; y < height; y++) {
+ int lineOffs = 0x20 + (lineWidth * y);
+ for (int x = 0; x < width; x++) {
+ uint8_t byte = lcdBuf[lineOffs + (x / ppb)];
+ int shift = (x & (ppb - 1)) * bpp;
+ int mask = (1 << bpp) - 1;
+ int palIdx = (byte >> shift) & mask;
+ int palValue = palette[palIdx];
+
+ if (is32BitOutput) {
+ auto line = (uint32_t*)lines[y];
+ line[x] = rgbValues[palValue];
+ } else {
+ palValue |= (palValue << 4);
+ lines[y][x] = palValue ^ 0xFF;
+ }
+ }
+ }
+ }
}
-
void Emulator::diffPorts(uint32_t oldval, uint32_t newval) {
- uint32_t changes = oldval ^ newval;
- if (changes & 1) log("PRT codec enable: %d", newval&1);
- if (changes & 2) log("PRT audio amp enable: %d", newval&2);
- if (changes & 4) log("PRT lcd power: %d", newval&4);
- if (changes & 8) log("PRT etna door: %d", newval&8);
- if (changes & 0x10) log("PRT sled: %d", newval&0x10);
- if (changes & 0x20) log("PRT pump pwr2: %d", newval&0x20);
- if (changes & 0x40) log("PRT pump pwr1: %d", newval&0x40);
- if (changes & 0x80) log("PRT etna err: %d", newval&0x80);
- if (changes & 0x100) log("PRT rs-232 rts: %d", newval&0x100);
- if (changes & 0x200) log("PRT rs-232 dtr toggle: %d", newval&0x200);
- if (changes & 0x400) log("PRT disable power led: %d", newval&0x400);
- if (changes & 0x800) log("PRT enable uart1: %d", newval&0x800);
- if (changes & 0x1000) log("PRT lcd backlight: %d", newval&0x1000);
- if (changes & 0x2000) log("PRT enable uart0: %d", newval&0x2000);
- if (changes & 0x4000) log("PRT dictaphone: %d", newval&0x4000);
-// PROM read process makes this super spammy in stdout
-// if (changes & 0x10000) log("PRT EECS: %d", newval&0x10000);
-// if (changes & 0x20000) log("PRT EECLK: %d", newval&0x20000);
- if (changes & 0x40000) log("PRT contrast0: %d", newval&0x40000);
- if (changes & 0x80000) log("PRT contrast1: %d", newval&0x80000);
- if (changes & 0x100000) log("PRT contrast2: %d", newval&0x100000);
- if (changes & 0x200000) log("PRT contrast3: %d", newval&0x200000);
- if (changes & 0x400000) log("PRT case open: %d", newval&0x400000);
- if (changes & 0x800000) log("PRT etna cf power: %d", newval&0x800000);
+ uint32_t changes = oldval ^ newval;
+ if (changes & 1)
+ log("PRT codec enable: %d", newval & 1);
+ if (changes & 2)
+ log("PRT audio amp enable: %d", newval & 2);
+ if (changes & 4)
+ log("PRT lcd power: %d", newval & 4);
+ if (changes & 8)
+ log("PRT etna door: %d", newval & 8);
+ if (changes & 0x10)
+ log("PRT sled: %d", newval & 0x10);
+ if (changes & 0x20)
+ log("PRT pump pwr2: %d", newval & 0x20);
+ if (changes & 0x40)
+ log("PRT pump pwr1: %d", newval & 0x40);
+ if (changes & 0x80)
+ log("PRT etna err: %d", newval & 0x80);
+ if (changes & 0x100)
+ log("PRT rs-232 rts: %d", newval & 0x100);
+ if (changes & 0x200)
+ log("PRT rs-232 dtr toggle: %d", newval & 0x200);
+ if (changes & 0x400)
+ log("PRT disable power led: %d", newval & 0x400);
+ if (changes & 0x800)
+ log("PRT enable uart1: %d", newval & 0x800);
+ if (changes & 0x1000)
+ log("PRT lcd backlight: %d", newval & 0x1000);
+ if (changes & 0x2000)
+ log("PRT enable uart0: %d", newval & 0x2000);
+ if (changes & 0x4000)
+ log("PRT dictaphone: %d", newval & 0x4000);
+ // PROM read process makes this super spammy in stdout
+ // if (changes & 0x10000) log("PRT EECS: %d", newval&0x10000);
+ // if (changes & 0x20000) log("PRT EECLK: %d", newval&0x20000);
+ if (changes & 0x40000)
+ log("PRT contrast0: %d", newval & 0x40000);
+ if (changes & 0x80000)
+ log("PRT contrast1: %d", newval & 0x80000);
+ if (changes & 0x100000)
+ log("PRT contrast2: %d", newval & 0x100000);
+ if (changes & 0x200000)
+ log("PRT contrast3: %d", newval & 0x200000);
+ if (changes & 0x400000)
+ log("PRT case open: %d", newval & 0x400000);
+ if (changes & 0x800000)
+ log("PRT etna cf power: %d", newval & 0x800000);
}
void Emulator::diffInterrupts(uint16_t oldval, uint16_t newval) {
- uint16_t changes = oldval ^ newval;
- if (changes & 1) log("INTCHG external=%d", newval & 1);
- if (changes & 2) log("INTCHG lowbat=%d", newval & 2);
- if (changes & 4) log("INTCHG watchdog=%d", newval & 4);
- if (changes & 8) log("INTCHG mediachg=%d", newval & 8);
- if (changes & 0x10) log("INTCHG codec=%d", newval & 0x10);
- if (changes & 0x20) log("INTCHG ext1=%d", newval & 0x20);
- if (changes & 0x40) log("INTCHG ext2=%d", newval & 0x40);
- if (changes & 0x80) log("INTCHG ext3=%d", newval & 0x80);
- if (changes & 0x100) log("INTCHG timer1=%d", newval & 0x100);
- if (changes & 0x200) log("INTCHG timer2=%d", newval & 0x200);
- if (changes & 0x400) log("INTCHG rtcmatch=%d", newval & 0x400);
- if (changes & 0x800) log("INTCHG tick=%d", newval & 0x800);
- if (changes & 0x1000) log("INTCHG uart1=%d", newval & 0x1000);
- if (changes & 0x2000) log("INTCHG uart2=%d", newval & 0x2000);
- if (changes & 0x4000) log("INTCHG lcd=%d", newval & 0x4000);
- if (changes & 0x8000) log("INTCHG spi=%d", newval & 0x8000);
+ uint16_t changes = oldval ^ newval;
+ if (changes & 1)
+ log("INTCHG external=%d", newval & 1);
+ if (changes & 2)
+ log("INTCHG lowbat=%d", newval & 2);
+ if (changes & 4)
+ log("INTCHG watchdog=%d", newval & 4);
+ if (changes & 8)
+ log("INTCHG mediachg=%d", newval & 8);
+ if (changes & 0x10)
+ log("INTCHG codec=%d", newval & 0x10);
+ if (changes & 0x20)
+ log("INTCHG ext1=%d", newval & 0x20);
+ if (changes & 0x40)
+ log("INTCHG ext2=%d", newval & 0x40);
+ if (changes & 0x80)
+ log("INTCHG ext3=%d", newval & 0x80);
+ if (changes & 0x100)
+ log("INTCHG timer1=%d", newval & 0x100);
+ if (changes & 0x200)
+ log("INTCHG timer2=%d", newval & 0x200);
+ if (changes & 0x400)
+ log("INTCHG rtcmatch=%d", newval & 0x400);
+ if (changes & 0x800)
+ log("INTCHG tick=%d", newval & 0x800);
+ if (changes & 0x1000)
+ log("INTCHG uart1=%d", newval & 0x1000);
+ if (changes & 0x2000)
+ log("INTCHG uart2=%d", newval & 0x2000);
+ if (changes & 0x4000)
+ log("INTCHG lcd=%d", newval & 0x4000);
+ if (changes & 0x8000)
+ log("INTCHG spi=%d", newval & 0x8000);
}
-
uint32_t Emulator::readKeyboard() {
- if (kScan & 8) {
- // Select one keyboard
- return keyboardColumns[kScan & 7];
- } else if (kScan == 0) {
- // Report all columns combined
- uint8_t val = 0;
- for (int i = 0; i < 8; i++)
- val |= keyboardColumns[i];
- return val;
- } else {
- return 0;
- }
+ if (kScan & 8) {
+ // Select one keyboard
+ return keyboardColumns[kScan & 7];
+ } else if (kScan == 0) {
+ // Report all columns combined
+ uint8_t val = 0;
+ for (int i = 0; i < 8; i++)
+ val |= keyboardColumns[i];
+ return val;
+ } else {
+ return 0;
+ }
}
void Emulator::setKeyboardKey(EpocKey key, bool value) {
- int idx = -1;
-#define KEY(column, bit) idx = (column << 8) | (1 << bit); break
-
- switch ((int)key) {
- case EStdKeyDictaphoneRecord: KEY(0, 6);
- case '1': KEY(0, 5);
- case '2': KEY(0, 4);
- case '3': KEY(0, 3);
- case '4': KEY(0, 2);
- case '5': KEY(0, 1);
- case '6': KEY(0, 0);
-
- case EStdKeyDictaphonePlay: KEY(1, 6);
- case '7': KEY(1, 5);
- case '8': KEY(1, 4);
- case '9': KEY(1, 3);
- case '0': KEY(1, 2);
- case EStdKeyBackspace: KEY(1, 1);
- case EStdKeySingleQuote: KEY(1, 0);
-
- case EStdKeyEscape: KEY(2, 6);
- case 'Q': KEY(2, 5);
- case 'W': KEY(2, 4);
- case 'E': KEY(2, 3);
- case 'R': KEY(2, 2);
- case 'T': KEY(2, 1);
- case 'Y': KEY(2, 0);
-
- case EStdKeyMenu: KEY(3, 6);
- case 'U': KEY(3, 5);
- case 'I': KEY(3, 4);
- case 'O': KEY(3, 3);
- case 'P': KEY(3, 2);
- case 'L': KEY(3, 1);
- case EStdKeyEnter: KEY(3, 0);
-
- case EStdKeyLeftCtrl: KEY(4, 6);
- case EStdKeyTab: KEY(4, 5);
- case 'A': KEY(4, 4);
- case 'S': KEY(4, 3);
- case 'D': KEY(4, 2);
- case 'F': KEY(4, 1);
- case 'G': KEY(4, 0);
-
- case EStdKeyLeftFunc: KEY(5, 6);
- case 'H': KEY(5, 5);
- case 'J': KEY(5, 4);
- case 'K': KEY(5, 3);
- case 'M': KEY(5, 2);
- case EStdKeyFullStop: KEY(5, 1);
- case EStdKeyDownArrow: KEY(5, 0);
-
- case EStdKeyRightShift: KEY(6, 6);
- case 'Z': KEY(6, 5);
- case 'X': KEY(6, 4);
- case 'C': KEY(6, 3);
- case 'V': KEY(6, 2);
- case 'B': KEY(6, 1);
- case 'N': KEY(6, 0);
-
- case EStdKeyLeftShift: KEY(7, 6);
- case EStdKeyDictaphoneStop: KEY(7, 5);
- case EStdKeySpace: KEY(7, 4);
- case EStdKeyUpArrow: KEY(7, 3);
- case EStdKeyComma: KEY(7, 2);
- case EStdKeyLeftArrow: KEY(7, 1);
- case EStdKeyRightArrow: KEY(7, 0);
- }
-
- if (idx >= 0) {
- if (value)
- keyboardColumns[idx >> 8] |= (idx & 0xFF);
- else
- keyboardColumns[idx >> 8] &= ~(idx & 0xFF);
- }
+ int idx = -1;
+#define KEY(column, bit) \
+ idx = (column << 8) | (1 << bit); \
+ break
+
+ switch ((int)key) {
+ case EStdKeyDictaphoneRecord:
+ KEY(0, 6);
+ case '1':
+ KEY(0, 5);
+ case '2':
+ KEY(0, 4);
+ case '3':
+ KEY(0, 3);
+ case '4':
+ KEY(0, 2);
+ case '5':
+ KEY(0, 1);
+ case '6':
+ KEY(0, 0);
+
+ case EStdKeyDictaphonePlay:
+ KEY(1, 6);
+ case '7':
+ KEY(1, 5);
+ case '8':
+ KEY(1, 4);
+ case '9':
+ KEY(1, 3);
+ case '0':
+ KEY(1, 2);
+ case EStdKeyBackspace:
+ KEY(1, 1);
+ case EStdKeySingleQuote:
+ KEY(1, 0);
+
+ case EStdKeyEscape:
+ KEY(2, 6);
+ case 'Q':
+ KEY(2, 5);
+ case 'W':
+ KEY(2, 4);
+ case 'E':
+ KEY(2, 3);
+ case 'R':
+ KEY(2, 2);
+ case 'T':
+ KEY(2, 1);
+ case 'Y':
+ KEY(2, 0);
+
+ case EStdKeyMenu:
+ KEY(3, 6);
+ case 'U':
+ KEY(3, 5);
+ case 'I':
+ KEY(3, 4);
+ case 'O':
+ KEY(3, 3);
+ case 'P':
+ KEY(3, 2);
+ case 'L':
+ KEY(3, 1);
+ case EStdKeyEnter:
+ KEY(3, 0);
+
+ case EStdKeyLeftCtrl:
+ KEY(4, 6);
+ case EStdKeyTab:
+ KEY(4, 5);
+ case 'A':
+ KEY(4, 4);
+ case 'S':
+ KEY(4, 3);
+ case 'D':
+ KEY(4, 2);
+ case 'F':
+ KEY(4, 1);
+ case 'G':
+ KEY(4, 0);
+
+ case EStdKeyLeftFunc:
+ KEY(5, 6);
+ case 'H':
+ KEY(5, 5);
+ case 'J':
+ KEY(5, 4);
+ case 'K':
+ KEY(5, 3);
+ case 'M':
+ KEY(5, 2);
+ case EStdKeyFullStop:
+ KEY(5, 1);
+ case EStdKeyDownArrow:
+ KEY(5, 0);
+
+ case EStdKeyRightShift:
+ KEY(6, 6);
+ case 'Z':
+ KEY(6, 5);
+ case 'X':
+ KEY(6, 4);
+ case 'C':
+ KEY(6, 3);
+ case 'V':
+ KEY(6, 2);
+ case 'B':
+ KEY(6, 1);
+ case 'N':
+ KEY(6, 0);
+
+ case EStdKeyLeftShift:
+ KEY(7, 6);
+ case EStdKeyDictaphoneStop:
+ KEY(7, 5);
+ case EStdKeySpace:
+ KEY(7, 4);
+ case EStdKeyUpArrow:
+ KEY(7, 3);
+ case EStdKeyComma:
+ KEY(7, 2);
+ case EStdKeyLeftArrow:
+ KEY(7, 1);
+ case EStdKeyRightArrow:
+ KEY(7, 0);
+ }
+
+ if (idx >= 0) {
+ if (value)
+ keyboardColumns[idx >> 8] |= (idx & 0xFF);
+ else
+ keyboardColumns[idx >> 8] &= ~(idx & 0xFF);
+ }
}
void Emulator::updateTouchInput(int32_t x, int32_t y, bool down) {
- pendingInterrupts &= ~(1 << EINT3);
- if (down)
- pendingInterrupts |= (1 << EINT3);
- touchX = x;
- touchY = y;
+ pendingInterrupts &= ~(1 << EINT3);
+ if (down)
+ pendingInterrupts |= (1 << EINT3);
+ touchX = x;
+ touchY = y;
}
-}
+} // namespace Windermere
#pragma once
#include "emubase.h"
-#include "wind_defs.h"
-#include "hardware.h"
#include "etna.h"
+#include "hardware.h"
+#include "wind_defs.h"
namespace Windermere {
class Emulator : public EmuBase {
public:
- uint8_t ROM[0x1000000];
- uint8_t ROM2[0x40000];
- uint8_t MemoryBlockC0[0x800000];
- uint8_t MemoryBlockC1[0x800000];
- uint8_t MemoryBlockD0[0x800000];
- uint8_t MemoryBlockD1[0x800000];
- enum { MemoryBlockMask = 0x7FFFFF };
+ uint8_t ROM[0x1000000];
+ uint8_t ROM2[0x40000];
+ uint8_t MemoryBlockC0[0x800000];
+ uint8_t MemoryBlockC1[0x800000];
+ uint8_t MemoryBlockD0[0x800000];
+ uint8_t MemoryBlockD1[0x800000];
+ enum { MemoryBlockMask = 0x7FFFFF };
private:
- uint16_t pendingInterrupts = 0;
- uint16_t interruptMask = 0;
- uint32_t portValues = 0;
- uint32_t portDirections = 0;
- uint32_t pwrsr = 0x00002000; // cold start flag
- uint32_t lcdControl = 0;
- uint32_t lcdAddress = 0;
- uint32_t rtc = 0;
- uint16_t lastSSIRequest = 0;
- int ssiReadCounter = 0;
+ uint16_t pendingInterrupts = 0;
+ uint16_t interruptMask = 0;
+ uint32_t portValues = 0;
+ uint32_t portDirections = 0;
+ uint32_t pwrsr = 0x00002000; // cold start flag
+ uint32_t lcdControl = 0;
+ uint32_t lcdAddress = 0;
+ uint32_t rtc = 0;
+ uint16_t lastSSIRequest = 0;
+ int ssiReadCounter = 0;
- uint32_t kScan = 0;
- uint8_t keyboardColumns[8] = {0,0,0,0,0,0,0};
- int32_t touchX = 0, touchY = 0;
+ uint32_t kScan = 0;
+ uint8_t keyboardColumns[8] = {0, 0, 0, 0, 0, 0, 0};
+ int32_t touchX = 0, touchY = 0;
- Timer tc1, tc2;
- UART uart1, uart2;
- Etna etna;
- bool halted = false, asleep = false;
+ Timer tc1, tc2;
+ UART uart1, uart2;
+ Etna etna;
+ bool halted = false, asleep = false;
- uint32_t getRTC();
+ uint32_t getRTC();
- uint32_t readReg8(uint32_t reg);
- uint32_t readReg32(uint32_t reg);
- void writeReg8(uint32_t reg, uint8_t value);
- void writeReg32(uint32_t reg, uint32_t value);
+ uint32_t readReg8(uint32_t reg);
+ uint32_t readReg32(uint32_t reg);
+ void writeReg8(uint32_t reg, uint8_t value);
+ void writeReg32(uint32_t reg, uint32_t value);
public:
- MaybeU32 readPhysical(uint32_t physAddr, ValueSize valueSize) override;
- bool writePhysical(uint32_t value, uint32_t physAddr, ValueSize valueSize) override;
+ MaybeU32 readPhysical(uint32_t physAddr, ValueSize valueSize) override;
+ bool writePhysical(uint32_t value, uint32_t physAddr,
+ ValueSize valueSize) override;
private:
- bool configured = false;
- void configure();
+ bool configured = false;
+ void configure();
- const char *identifyObjectCon(uint32_t ptr);
- void fetchStr(uint32_t str, char *buf);
- void fetchName(uint32_t obj, char *buf);
- void fetchProcessFilename(uint32_t obj, char *buf);
- void debugPC(uint32_t pc);
- void diffPorts(uint32_t oldval, uint32_t newval);
- void diffInterrupts(uint16_t oldval, uint16_t newval);
- uint32_t readKeyboard();
+ const char* identifyObjectCon(uint32_t ptr);
+ void fetchStr(uint32_t str, char* buf);
+ void fetchName(uint32_t obj, char* buf);
+ void fetchProcessFilename(uint32_t obj, char* buf);
+ void debugPC(uint32_t pc);
+ void diffPorts(uint32_t oldval, uint32_t newval);
+ void diffInterrupts(uint16_t oldval, uint16_t newval);
+ uint32_t readKeyboard();
public:
- Emulator();
- uint8_t *getROMBuffer() override;
- size_t getROMSize() override;
- void loadROM(uint8_t *buffer, size_t size) override;
- void executeUntil(int64_t cycles) override;
- int32_t getClockSpeed() const override { return CLOCK_SPEED; }
- const char *getDeviceName() const override;
- int getDigitiserWidth() const override;
- int getDigitiserHeight() const override;
- int getLCDOffsetX() const override;
- int getLCDOffsetY() const override;
- int getLCDWidth() const override;
- int getLCDHeight() const override;
- void readLCDIntoBuffer(uint8_t **lines, bool is32BitOutput) const override;
- void setKeyboardKey(EpocKey key, bool value) override;
- void updateTouchInput(int32_t x, int32_t y, bool down) override;
+ Emulator();
+ uint8_t* getROMBuffer() override;
+ size_t getROMSize() override;
+ void loadROM(uint8_t* buffer, size_t size) override;
+ void executeUntil(int64_t cycles) override;
+ int32_t getClockSpeed() const override { return CLOCK_SPEED; }
+ const char* getDeviceName() const override;
+ int getDigitiserWidth() const override;
+ int getDigitiserHeight() const override;
+ int getLCDOffsetX() const override;
+ int getLCDOffsetY() const override;
+ int getLCDWidth() const override;
+ int getLCDHeight() const override;
+ void readLCDIntoBuffer(uint8_t** lines, bool is32BitOutput) const override;
+ void setKeyboardKey(EpocKey key, bool value) override;
+ void updateTouchInput(int32_t x, int32_t y, bool down) override;
};
-}
+} // namespace Windermere
+#include "../WindCore/clps7111.h"
+#include "../WindCore/windermere.h"
#include "mainwindow.h"
#include <QApplication>
#include <QFileDialog>
#include <QMessageBox>
-#include "../WindCore/clps7111.h"
-#include "../WindCore/windermere.h"
-int main(int argc, char *argv[])
-{
- QApplication a(argc, argv);
- auto args = a.arguments();
-
- QString romFile;
- if (args.length() > 1)
- romFile = args.last();
- else
- romFile = QFileDialog::getOpenFileName(nullptr, "Select a ROM");
- if (romFile.isNull()) return 0;
-
- // what do we have?
- QFile f(romFile);
- f.open(QFile::ReadOnly);
- auto buffer = f.readAll();
- f.close();
-
- if (buffer.size() < 0x400000) {
- QMessageBox::critical(nullptr, "WindEmu", "Invalid ROM file!");
- return 0;
- }
-
- EmuBase *emu = nullptr;
- uint8_t *romData = (uint8_t *)buffer.data();
-
- // parse this ROM to learn what hardware it's for
- int variantFile = *((uint32_t *)&romData[0x80 + 0x4C]) & 0xFFFFFFF;
- if (variantFile < (buffer.size() - 8)) {
- int variantImg = *((uint32_t *)&romData[variantFile + 4]) & 0xFFFFFFF;
- if (variantImg < (buffer.size() - 0x70)) {
- int variant = *((uint32_t *)&romData[variantImg + 0x60]);
-
- if (variant == 0x7060001) {
- // 5mx ROM
- emu = new Windermere::Emulator;
- } else if (variant == 0x5040001) {
- // Osaris ROM
- emu = new CLPS7111::Emulator;
- } else {
- QMessageBox::critical(nullptr, "WindEmu", "Unrecognised ROM file!");
- return 0;
- }
- }
- }
-
- emu->loadROM(romData, buffer.size());
- MainWindow w(emu);
- w.show();
-
- return a.exec();
+int main(int argc, char* argv[]) {
+ QApplication a(argc, argv);
+ auto args = a.arguments();
+
+ QString romFile;
+ if (args.length() > 1)
+ romFile = args.last();
+ else
+ romFile = QFileDialog::getOpenFileName(nullptr, "Select a ROM");
+ if (romFile.isNull())
+ return 0;
+
+ // what do we have?
+ QFile f(romFile);
+ f.open(QFile::ReadOnly);
+ auto buffer = f.readAll();
+ f.close();
+
+ if (buffer.size() < 0x400000) {
+ QMessageBox::critical(nullptr, "WindEmu", "Invalid ROM file!");
+ return 0;
+ }
+
+ EmuBase* emu = nullptr;
+ uint8_t* romData = (uint8_t*)buffer.data();
+
+ // parse this ROM to learn what hardware it's for
+ int variantFile = *((uint32_t*)&romData[0x80 + 0x4C]) & 0xFFFFFFF;
+ if (variantFile < (buffer.size() - 8)) {
+ int variantImg = *((uint32_t*)&romData[variantFile + 4]) & 0xFFFFFFF;
+ if (variantImg < (buffer.size() - 0x70)) {
+ int variant = *((uint32_t*)&romData[variantImg + 0x60]);
+
+ if (variant == 0x7060001) {
+ // 5mx ROM
+ emu = new Windermere::Emulator;
+ } else if (variant == 0x5040001) {
+ // Osaris ROM
+ emu = new CLPS7111::Emulator;
+ } else {
+ QMessageBox::critical(nullptr, "WindEmu", "Unrecognised ROM file!");
+ return 0;
+ }
+ }
+ }
+
+ emu->loadROM(romData, buffer.size());
+ MainWindow w(emu);
+ w.show();
+
+ return a.exec();
}
#include "mainwindow.h"
-#include "ui_mainwindow.h"
-#include <QTimer>
#include "../WindCore/decoder.h"
#include "clps7111.h"
+#include "ui_mainwindow.h"
+#include <QTimer>
-MainWindow::MainWindow(EmuBase *emu, QWidget *parent) :
- QMainWindow(parent),
- ui(new Ui::MainWindow),
- pdaScreen(emu),
- emu(emu)
-{
- ui->setupUi(this);
- ui->logView->setMaximumBlockCount(1000);
-
- elapsedTimer.start();
- emu->setLogger([&](const char *str) {
- QString fullStr = QStringLiteral("[%1] %2").arg(elapsedTimer.elapsed()).arg(str);
- ui->logView->appendPlainText(fullStr);
- });
-
- timer = new QTimer(this);
- timer->setInterval(1000/64);
- connect(timer, SIGNAL(timeout()), SLOT(execTimer()));
-
- pdaScreen.show();
-
- updateScreen();
-}
-
-MainWindow::~MainWindow()
-{
- delete ui;
-}
-
-void MainWindow::updateScreen()
-{
- ui->cycleCounter->setText(QString("Cycles: %1").arg(emu->currentCycles()));
-
- updateMemory();
-
- char flagDisplay[] = {
- (emu->getCPSR() & 0x80000000) ? 'N' : '-',
- (emu->getCPSR() & 0x40000000) ? 'Z' : '-',
- (emu->getCPSR() & 0x20000000) ? 'C' : '-',
- (emu->getCPSR() & 0x10000000) ? 'V' : '-',
- 0
- };
- const char *modeName = "???";
- switch (emu->getCPSR() & 0x1F) {
- case 0x10: modeName = "User"; break;
- case 0x11: modeName = "FIQ"; break;
- case 0x12: modeName = "IRQ"; break;
- case 0x13: modeName = "Supervisor"; break;
- case 0x17: modeName = "Abort"; break;
- case 0x1B: modeName = "Undefined"; break;
- }
-
- ui->regsLabel->setText(
- QString("R0: %1 / R1: %2 / R2: %3 / R3: %4 / R4: %5 / R5: %6 / R6: %7 / R7: %8\nR8: %9 / R9: %10 / R10:%11 / R11:%12 / R12:%13 / SP: %14 / LR: %15 / PC: %16\n%17 / Mode: %18")
- .arg(emu->getGPR(0), 8, 16)
- .arg(emu->getGPR(1), 8, 16)
- .arg(emu->getGPR(2), 8, 16)
- .arg(emu->getGPR(3), 8, 16)
- .arg(emu->getGPR(4), 8, 16)
- .arg(emu->getGPR(5), 8, 16)
- .arg(emu->getGPR(6), 8, 16)
- .arg(emu->getGPR(7), 8, 16)
- .arg(emu->getGPR(8), 8, 16)
- .arg(emu->getGPR(9), 8, 16)
- .arg(emu->getGPR(10), 8, 16)
- .arg(emu->getGPR(11), 8, 16)
- .arg(emu->getGPR(12), 8, 16)
- .arg(emu->getGPR(13), 8, 16)
- .arg(emu->getGPR(14), 8, 16)
- .arg(emu->getGPR(15), 8, 16)
- .arg(flagDisplay)
- .arg(modeName)
- );
-
- // show a crude disassembly
- const int context = 8 * 4;
- uint32_t pc = emu->getGPR(15) - 8;
- uint32_t minCode = pc - context;
- if (minCode >= (UINT32_MAX - context))
- minCode = 0;
- uint32_t maxCode = pc + context;
- if (maxCode < context)
- maxCode = UINT32_MAX;
-
- QStringList codeLines;
- for (uint32_t addr = minCode; addr >= minCode && addr <= maxCode; addr += 4) {
- const char *prefix = (addr == pc) ? (emu->instructionReady() ? "==>" : "...") : " ";
- struct ARMInstructionInfo info;
- char buffer[512];
-
- auto result = emu->readVirtual(addr, ARM710::V32);
- if (result.first.has_value()) {
- uint32_t opcode = result.first.value();
- ARMDecodeARM(opcode, &info);
- ARMDisassemble(&info, addr, buffer, sizeof(buffer));
- codeLines.append(QString("%1 %2 | %3 | %4").arg(prefix).arg(addr, 8, 16).arg(opcode, 8, 16).arg(buffer));
- }
+MainWindow::MainWindow(EmuBase* emu, QWidget* parent)
+ : QMainWindow(parent), ui(new Ui::MainWindow), pdaScreen(emu), emu(emu) {
+ ui->setupUi(this);
+ ui->logView->setMaximumBlockCount(1000);
+
+ elapsedTimer.start();
+ emu->setLogger([&](const char* str) {
+ QString fullStr =
+ QStringLiteral("[%1] %2").arg(elapsedTimer.elapsed()).arg(str);
+ ui->logView->appendPlainText(fullStr);
+ });
+
+ timer = new QTimer(this);
+ timer->setInterval(1000 / 64);
+ connect(timer, SIGNAL(timeout()), SLOT(execTimer()));
+
+ pdaScreen.show();
+
+ updateScreen();
+}
+
+MainWindow::~MainWindow() { delete ui; }
+
+void MainWindow::updateScreen() {
+ ui->cycleCounter->setText(QString("Cycles: %1").arg(emu->currentCycles()));
+
+ updateMemory();
+
+ char flagDisplay[] = {(emu->getCPSR() & 0x80000000) ? 'N' : '-',
+ (emu->getCPSR() & 0x40000000) ? 'Z' : '-',
+ (emu->getCPSR() & 0x20000000) ? 'C' : '-',
+ (emu->getCPSR() & 0x10000000) ? 'V' : '-', 0};
+ const char* modeName = "???";
+ switch (emu->getCPSR() & 0x1F) {
+ case 0x10:
+ modeName = "User";
+ break;
+ case 0x11:
+ modeName = "FIQ";
+ break;
+ case 0x12:
+ modeName = "IRQ";
+ break;
+ case 0x13:
+ modeName = "Supervisor";
+ break;
+ case 0x17:
+ modeName = "Abort";
+ break;
+ case 0x1B:
+ modeName = "Undefined";
+ break;
+ }
+
+ ui->regsLabel->setText(
+ QString("R0: %1 / R1: %2 / R2: %3 / R3: %4 / R4: %5 / R5: %6 / R6: %7 / "
+ "R7: %8\nR8: %9 / R9: %10 / R10:%11 / R11:%12 / R12:%13 / SP: "
+ "%14 / LR: %15 / PC: %16\n%17 / Mode: %18")
+ .arg(emu->getGPR(0), 8, 16)
+ .arg(emu->getGPR(1), 8, 16)
+ .arg(emu->getGPR(2), 8, 16)
+ .arg(emu->getGPR(3), 8, 16)
+ .arg(emu->getGPR(4), 8, 16)
+ .arg(emu->getGPR(5), 8, 16)
+ .arg(emu->getGPR(6), 8, 16)
+ .arg(emu->getGPR(7), 8, 16)
+ .arg(emu->getGPR(8), 8, 16)
+ .arg(emu->getGPR(9), 8, 16)
+ .arg(emu->getGPR(10), 8, 16)
+ .arg(emu->getGPR(11), 8, 16)
+ .arg(emu->getGPR(12), 8, 16)
+ .arg(emu->getGPR(13), 8, 16)
+ .arg(emu->getGPR(14), 8, 16)
+ .arg(emu->getGPR(15), 8, 16)
+ .arg(flagDisplay)
+ .arg(modeName));
+
+ // show a crude disassembly
+ const int context = 8 * 4;
+ uint32_t pc = emu->getGPR(15) - 8;
+ uint32_t minCode = pc - context;
+ if (minCode >= (UINT32_MAX - context))
+ minCode = 0;
+ uint32_t maxCode = pc + context;
+ if (maxCode < context)
+ maxCode = UINT32_MAX;
+
+ QStringList codeLines;
+ for (uint32_t addr = minCode; addr >= minCode && addr <= maxCode; addr += 4) {
+ const char* prefix =
+ (addr == pc) ? (emu->instructionReady() ? "==>" : "...") : " ";
+ struct ARMInstructionInfo info;
+ char buffer[512];
+
+ auto result = emu->readVirtual(addr, ARM710::V32);
+ if (result.first.has_value()) {
+ uint32_t opcode = result.first.value();
+ ARMDecodeARM(opcode, &info);
+ ARMDisassemble(&info, addr, buffer, sizeof(buffer));
+ codeLines.append(QString("%1 %2 | %3 | %4")
+ .arg(prefix)
+ .arg(addr, 8, 16)
+ .arg(opcode, 8, 16)
+ .arg(buffer));
}
- ui->codeLabel->setText(codeLines.join('\n'));
+ }
+ ui->codeLabel->setText(codeLines.join('\n'));
- // now, the actual screen
- pdaScreen.updateScreen();
+ // now, the actual screen
+ pdaScreen.updateScreen();
}
+void MainWindow::on_startButton_clicked() {
+ timer->start();
+ ui->startButton->setEnabled(false);
+ ui->stopButton->setEnabled(true);
+ ui->stepInsnButton->setEnabled(false);
+ ui->stepTickButton->setEnabled(false);
+}
-
-void MainWindow::on_startButton_clicked()
-{
- timer->start();
- ui->startButton->setEnabled(false);
- ui->stopButton->setEnabled(true);
- ui->stepInsnButton->setEnabled(false);
- ui->stepTickButton->setEnabled(false);
+void MainWindow::on_stopButton_clicked() {
+ timer->stop();
+ ui->startButton->setEnabled(true);
+ ui->stopButton->setEnabled(false);
+ ui->stepInsnButton->setEnabled(true);
+ ui->stepTickButton->setEnabled(true);
}
-void MainWindow::on_stopButton_clicked()
-{
- timer->stop();
- ui->startButton->setEnabled(true);
- ui->stopButton->setEnabled(false);
- ui->stepInsnButton->setEnabled(true);
- ui->stepTickButton->setEnabled(true);
+void MainWindow::on_stepTickButton_clicked() {
+ // emu->executeUntil(emu->currentCycles() + (CLOCK_SPEED * 2));
+ emu->executeUntil(emu->currentCycles() + 25000000);
+ updateScreen();
}
-void MainWindow::on_stepTickButton_clicked()
-{
-// emu->executeUntil(emu->currentCycles() + (CLOCK_SPEED * 2));
- emu->executeUntil(emu->currentCycles() + 25000000);
- updateScreen();
+void MainWindow::on_stepInsnButton_clicked() {
+ emu->executeUntil(emu->currentCycles() + 1);
+ updateScreen();
}
-void MainWindow::on_stepInsnButton_clicked()
-{
- emu->executeUntil(emu->currentCycles() + 1);
+void MainWindow::execTimer() {
+ if (emu) {
+ emu->executeUntil(emu->currentCycles() + (emu->getClockSpeed() / 64));
updateScreen();
+ }
}
-void MainWindow::execTimer()
-{
- if (emu) {
- emu->executeUntil(emu->currentCycles() + (emu->getClockSpeed() / 64));
- updateScreen();
- }
+void MainWindow::on_addBreakButton_clicked() {
+ uint32_t addr = ui->breakpointAddress->text().toUInt(nullptr, 16);
+ emu->breakpoints().insert(addr);
+ updateBreakpointsList();
}
-void MainWindow::on_addBreakButton_clicked()
-{
- uint32_t addr = ui->breakpointAddress->text().toUInt(nullptr, 16);
- emu->breakpoints().insert(addr);
- updateBreakpointsList();
+void MainWindow::on_removeBreakButton_clicked() {
+ uint32_t addr = ui->breakpointAddress->text().toUInt(nullptr, 16);
+ emu->breakpoints().erase(addr);
+ updateBreakpointsList();
}
-void MainWindow::on_removeBreakButton_clicked()
-{
- uint32_t addr = ui->breakpointAddress->text().toUInt(nullptr, 16);
- emu->breakpoints().erase(addr);
- updateBreakpointsList();
+void MainWindow::updateBreakpointsList() {
+ ui->breakpointsList->clear();
+ for (uint32_t addr : emu->breakpoints()) {
+ ui->breakpointsList->addItem(QString::number(addr, 16));
+ }
}
-void MainWindow::updateBreakpointsList()
-{
- ui->breakpointsList->clear();
- for (uint32_t addr : emu->breakpoints()) {
- ui->breakpointsList->addItem(QString::number(addr, 16));
- }
+void MainWindow::on_memoryViewAddress_textEdited(const QString&) {
+ updateMemory();
}
-void MainWindow::on_memoryViewAddress_textEdited(const QString &)
-{
- updateMemory();
-}
+void MainWindow::updateMemory() {
+ uint32_t virtBase = ui->memoryViewAddress->text().toUInt(nullptr, 16) & ~0xFF;
+ auto physBaseOpt = emu->virtToPhys(virtBase);
+ auto physBase = physBaseOpt.value_or(0xFFFFFFFF);
+ bool ok = physBaseOpt.has_value();
+ if (ok && (virtBase != physBase))
+ ui->physicalAddressLabel->setText(
+ QStringLiteral("Physical: %1").arg(physBase, 8, 16, QLatin1Char('0')));
+
+ uint8_t block[0x100];
+ if (ok) {
+ for (int i = 0; i < 0x100; i++) {
+ block[i] = emu->readPhysical(physBase + i, ARM710::V8).value();
+ }
+ }
+
+ QStringList output;
+ for (int row = 0; row < 16; row++) {
+ QString outLine;
+ outLine.reserve(8 + 2 + (2 * 16) + 3 + 16);
+ outLine.append(QStringLiteral("%1 |").arg(virtBase + (row * 16), 8, 16));
+ for (int col = 0; col < 16; col++) {
+ if (ok)
+ outLine.append(QStringLiteral(" %1").arg(block[row * 16 + col], 2, 16,
+ QLatin1Char('0')));
+ else
+ outLine.append(QStringLiteral(" ??"));
+ }
+ outLine.append(QStringLiteral(" | "));
+ for (int col = 0; col < 16; col++) {
+ uint8_t byte = block[row * 16 + col];
+ if (!ok)
+ outLine.append('?');
+ else if (byte >= 0x20 && byte <= 0x7E)
+ outLine.append((QChar)byte);
+ else
+ outLine.append('.');
+ }
+ output.append(outLine);
+ }
-void MainWindow::updateMemory()
-{
- uint32_t virtBase = ui->memoryViewAddress->text().toUInt(nullptr, 16) & ~0xFF;
- auto physBaseOpt = emu->virtToPhys(virtBase);
- auto physBase = physBaseOpt.value_or(0xFFFFFFFF);
- bool ok = physBaseOpt.has_value();
- if (ok && (virtBase != physBase))
- ui->physicalAddressLabel->setText(QStringLiteral("Physical: %1").arg(physBase, 8, 16, QLatin1Char('0')));
-
- uint8_t block[0x100];
- if (ok) {
- for (int i = 0; i < 0x100; i++) {
- block[i] = emu->readPhysical(physBase + i, ARM710::V8).value();
- }
- }
-
- QStringList output;
- for (int row = 0; row < 16; row++) {
- QString outLine;
- outLine.reserve(8 + 2 + (2 * 16) + 3 + 16);
- outLine.append(QStringLiteral("%1 |").arg(virtBase + (row * 16), 8, 16));
- for (int col = 0; col < 16; col++) {
- if (ok)
- outLine.append(QStringLiteral(" %1").arg(block[row*16+col], 2, 16, QLatin1Char('0')));
- else
- outLine.append(QStringLiteral(" ??"));
- }
- outLine.append(QStringLiteral(" | "));
- for (int col = 0; col < 16; col++) {
- uint8_t byte = block[row*16+col];
- if (!ok)
- outLine.append('?');
- else if (byte >= 0x20 && byte <= 0x7E)
- outLine.append((QChar)byte);
- else
- outLine.append('.');
- }
- output.append(outLine);
- }
-
- ui->memoryViewLabel->setText(output.join('\n'));
+ ui->memoryViewLabel->setText(output.join('\n'));
}
void MainWindow::on_memoryAdd1_clicked() { adjustMemoryAddress(1); }
void MainWindow::on_memorySub100_clicked() { adjustMemoryAddress(-0x100); }
void MainWindow::adjustMemoryAddress(int offset) {
- uint32_t address = ui->memoryViewAddress->text().toUInt(nullptr, 16);
- address += offset;
- ui->memoryViewAddress->setText(QString("%1").arg(address, 8, 16, QLatin1Char('0')));
- updateMemory();
+ uint32_t address = ui->memoryViewAddress->text().toUInt(nullptr, 16);
+ address += offset;
+ ui->memoryViewAddress->setText(
+ QString("%1").arg(address, 8, 16, QLatin1Char('0')));
+ updateMemory();
}
-void MainWindow::on_writeByteButton_clicked()
-{
- uint32_t address = ui->memoryViewAddress->text().toUInt(nullptr, 16);
- uint8_t value = (uint8_t)ui->memoryWriteValue->text().toUInt(nullptr, 16);
- emu->writeVirtual(value, address, ARM710::V8);
- updateMemory();
+void MainWindow::on_writeByteButton_clicked() {
+ uint32_t address = ui->memoryViewAddress->text().toUInt(nullptr, 16);
+ uint8_t value = (uint8_t)ui->memoryWriteValue->text().toUInt(nullptr, 16);
+ emu->writeVirtual(value, address, ARM710::V8);
+ updateMemory();
}
-void MainWindow::on_writeDwordButton_clicked()
-{
- uint32_t address = ui->memoryViewAddress->text().toUInt(nullptr, 16);
- uint32_t value = ui->memoryWriteValue->text().toUInt(nullptr, 16);
- emu->writeVirtual(value, address, ARM710::V32);
- updateMemory();
+void MainWindow::on_writeDwordButton_clicked() {
+ uint32_t address = ui->memoryViewAddress->text().toUInt(nullptr, 16);
+ uint32_t value = ui->memoryWriteValue->text().toUInt(nullptr, 16);
+ emu->writeVirtual(value, address, ARM710::V32);
+ updateMemory();
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
-#include <QMainWindow>
-#include <QElapsedTimer>
#include "../WindCore/emubase.h"
#include "pdascreenwindow.h"
+#include <QElapsedTimer>
+#include <QMainWindow>
namespace Ui {
class MainWindow;
}
-class MainWindow : public QMainWindow
-{
- Q_OBJECT
+class MainWindow : public QMainWindow {
+ Q_OBJECT
public:
- explicit MainWindow(EmuBase *emu, QWidget *parent = nullptr);
- ~MainWindow() override;
+ explicit MainWindow(EmuBase* emu, QWidget* parent = nullptr);
+ ~MainWindow() override;
private slots:
- void execTimer();
+ void execTimer();
- void on_startButton_clicked();
- void on_stopButton_clicked();
- void on_stepInsnButton_clicked();
- void on_stepTickButton_clicked();
+ void on_startButton_clicked();
+ void on_stopButton_clicked();
+ void on_stepInsnButton_clicked();
+ void on_stepTickButton_clicked();
- void on_addBreakButton_clicked();
+ void on_addBreakButton_clicked();
- void on_removeBreakButton_clicked();
+ void on_removeBreakButton_clicked();
- void on_memoryViewAddress_textEdited(const QString &arg1);
- void on_memoryAdd1_clicked();
- void on_memoryAdd4_clicked();
- void on_memoryAdd10_clicked();
- void on_memoryAdd100_clicked();
- void on_memorySub1_clicked();
- void on_memorySub4_clicked();
- void on_memorySub10_clicked();
- void on_memorySub100_clicked();
+ void on_memoryViewAddress_textEdited(const QString& arg1);
+ void on_memoryAdd1_clicked();
+ void on_memoryAdd4_clicked();
+ void on_memoryAdd10_clicked();
+ void on_memoryAdd100_clicked();
+ void on_memorySub1_clicked();
+ void on_memorySub4_clicked();
+ void on_memorySub10_clicked();
+ void on_memorySub100_clicked();
- void on_writeByteButton_clicked();
+ void on_writeByteButton_clicked();
- void on_writeDwordButton_clicked();
+ void on_writeDwordButton_clicked();
private:
- QElapsedTimer elapsedTimer;
- Ui::MainWindow *ui;
- PDAScreenWindow pdaScreen;
- EmuBase *emu;
- QTimer *timer;
- void updateScreen();
- void updateBreakpointsList();
- void updateMemory();
- void adjustMemoryAddress(int offset);
+ QElapsedTimer elapsedTimer;
+ Ui::MainWindow* ui;
+ PDAScreenWindow pdaScreen;
+ EmuBase* emu;
+ QTimer* timer;
+ void updateScreen();
+ void updateBreakpointsList();
+ void updateMemory();
+ void adjustMemoryAddress(int offset);
};
#endif // MAINWINDOW_H
#include "pdascreenwindow.h"
#include <QKeyEvent>
-PDAScreenWindow::PDAScreenWindow(EmuBase *emu, QWidget *parent) :
- QWidget(parent),
- emu(emu),
- lcd(new QLabel(this))
-{
- setWindowTitle("WindEmu");
- setFixedSize(emu->getDigitiserWidth(), emu->getDigitiserHeight());
- lcd->setGeometry(emu->getLCDOffsetX(), emu->getLCDOffsetY(), emu->getLCDWidth(), emu->getLCDHeight());
-
- const char *who = emu->getDeviceName();
- if (strcmp(who, "Osaris") == 0) {
- // some cheap and cheerful placeholders
- int bitW = (emu->getDigitiserWidth() - emu->getLCDWidth()) / 2;
- int bitH = emu->getDigitiserHeight() / 5;
- int leftX = 0;
- int rightX = bitW + emu->getLCDWidth();
- (new QLabel("Word", this))->setGeometry(leftX, bitH * 0, bitW, bitH);
- (new QLabel("Sheet", this))->setGeometry(leftX, bitH * 1, bitW, bitH);
- (new QLabel("Data", this))->setGeometry(leftX, bitH * 2, bitW, bitH);
- (new QLabel("Agenda", this))->setGeometry(leftX, bitH * 3, bitW, bitH);
- (new QLabel("Extras", this))->setGeometry(leftX, bitH * 4, bitW, bitH);
- (new QLabel("EPOC", this))->setGeometry(rightX, bitH * 0, bitW, bitH);
- (new QLabel("Menu", this))->setGeometry(rightX, bitH * 1, bitW, bitH);
- (new QLabel("Copy/Paste", this))->setGeometry(rightX, bitH * 2, bitW, bitH);
- (new QLabel("Zoom In", this))->setGeometry(rightX, bitH * 3, bitW, bitH);
- (new QLabel("Zoom Out", this))->setGeometry(rightX, bitH * 4, bitW, bitH);
- } else if (strcmp(who, "Series 5mx") == 0) {
- int leftW = emu->getLCDOffsetX();
- int leftH = emu->getLCDHeight() / 5;
- (new QLabel("➡️", this))->setGeometry(0, leftH * 0, leftW, leftH);
- (new QLabel("📄", this))->setGeometry(0, leftH * 1, leftW, leftH);
- (new QLabel("📡", this))->setGeometry(0, leftH * 2, leftW, leftH);
- (new QLabel("+", this))->setGeometry(0, leftH * 3, leftW, leftH);
- (new QLabel("-", this))->setGeometry(0, leftH * 4, leftW, leftH);
-
- int barX = 50;
- int barY = leftH * 5;
- int barW = (emu->getDigitiserWidth() - barX) / 8;
- int barH = emu->getDigitiserHeight() - emu->getLCDHeight();
- (new QLabel("System", this))->setGeometry(0, barY, barX, barH);
- (new QLabel("Word", this))->setGeometry(barX + barW * 0, barY, barW, barH);
- (new QLabel("Sheet", this))->setGeometry(barX + barW * 1, barY, barW, barH);
- (new QLabel("Contacts", this))->setGeometry(barX + barW * 2, barY, barW, barH);
- (new QLabel("Agenda", this))->setGeometry(barX + barW * 3, barY, barW, barH);
- (new QLabel("Email", this))->setGeometry(barX + barW * 4, barY, barW, barH);
- (new QLabel("Calc", this))->setGeometry(barX + barW * 5, barY, barW, barH);
- (new QLabel("Jotter", this))->setGeometry(barX + barW * 6, barY, barW, barH);
- (new QLabel("Extras", this))->setGeometry(barX + barW * 7, barY, barW, barH);
- }
+PDAScreenWindow::PDAScreenWindow(EmuBase* emu, QWidget* parent)
+ : QWidget(parent), emu(emu), lcd(new QLabel(this)) {
+ setWindowTitle("WindEmu");
+ setFixedSize(emu->getDigitiserWidth(), emu->getDigitiserHeight());
+ lcd->setGeometry(emu->getLCDOffsetX(), emu->getLCDOffsetY(),
+ emu->getLCDWidth(), emu->getLCDHeight());
+
+ const char* who = emu->getDeviceName();
+ if (strcmp(who, "Osaris") == 0) {
+ // some cheap and cheerful placeholders
+ int bitW = (emu->getDigitiserWidth() - emu->getLCDWidth()) / 2;
+ int bitH = emu->getDigitiserHeight() / 5;
+ int leftX = 0;
+ int rightX = bitW + emu->getLCDWidth();
+ (new QLabel("Word", this))->setGeometry(leftX, bitH * 0, bitW, bitH);
+ (new QLabel("Sheet", this))->setGeometry(leftX, bitH * 1, bitW, bitH);
+ (new QLabel("Data", this))->setGeometry(leftX, bitH * 2, bitW, bitH);
+ (new QLabel("Agenda", this))->setGeometry(leftX, bitH * 3, bitW, bitH);
+ (new QLabel("Extras", this))->setGeometry(leftX, bitH * 4, bitW, bitH);
+ (new QLabel("EPOC", this))->setGeometry(rightX, bitH * 0, bitW, bitH);
+ (new QLabel("Menu", this))->setGeometry(rightX, bitH * 1, bitW, bitH);
+ (new QLabel("Copy/Paste", this))->setGeometry(rightX, bitH * 2, bitW, bitH);
+ (new QLabel("Zoom In", this))->setGeometry(rightX, bitH * 3, bitW, bitH);
+ (new QLabel("Zoom Out", this))->setGeometry(rightX, bitH * 4, bitW, bitH);
+ } else if (strcmp(who, "Series 5mx") == 0) {
+ int leftW = emu->getLCDOffsetX();
+ int leftH = emu->getLCDHeight() / 5;
+ (new QLabel("➡️", this))->setGeometry(0, leftH * 0, leftW, leftH);
+ (new QLabel("📄", this))->setGeometry(0, leftH * 1, leftW, leftH);
+ (new QLabel("📡", this))->setGeometry(0, leftH * 2, leftW, leftH);
+ (new QLabel("+", this))->setGeometry(0, leftH * 3, leftW, leftH);
+ (new QLabel("-", this))->setGeometry(0, leftH * 4, leftW, leftH);
+
+ int barX = 50;
+ int barY = leftH * 5;
+ int barW = (emu->getDigitiserWidth() - barX) / 8;
+ int barH = emu->getDigitiserHeight() - emu->getLCDHeight();
+ (new QLabel("System", this))->setGeometry(0, barY, barX, barH);
+ (new QLabel("Word", this))->setGeometry(barX + barW * 0, barY, barW, barH);
+ (new QLabel("Sheet", this))->setGeometry(barX + barW * 1, barY, barW, barH);
+ (new QLabel("Contacts", this))
+ ->setGeometry(barX + barW * 2, barY, barW, barH);
+ (new QLabel("Agenda", this))
+ ->setGeometry(barX + barW * 3, barY, barW, barH);
+ (new QLabel("Email", this))->setGeometry(barX + barW * 4, barY, barW, barH);
+ (new QLabel("Calc", this))->setGeometry(barX + barW * 5, barY, barW, barH);
+ (new QLabel("Jotter", this))
+ ->setGeometry(barX + barW * 6, barY, barW, barH);
+ (new QLabel("Extras", this))
+ ->setGeometry(barX + barW * 7, barY, barW, barH);
+ }
}
void PDAScreenWindow::updateScreen() {
- uint8_t *lines[1024];
- QImage img(emu->getLCDWidth(), emu->getLCDHeight(), QImage::Format_Grayscale8);
- for (int y = 0; y < img.height(); y++)
- lines[y] = img.scanLine(y);
- emu->readLCDIntoBuffer(lines, false);
+ uint8_t* lines[1024];
+ QImage img(emu->getLCDWidth(), emu->getLCDHeight(),
+ QImage::Format_Grayscale8);
+ for (int y = 0; y < img.height(); y++)
+ lines[y] = img.scanLine(y);
+ emu->readLCDIntoBuffer(lines, false);
- lcd->setPixmap(QPixmap::fromImage(std::move(img)));
+ lcd->setPixmap(QPixmap::fromImage(std::move(img)));
}
#ifdef Q_OS_MAC
static EpocKey resolveKey(int key, int vk) {
- // Although Cocoa/Carbon's virtual keycodes include
- // modifiers, Qt doesn't expose them through QKeyEvent...
- switch (key) {
- case Qt::Key_Control: return EStdKeyLeftFunc;
- case Qt::Key_Shift: return EStdKeyLeftShift;
- case Qt::Key_Alt: return EStdKeyMenu;
- case Qt::Key_Meta: return EStdKeyLeftCtrl;
- }
-
- // https://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX10.6.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h#L182
- switch (vk) {
- case 0x00: return (EpocKey)'A';
- case 0x01: return (EpocKey)'S';
- case 0x02: return (EpocKey)'D';
- case 0x03: return (EpocKey)'F';
- case 0x04: return (EpocKey)'H';
- case 0x05: return (EpocKey)'G';
- case 0x06: return (EpocKey)'Z';
- case 0x07: return (EpocKey)'X';
- case 0x08: return (EpocKey)'C';
- case 0x09: return (EpocKey)'V';
- case 0x0B: return (EpocKey)'B';
- case 0x0C: return (EpocKey)'Q';
- case 0x0D: return (EpocKey)'W';
- case 0x0E: return (EpocKey)'E';
- case 0x0F: return (EpocKey)'R';
-
- case 0x10: return (EpocKey)'Y';
- case 0x11: return (EpocKey)'T';
- case 0x12: return (EpocKey)'1';
- case 0x13: return (EpocKey)'2';
- case 0x14: return (EpocKey)'3';
- case 0x15: return (EpocKey)'4';
- case 0x16: return (EpocKey)'6';
- case 0x17: return (EpocKey)'5';
- case 0x19: return (EpocKey)'9';
- case 0x1A: return (EpocKey)'7';
- case 0x1C: return (EpocKey)'8';
- case 0x1D: return (EpocKey)'0';
- case 0x1F: return (EpocKey)'O';
-
- case 0x20: return (EpocKey)'U';
- case 0x22: return (EpocKey)'I';
- case 0x23: return (EpocKey)'P';
- case 0x24: return EStdKeyEnter;
- case 0x25: return (EpocKey)'L';
- case 0x26: return (EpocKey)'J';
- case 0x27: return EStdKeySingleQuote;
- case 0x28: return (EpocKey)'K';
- case 0x2B: return EStdKeyComma;
- case 0x2D: return (EpocKey)'N';
- case 0x2E: return (EpocKey)'M';
- case 0x2F: return EStdKeyFullStop;
-
- case 0x30: return EStdKeyTab;
- case 0x31: return EStdKeySpace;
- case 0x33: return EStdKeyBackspace;
- case 0x35: return EStdKeyEscape;
-
- case 0x7B: return EStdKeyLeftArrow;
- case 0x7C: return EStdKeyRightArrow;
- case 0x7D: return EStdKeyDownArrow;
- case 0x7E: return EStdKeyUpArrow;
- }
-
- return EStdKeyNull;
+ // Although Cocoa/Carbon's virtual keycodes include
+ // modifiers, Qt doesn't expose them through QKeyEvent...
+ switch (key) {
+ case Qt::Key_Control:
+ return EStdKeyLeftFunc;
+ case Qt::Key_Shift:
+ return EStdKeyLeftShift;
+ case Qt::Key_Alt:
+ return EStdKeyMenu;
+ case Qt::Key_Meta:
+ return EStdKeyLeftCtrl;
+ }
+
+ // https://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX10.6.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h#L182
+ switch (vk) {
+ case 0x00:
+ return (EpocKey)'A';
+ case 0x01:
+ return (EpocKey)'S';
+ case 0x02:
+ return (EpocKey)'D';
+ case 0x03:
+ return (EpocKey)'F';
+ case 0x04:
+ return (EpocKey)'H';
+ case 0x05:
+ return (EpocKey)'G';
+ case 0x06:
+ return (EpocKey)'Z';
+ case 0x07:
+ return (EpocKey)'X';
+ case 0x08:
+ return (EpocKey)'C';
+ case 0x09:
+ return (EpocKey)'V';
+ case 0x0B:
+ return (EpocKey)'B';
+ case 0x0C:
+ return (EpocKey)'Q';
+ case 0x0D:
+ return (EpocKey)'W';
+ case 0x0E:
+ return (EpocKey)'E';
+ case 0x0F:
+ return (EpocKey)'R';
+
+ case 0x10:
+ return (EpocKey)'Y';
+ case 0x11:
+ return (EpocKey)'T';
+ case 0x12:
+ return (EpocKey)'1';
+ case 0x13:
+ return (EpocKey)'2';
+ case 0x14:
+ return (EpocKey)'3';
+ case 0x15:
+ return (EpocKey)'4';
+ case 0x16:
+ return (EpocKey)'6';
+ case 0x17:
+ return (EpocKey)'5';
+ case 0x19:
+ return (EpocKey)'9';
+ case 0x1A:
+ return (EpocKey)'7';
+ case 0x1C:
+ return (EpocKey)'8';
+ case 0x1D:
+ return (EpocKey)'0';
+ case 0x1F:
+ return (EpocKey)'O';
+
+ case 0x20:
+ return (EpocKey)'U';
+ case 0x22:
+ return (EpocKey)'I';
+ case 0x23:
+ return (EpocKey)'P';
+ case 0x24:
+ return EStdKeyEnter;
+ case 0x25:
+ return (EpocKey)'L';
+ case 0x26:
+ return (EpocKey)'J';
+ case 0x27:
+ return EStdKeySingleQuote;
+ case 0x28:
+ return (EpocKey)'K';
+ case 0x2B:
+ return EStdKeyComma;
+ case 0x2D:
+ return (EpocKey)'N';
+ case 0x2E:
+ return (EpocKey)'M';
+ case 0x2F:
+ return EStdKeyFullStop;
+
+ case 0x30:
+ return EStdKeyTab;
+ case 0x31:
+ return EStdKeySpace;
+ case 0x33:
+ return EStdKeyBackspace;
+ case 0x35:
+ return EStdKeyEscape;
+
+ case 0x7B:
+ return EStdKeyLeftArrow;
+ case 0x7C:
+ return EStdKeyRightArrow;
+ case 0x7D:
+ return EStdKeyDownArrow;
+ case 0x7E:
+ return EStdKeyUpArrow;
+ }
+
+ return EStdKeyNull;
}
#else
#error "Unsupported platform (for now! fix me in pdascreenwindow.cpp)"
static EpocKey resolveKey(int key) {
- // Placeholder, doesn't work for all keys
- switch (key) {
- case Qt::Key_Apostrophe: return EStdKeySingleQuote;
- case Qt::Key_Backspace: return EStdKeyBackspace;
- case Qt::Key_Escape: return EStdKeyEscape;
- case Qt::Key_Enter: return EStdKeyEnter;
- case Qt::Key_Return: return EStdKeyEnter;
- case Qt::Key_Alt: return EStdKeyMenu;
- case Qt::Key_Tab: return EStdKeyTab;
+ // Placeholder, doesn't work for all keys
+ switch (key) {
+ case Qt::Key_Apostrophe:
+ return EStdKeySingleQuote;
+ case Qt::Key_Backspace:
+ return EStdKeyBackspace;
+ case Qt::Key_Escape:
+ return EStdKeyEscape;
+ case Qt::Key_Enter:
+ return EStdKeyEnter;
+ case Qt::Key_Return:
+ return EStdKeyEnter;
+ case Qt::Key_Alt:
+ return EStdKeyMenu;
+ case Qt::Key_Tab:
+ return EStdKeyTab;
#ifdef Q_OS_MAC
- case Qt::Key_Meta: return EStdKeyLeftCtrl;
+ case Qt::Key_Meta:
+ return EStdKeyLeftCtrl;
#else
- case Qt::Key_Control: return EStdKeyLeftCtrl;
+ case Qt::Key_Control:
+ return EStdKeyLeftCtrl;
#endif
- case Qt::Key_Down: return EStdKeyDownArrow;
- case Qt::Key_Period: return EStdKeyFullStop;
+ case Qt::Key_Down:
+ return EStdKeyDownArrow;
+ case Qt::Key_Period:
+ return EStdKeyFullStop;
#ifdef Q_OS_MAC
- case Qt::Key_Control: return EStdKeyLeftFunc;
+ case Qt::Key_Control:
+ return EStdKeyLeftFunc;
#else
- case Qt::Key_Meta: return EStdKeyLeftFunc;
+ case Qt::Key_Meta:
+ return EStdKeyLeftFunc;
#endif
- case Qt::Key_Shift: return EStdKeyLeftShift;
- case Qt::Key_Right: return EStdKeyRightArrow;
- case Qt::Key_Left: return EStdKeyLeftArrow;
- case Qt::Key_Comma: return EStdKeyComma;
- case Qt::Key_Up: return EStdKeyUpArrow;
- case Qt::Key_Space: return EStdKeySpace;
- }
-
- if (key >= '0' && key <= '9') return (EpocKey)key;
- if (key >= 'A' && key <= 'Z') return (EpocKey)key;
- return EStdKeyNull;
+ case Qt::Key_Shift:
+ return EStdKeyLeftShift;
+ case Qt::Key_Right:
+ return EStdKeyRightArrow;
+ case Qt::Key_Left:
+ return EStdKeyLeftArrow;
+ case Qt::Key_Comma:
+ return EStdKeyComma;
+ case Qt::Key_Up:
+ return EStdKeyUpArrow;
+ case Qt::Key_Space:
+ return EStdKeySpace;
+ }
+
+ if (key >= '0' && key <= '9')
+ return (EpocKey)key;
+ if (key >= 'A' && key <= 'Z')
+ return (EpocKey)key;
+ return EStdKeyNull;
}
#endif
-
-void PDAScreenWindow::keyPressEvent(QKeyEvent *event)
-{
- emu->log("KeyPress: QtKey=%d nativeVirtualKey=%x nativeModifiers=%x", event->key(), event->nativeVirtualKey(), event->nativeModifiers());
- EpocKey k = resolveKey(event->key(), event->nativeVirtualKey());
- if (k != EStdKeyNull)
- emu->setKeyboardKey(k, true);
+void PDAScreenWindow::keyPressEvent(QKeyEvent* event) {
+ emu->log("KeyPress: QtKey=%d nativeVirtualKey=%x nativeModifiers=%x",
+ event->key(), event->nativeVirtualKey(), event->nativeModifiers());
+ EpocKey k = resolveKey(event->key(), event->nativeVirtualKey());
+ if (k != EStdKeyNull)
+ emu->setKeyboardKey(k, true);
}
-void PDAScreenWindow::keyReleaseEvent(QKeyEvent *event)
-{
- EpocKey k = resolveKey(event->key(), event->nativeVirtualKey());
- if (k != EStdKeyNull)
- emu->setKeyboardKey(k, false);
+void PDAScreenWindow::keyReleaseEvent(QKeyEvent* event) {
+ EpocKey k = resolveKey(event->key(), event->nativeVirtualKey());
+ if (k != EStdKeyNull)
+ emu->setKeyboardKey(k, false);
}
-
-void PDAScreenWindow::mousePressEvent(QMouseEvent *event)
-{
- emu->updateTouchInput(event->x(), event->y(), true);
+void PDAScreenWindow::mousePressEvent(QMouseEvent* event) {
+ emu->updateTouchInput(event->x(), event->y(), true);
}
-void PDAScreenWindow::mouseReleaseEvent(QMouseEvent *event)
-{
- emu->updateTouchInput(event->x(), event->y(), false);
+void PDAScreenWindow::mouseReleaseEvent(QMouseEvent* event) {
+ emu->updateTouchInput(event->x(), event->y(), false);
}
-void PDAScreenWindow::mouseMoveEvent(QMouseEvent *event)
-{
- if (event->buttons() & Qt::LeftButton)
- emu->updateTouchInput(event->x(), event->y(), true);
+void PDAScreenWindow::mouseMoveEvent(QMouseEvent* event) {
+ if (event->buttons() & Qt::LeftButton)
+ emu->updateTouchInput(event->x(), event->y(), true);
}
#ifndef PDASCREENWINDOW_H
#define PDASCREENWINDOW_H
-#include <QWidget>
-#include <QLabel>
#include "emubase.h"
+#include <QLabel>
+#include <QWidget>
-class PDAScreenWindow : public QWidget
-{
- Q_OBJECT
+class PDAScreenWindow : public QWidget {
+ Q_OBJECT
private:
- EmuBase *emu;
- QLabel *lcd;
+ EmuBase* emu;
+ QLabel* lcd;
public:
- explicit PDAScreenWindow(EmuBase *emu, QWidget *parent = nullptr);
+ explicit PDAScreenWindow(EmuBase* emu, QWidget* parent = nullptr);
public slots:
- void updateScreen();
+ void updateScreen();
protected:
- void keyPressEvent(QKeyEvent *event) override;
- void keyReleaseEvent(QKeyEvent *event) override;
- void mousePressEvent(QMouseEvent *event) override;
- void mouseReleaseEvent(QMouseEvent *event) override;
- void mouseMoveEvent(QMouseEvent *event) override;
+ void keyPressEvent(QKeyEvent* event) override;
+ void keyReleaseEvent(QKeyEvent* event) override;
+ void mousePressEvent(QMouseEvent* event) override;
+ void mouseReleaseEvent(QMouseEvent* event) override;
+ void mouseMoveEvent(QMouseEvent* event) override;
};
#endif // PDASCREENWINDOW_H
#include "../WindCore/emubase.h"
#include "../WindCore/windermere.h"
-#include <stdio.h>
-#include <emscripten.h>
#include <SDL.h>
+#include <emscripten.h>
+#include <stdio.h>
-EmuBase *emu;
+EmuBase* emu;
// SDL_Window *window;
-SDL_Surface *surface;
+SDL_Surface* surface;
static EpocKey resolveKey(SDLKey sym) {
- switch (sym) {
- case SDLK_BACKSPACE: return EStdKeyBackspace;
- case SDLK_TAB: return EStdKeyTab;
- case SDLK_RETURN: return EStdKeyEnter;
- case SDLK_ESCAPE: return EStdKeyEscape;
- case SDLK_SPACE: return EStdKeySpace;
- case SDLK_QUOTE: return EStdKeySingleQuote;
- case SDLK_COMMA: return EStdKeyComma;
- case SDLK_PERIOD: return EStdKeyFullStop;
- case SDLK_0: return (EpocKey)'0';
- case SDLK_1: return (EpocKey)'1';
- case SDLK_2: return (EpocKey)'2';
- case SDLK_3: return (EpocKey)'3';
- case SDLK_4: return (EpocKey)'4';
- case SDLK_5: return (EpocKey)'5';
- case SDLK_6: return (EpocKey)'6';
- case SDLK_7: return (EpocKey)'7';
- case SDLK_8: return (EpocKey)'8';
- case SDLK_9: return (EpocKey)'9';
- case SDLK_a: return (EpocKey)'A';
- case SDLK_b: return (EpocKey)'B';
- case SDLK_c: return (EpocKey)'C';
- case SDLK_d: return (EpocKey)'D';
- case SDLK_e: return (EpocKey)'E';
- case SDLK_f: return (EpocKey)'F';
- case SDLK_g: return (EpocKey)'G';
- case SDLK_h: return (EpocKey)'H';
- case SDLK_i: return (EpocKey)'I';
- case SDLK_j: return (EpocKey)'J';
- case SDLK_k: return (EpocKey)'K';
- case SDLK_l: return (EpocKey)'L';
- case SDLK_m: return (EpocKey)'M';
- case SDLK_n: return (EpocKey)'N';
- case SDLK_o: return (EpocKey)'O';
- case SDLK_p: return (EpocKey)'P';
- case SDLK_q: return (EpocKey)'Q';
- case SDLK_r: return (EpocKey)'R';
- case SDLK_s: return (EpocKey)'S';
- case SDLK_t: return (EpocKey)'T';
- case SDLK_u: return (EpocKey)'U';
- case SDLK_v: return (EpocKey)'V';
- case SDLK_w: return (EpocKey)'W';
- case SDLK_x: return (EpocKey)'X';
- case SDLK_y: return (EpocKey)'Y';
- case SDLK_z: return (EpocKey)'Z';
- case SDLK_UP: return EStdKeyUpArrow;
- case SDLK_DOWN: return EStdKeyDownArrow;
- case SDLK_RIGHT: return EStdKeyRightArrow;
- case SDLK_LEFT: return EStdKeyLeftArrow;
- case SDLK_RSHIFT: return EStdKeyRightShift;
- case SDLK_LSHIFT: return EStdKeyLeftShift;
- case SDLK_RCTRL: return EStdKeyRightCtrl;
- case SDLK_LCTRL: return EStdKeyLeftCtrl;
- case SDLK_RALT: return EStdKeyMenu;
- case SDLK_LALT: return EStdKeyMenu;
- case SDLK_LSUPER: return EStdKeyLeftFunc;
- case SDLK_RSUPER: return EStdKeyRightFunc;
- }
- return EStdKeyNull;
+ switch (sym) {
+ case SDLK_BACKSPACE:
+ return EStdKeyBackspace;
+ case SDLK_TAB:
+ return EStdKeyTab;
+ case SDLK_RETURN:
+ return EStdKeyEnter;
+ case SDLK_ESCAPE:
+ return EStdKeyEscape;
+ case SDLK_SPACE:
+ return EStdKeySpace;
+ case SDLK_QUOTE:
+ return EStdKeySingleQuote;
+ case SDLK_COMMA:
+ return EStdKeyComma;
+ case SDLK_PERIOD:
+ return EStdKeyFullStop;
+ case SDLK_0:
+ return (EpocKey)'0';
+ case SDLK_1:
+ return (EpocKey)'1';
+ case SDLK_2:
+ return (EpocKey)'2';
+ case SDLK_3:
+ return (EpocKey)'3';
+ case SDLK_4:
+ return (EpocKey)'4';
+ case SDLK_5:
+ return (EpocKey)'5';
+ case SDLK_6:
+ return (EpocKey)'6';
+ case SDLK_7:
+ return (EpocKey)'7';
+ case SDLK_8:
+ return (EpocKey)'8';
+ case SDLK_9:
+ return (EpocKey)'9';
+ case SDLK_a:
+ return (EpocKey)'A';
+ case SDLK_b:
+ return (EpocKey)'B';
+ case SDLK_c:
+ return (EpocKey)'C';
+ case SDLK_d:
+ return (EpocKey)'D';
+ case SDLK_e:
+ return (EpocKey)'E';
+ case SDLK_f:
+ return (EpocKey)'F';
+ case SDLK_g:
+ return (EpocKey)'G';
+ case SDLK_h:
+ return (EpocKey)'H';
+ case SDLK_i:
+ return (EpocKey)'I';
+ case SDLK_j:
+ return (EpocKey)'J';
+ case SDLK_k:
+ return (EpocKey)'K';
+ case SDLK_l:
+ return (EpocKey)'L';
+ case SDLK_m:
+ return (EpocKey)'M';
+ case SDLK_n:
+ return (EpocKey)'N';
+ case SDLK_o:
+ return (EpocKey)'O';
+ case SDLK_p:
+ return (EpocKey)'P';
+ case SDLK_q:
+ return (EpocKey)'Q';
+ case SDLK_r:
+ return (EpocKey)'R';
+ case SDLK_s:
+ return (EpocKey)'S';
+ case SDLK_t:
+ return (EpocKey)'T';
+ case SDLK_u:
+ return (EpocKey)'U';
+ case SDLK_v:
+ return (EpocKey)'V';
+ case SDLK_w:
+ return (EpocKey)'W';
+ case SDLK_x:
+ return (EpocKey)'X';
+ case SDLK_y:
+ return (EpocKey)'Y';
+ case SDLK_z:
+ return (EpocKey)'Z';
+ case SDLK_UP:
+ return EStdKeyUpArrow;
+ case SDLK_DOWN:
+ return EStdKeyDownArrow;
+ case SDLK_RIGHT:
+ return EStdKeyRightArrow;
+ case SDLK_LEFT:
+ return EStdKeyLeftArrow;
+ case SDLK_RSHIFT:
+ return EStdKeyRightShift;
+ case SDLK_LSHIFT:
+ return EStdKeyLeftShift;
+ case SDLK_RCTRL:
+ return EStdKeyRightCtrl;
+ case SDLK_LCTRL:
+ return EStdKeyLeftCtrl;
+ case SDLK_RALT:
+ return EStdKeyMenu;
+ case SDLK_LALT:
+ return EStdKeyMenu;
+ case SDLK_LSUPER:
+ return EStdKeyLeftFunc;
+ case SDLK_RSUPER:
+ return EStdKeyRightFunc;
+ }
+ return EStdKeyNull;
}
void emuEventLoop() {
- // printf("Doing it\n");
- emu->executeUntil(emu->currentCycles() + (emu->getClockSpeed() / 64));
+ // printf("Doing it\n");
+ emu->executeUntil(emu->currentCycles() + (emu->getClockSpeed() / 64));
- uint8_t *lines[480];
+ uint8_t* lines[480];
- SDL_LockSurface(surface);
- int baseX = emu->getLCDOffsetX();
- int baseY = emu->getLCDOffsetY();
- int height = emu->getLCDHeight();
- for (int y = 0; y < height; y++) {
- lines[y] = (uint8_t *)surface->pixels + (surface->pitch * (y + baseY)) + (baseX * 4);
- }
- emu->readLCDIntoBuffer(lines, true);
- SDL_UnlockSurface(surface);
- SDL_Flip(surface);
+ SDL_LockSurface(surface);
+ int baseX = emu->getLCDOffsetX();
+ int baseY = emu->getLCDOffsetY();
+ int height = emu->getLCDHeight();
+ for (int y = 0; y < height; y++) {
+ lines[y] = (uint8_t*)surface->pixels + (surface->pitch * (y + baseY)) +
+ (baseX * 4);
+ }
+ emu->readLCDIntoBuffer(lines, true);
+ SDL_UnlockSurface(surface);
+ SDL_Flip(surface);
- SDL_Event event;
- while (SDL_PollEvent(&event)) {
- if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) {
- EpocKey k = resolveKey(event.key.keysym.sym);
- if (k != EStdKeyNull)
- emu->setKeyboardKey(k, (event.key.state == SDL_PRESSED));
- } else if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) {
- if (event.button.button == SDL_BUTTON_LEFT)
- emu->updateTouchInput(event.button.x, event.button.y, (event.button.state == SDL_PRESSED));
- } else if (event.type == SDL_MOUSEMOTION) {
- emu->updateTouchInput(event.motion.x, event.motion.y, (event.motion.state & SDL_BUTTON(1)));
- }
- }
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) {
+ EpocKey k = resolveKey(event.key.keysym.sym);
+ if (k != EStdKeyNull)
+ emu->setKeyboardKey(k, (event.key.state == SDL_PRESSED));
+ } else if (event.type == SDL_MOUSEBUTTONDOWN ||
+ event.type == SDL_MOUSEBUTTONUP) {
+ if (event.button.button == SDL_BUTTON_LEFT)
+ emu->updateTouchInput(event.button.x, event.button.y,
+ (event.button.state == SDL_PRESSED));
+ } else if (event.type == SDL_MOUSEMOTION) {
+ emu->updateTouchInput(event.motion.x, event.motion.y,
+ (event.motion.state & SDL_BUTTON(1)));
+ }
+ }
}
-int main(int argc, char **argv) {
- emu = new Windermere::Emulator;
- emu->setLogger([](const char *str) {
- printf("%s\n", str);
- });
- FILE *f = fopen("rom/5mx.bin", "rb");
- fread(emu->getROMBuffer(), 1, 10485760, f);
- fclose(f);
+int main(int argc, char** argv) {
+ emu = new Windermere::Emulator;
+ emu->setLogger([](const char* str) { printf("%s\n", str); });
+ FILE* f = fopen("rom/5mx.bin", "rb");
+ fread(emu->getROMBuffer(), 1, 10485760, f);
+ fclose(f);
- if (SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO) != 0) {
- printf("SDL_Init failed: %s\n", SDL_GetError());
- return 1;
- }
- surface = SDL_SetVideoMode(emu->getDigitiserWidth(), emu->getDigitiserHeight(), 32, SDL_SWSURFACE);
- if (surface == NULL) {
- printf("SDL_SetVideoMode failed: %s\n", SDL_GetError());
- return 1;
- }
+ if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO) != 0) {
+ printf("SDL_Init failed: %s\n", SDL_GetError());
+ return 1;
+ }
+ surface = SDL_SetVideoMode(emu->getDigitiserWidth(),
+ emu->getDigitiserHeight(), 32, SDL_SWSURFACE);
+ if (surface == NULL) {
+ printf("SDL_SetVideoMode failed: %s\n", SDL_GetError());
+ return 1;
+ }
- EM_ASM("SDL.defaults.copyOnLock = false; SDL.defaults.discardOnLock = true; SDL.defaults.opaqueFrontBuffer = false;");
+ EM_ASM("SDL.defaults.copyOnLock = false; SDL.defaults.discardOnLock = true; "
+ "SDL.defaults.opaqueFrontBuffer = false;");
- emscripten_set_main_loop(&emuEventLoop, 64, 1);
+ emscripten_set_main_loop(&emuEventLoop, 64, 1);
- return 0;
+ return 0;
}