mirror of
https://github.com/lifting-bits/remill
synced 2026-06-21 13:56:07 +00:00
6322f794d1
* This branch contains support for new architectures. * Initial start to support for AArch 32 * Progress * Forgot the new files * Added all data Integer processing instructions without S + ADDS and started ANDS * Updated * Finished Integer Data Processing with three registers, added integer data processing with 2 regs + immediate, started MUL instructions * UMULL, UMULLS, UMLAL, UMLALS * Corrected condition for addend or 0 immediate for UMULL/UMLAL + SMULL/SMLAL instructions * Correct ops in Binary.cpp * UMAAL * SMULL, SMULLS, SMLAL, SMLALS + corrected acc was missing shift left in concatination * Updated decoding instructions based on top level encodings * Update returns around kDataProcessingRI and kDataProcessingI with comments to explain the correlation to the instruction rep * Added appropriate inst.category flags to Multiply and accumulate * Load/Store Word, Unsigned Byte (immediate, literal) && start of Logical Arithmetic (three register, immediate shift) * Was missing UMAAL DEF_ISEL in Binary.cpp * AddAddrRegOp * Logical Arithmetic (three register, immediate shift) without accounting for the possible PC jump * Made DecodeA32ExpandImm much much smaller * Replaced some imm ops with AddImmOp calls * Created AddShiftOp * Added interpreter for evaluating new PC value at decoding time to handle direct jumps and conditional jumps * Created EvalPCDest added PC evaluation to Logical Arithmetic Instructions * AddShiftOp -> AddShiftOp, AddShiftThenExtractOp, AddExtractThenShiftOp * Cleaned up some formatting, Renamed DecodeA32ExpandImm to ExpandTo32AddImmAddCarry and added a clarifying comment * Added comment to EvalPCDest for clarity * Cleaned up some things, updated the decoding semantics and semantics for the logical instructions * Shortened kLogArithEvaluators and fixed a bug * Updates from testing instructions * Fixed DEF_ISEL for pre/post index instructions in MEM.cpp * Integer Test and Compare (two register, immediate shift) * Logical Arithmetic (two register and immediate) * Integer Test and Compare (one register and immediate) * Added to the top level encoding infrastructure to handle the Data-processing register (register shift) set of instructions and 3 corresponding subsets * Add structs for the 3 subsets of Data-processing register (register shift) * Code status before refactoring operand types * This branch contains support for new architectures. * Initial start to support for AArch 32 * Progress * Forgot the new files * Added all data Integer processing instructions without S + ADDS and started ANDS * Updated * Finished Integer Data Processing with three registers, added integer data processing with 2 regs + immediate, started MUL instructions * UMULL, UMULLS, UMLAL, UMLALS * Corrected condition for addend or 0 immediate for UMULL/UMLAL + SMULL/SMLAL instructions * Correct ops in Binary.cpp * UMAAL * SMULL, SMULLS, SMLAL, SMLALS + corrected acc was missing shift left in concatination * Updated decoding instructions based on top level encodings * Update returns around kDataProcessingRI and kDataProcessingI with comments to explain the correlation to the instruction rep * Added appropriate inst.category flags to Multiply and accumulate * Load/Store Word, Unsigned Byte (immediate, literal) && start of Logical Arithmetic (three register, immediate shift) * Was missing UMAAL DEF_ISEL in Binary.cpp * AddAddrRegOp * Logical Arithmetic (three register, immediate shift) without accounting for the possible PC jump * Made DecodeA32ExpandImm much much smaller * Replaced some imm ops with AddImmOp calls * Created AddShiftOp * Added interpreter for evaluating new PC value at decoding time to handle direct jumps and conditional jumps * Created EvalPCDest added PC evaluation to Logical Arithmetic Instructions * AddShiftOp -> AddShiftOp, AddShiftThenExtractOp, AddExtractThenShiftOp * Cleaned up some formatting, Renamed DecodeA32ExpandImm to ExpandTo32AddImmAddCarry and added a clarifying comment * Added comment to EvalPCDest for clarity * Cleaned up some things, updated the decoding semantics and semantics for the logical instructions * Shortened kLogArithEvaluators and fixed a bug * Updates from testing instructions * Fixed DEF_ISEL for pre/post index instructions in MEM.cpp * Integer Test and Compare (two register, immediate shift) * Logical Arithmetic (two register and immediate) * Integer Test and Compare (one register and immediate) * Added to the top level encoding infrastructure to handle the Data-processing register (register shift) set of instructions and 3 corresponding subsets * Add structs for the 3 subsets of Data-processing register (register shift) * Code status before refactoring operand types * Finished updates off master * Start of operand refactor * Finished Expression Operand Support * Fix the .gitignore to add AArch32 to lib/Arch && removed all extra rrx ops from semantics * Updated .gitignore again, Added AddShiftRegRegOperand, Updated AddShiftRegImmOperand, Finished Register shift instructions for Integer Test and Compare, Logical Arithmetic, Integer Data Processing * Updated ROR in AddShiftRegRegOperand * Created ExtractAndZExtExpr * Fixed comment formatting in if else statements * Created RORExpr * Small fixes * Small fix in Logical Arithmetic (two register and immediate) * Corrected AddShiftRegRegOperand and cleaned it up. Split the carry op into a separate function. * conditional support + Start of Branch instructions * Created AddExprOp, cleaned up some expressions in reg shifted reg, and updated some occurances of ShiftThenExtractOp with ExtractAndZExtExpr * Updates from testing register shifted by register value inst * Fix to ROR in AddShiftRegCarryOperand * Corrected negation in DecodeCondition * DecodeCondition edit * DecodeCondition and AddShiftRegCarryOperand edits * Updated arch_for_decode to arch * Halfword Multiply and Accumulate * Edits from testing Halfword Multiply and Accumulate * Changed order of operands in Halfword Multiply and Accumulate to better reflect inst format + updated inst errors * Branch (Imm) & BX/BXL * Update aarch32 cmake * cmake update * CLZ * Forgot BITBYTE.cpp * MOVT * Integer Saturating Arithmetic * updated semantics in SMLAWh & SMLAh to use Select for setting PSTATE.Q * Started Load/Store Word, Unsigned Byte (register) & fixed MOV halfword * Load/Store Word, Unsigned Byte (register) * Finished testing load/Store Word, Unsigned Byte (register) * Load/Store Dual, Half, Signed Byte (register) * Rest of Extra load store: Load/Store Dual, Half, Signed Byte (immediate, literal) * Finished testing all the Load/store additions * Signed multiply, Divide * Cleaned up SExt some * Saturate Insts and Start of Load Store Multiple - STMDB and LDM (aliases which support PUSH and POP of multiple regs) * Condensed args in STMDB and LDM semantics * Rest of Multiple Load/Store that do not execute in a different mode * Bitfield Extract * Extend and Add * fix * NOP * Small fix * Simplified the bit reps in TryMoveSpecialRegisterAndHintsI * Moved Bitfield extract semantics out of BINARY and into BITBYTE * Finished correcting S/ZExt and Trunc use * Ran scripts/format-files to format * Smoke Test * Add false delay slot to kCategoryConditionalDirectFunctionCall * CI: Use single packaging job, add changelog support (#491) * CI: Add tag handler (#492) * Delay slot fixes to TraceLifter Co-authored-by: Peter Goodman <peter.goodman@gmail.com> Co-authored-by: Alessandro Gario <5714290+alessandrogario@users.noreply.github.com>
433 lines
12 KiB
C++
433 lines
12 KiB
C++
/*
|
|
* Copyright (c) 2020 Trail of Bits, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
namespace {
|
|
|
|
// Offset
|
|
DEF_COND_SEM(STR, M32W dst, R32 src1) {
|
|
auto src = Read(src1);
|
|
Write(dst, src);
|
|
return memory;
|
|
}
|
|
|
|
DEF_COND_SEM(STRB, M8W dst, R32 src1) {
|
|
auto src = Read(src1);
|
|
Write(dst, TruncTo<uint8_t>(src));
|
|
return memory;
|
|
}
|
|
|
|
// Pre + Post
|
|
DEF_COND_SEM(STRp, M32W dst, R32 src1, R32W dst_reg, R32 src2) {
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
Write(dst, src);
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
// Pre + Post
|
|
DEF_COND_SEM(STRBp, M8W dst, R32 src1, R32W dst_reg, R32 src2) {
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
Write(dst, TruncTo<uint8_t>(src));
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
// Offset
|
|
DEF_COND_SEM(LDR, M32 src1, R32W dst) {
|
|
auto src = Read(src1);
|
|
WriteZExt(dst, src);
|
|
return memory;
|
|
}
|
|
|
|
// Offset
|
|
DEF_COND_SEM(LDRB, M8 src1, R32W dst) {
|
|
auto src = Read(src1);
|
|
WriteZExt(dst, src);
|
|
return memory;
|
|
}
|
|
|
|
// Pre + Post
|
|
DEF_COND_SEM(LDRp, M32 src1, R32W dst, R32W dst_reg, R32 src2) {
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
WriteZExt(dst, src);
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
// Pre + Post
|
|
DEF_COND_SEM(LDRBp, M8 src1, R32W dst, R32W dst_reg, R32 src2) {
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
WriteZExt(dst, src);
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
DEF_COND_SEM(STRT, M32W dst, R32 src1, R32W dst_reg, R32 src2) {
|
|
memory = __remill_sync_hyper_call(state, memory,
|
|
SyncHyperCall::kAArch32CheckNotEL2);
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
Write(dst, TruncTo<uint32_t>(src));
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
DEF_COND_SEM(STRTB, M8W dst, R32 src1, R32W dst_reg, R32 src2) {
|
|
memory = __remill_sync_hyper_call(state, memory,
|
|
SyncHyperCall::kAArch32CheckNotEL2);
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
Write(dst, TruncTo<uint8_t>(src));
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
DEF_COND_SEM(LDRT, M32 src1, R32W dst, R32W dst_reg, R32 src2) {
|
|
memory = __remill_sync_hyper_call(state, memory,
|
|
SyncHyperCall::kAArch32CheckNotEL2);
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
WriteZExt(dst, src);
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
DEF_COND_SEM(LDRTB, M8 src1, R32W dst, R32W dst_reg, R32 src2) {
|
|
memory = __remill_sync_hyper_call(state, memory,
|
|
SyncHyperCall::kAArch32CheckNotEL2);
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
WriteZExt(dst, src);
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
DEF_ISEL(STR) = STR;
|
|
DEF_ISEL(STRB) = STRB;
|
|
DEF_ISEL(STRp) = STRp;
|
|
DEF_ISEL(STRBp) = STRBp;
|
|
DEF_ISEL(LDR) = LDR;
|
|
DEF_ISEL(LDRB) = LDRB;
|
|
DEF_ISEL(LDRp) = LDRp;
|
|
DEF_ISEL(LDRBp) = LDRBp;
|
|
DEF_ISEL(STRT) = STRT;
|
|
DEF_ISEL(STRBT) = STRTB;
|
|
DEF_ISEL(LDRT) = LDRT;
|
|
DEF_ISEL(LDRBT) = LDRTB;
|
|
|
|
namespace {
|
|
|
|
// Offset
|
|
DEF_COND_SEM(STRH, M16W dst, R32 src1) {
|
|
auto src = Read(src1);
|
|
Write(dst, TruncTo<uint16_t>(src));
|
|
return memory;
|
|
}
|
|
|
|
// Pre + Post
|
|
DEF_COND_SEM(STRHp, M16W dst, R32 src1, R32W dst_reg, R32 src2) {
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
Write(dst, TruncTo<uint16_t>(src));
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
// Offset
|
|
DEF_COND_SEM(LDRH, M16 src1, R32W dst) {
|
|
auto src = Read(src1);
|
|
WriteZExt(dst, src);
|
|
return memory;
|
|
}
|
|
|
|
// Pre + Post
|
|
DEF_COND_SEM(LDRHp, M16 src1, R32W dst, R32W dst_reg, R32 src2) {
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
WriteZExt(dst, src);
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
// Offset
|
|
DEF_COND_SEM(STRD, M64W dst, R32 src1, R32 src2) {
|
|
auto lhs = UShl(ZExt<uint64_t>(Read(src2)), 32ul);
|
|
auto rhs = ZExt<uint64_t>(Read(src1));
|
|
auto src = UOr(lhs, rhs);
|
|
WriteTrunc(dst, src);
|
|
return memory;
|
|
}
|
|
|
|
// Pre + Post
|
|
DEF_COND_SEM(STRDp, M64W dst, R32 src1, R32 src2, R32W dst_reg, R32 src_new) {
|
|
auto lhs = UShl(ZExt<uint64_t>(Read(src2)), 32ul);
|
|
auto rhs = ZExt<uint64_t>(Read(src1));
|
|
auto src = UOr(lhs, rhs);
|
|
auto new_val = Read(src_new);
|
|
WriteTrunc(dst, src);
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
// Offset
|
|
DEF_COND_SEM(LDRD, M64 src1, R32W dst1, R32W dst2) {
|
|
auto src = Read(src1);
|
|
Write(dst1, TruncTo<uint32_t>(src));
|
|
Write(dst2, TruncTo<uint32_t>(UShr(src, 32ul)));
|
|
return memory;
|
|
}
|
|
|
|
// Pre + Post
|
|
DEF_COND_SEM(LDRDp, M64 src1, R32W dst1, R32W dst2, R32W dst_reg, R32 src2) {
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
Write(dst1, TruncTo<uint32_t>(src));
|
|
Write(dst2, TruncTo<uint32_t>(UShr(src, 32ul)));
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
// Offset
|
|
DEF_COND_SEM(LDRSB, M8 src1, R32W dst) {
|
|
auto src = Read(src1);
|
|
WriteSExt(dst, src);
|
|
return memory;
|
|
}
|
|
|
|
// Pre + Post
|
|
DEF_COND_SEM(LDRSBp, M8 src1, R32W dst, R32W dst_reg, R32 src2) {
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
WriteSExt(dst, src);
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
// Offset
|
|
DEF_COND_SEM(LDRSH, M16 src1, R32W dst) {
|
|
auto src = Read(src1);
|
|
WriteSExt(dst, src);
|
|
return memory;
|
|
}
|
|
|
|
// Pre + Post
|
|
DEF_COND_SEM(LDRSHp, M16 src1, R32W dst, R32W dst_reg, R32 src2) {
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
WriteSExt(dst, src);
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
DEF_COND_SEM(STRHT, M16W dst, R32 src1, R32W dst_reg, R32 src2) {
|
|
memory = __remill_sync_hyper_call(state, memory,
|
|
SyncHyperCall::kAArch32CheckNotEL2);
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
WriteTrunc(dst, src);
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
DEF_COND_SEM(LDRHT, M16 src1, R32W dst, R32W dst_reg, R32 src2) {
|
|
memory = __remill_sync_hyper_call(state, memory,
|
|
SyncHyperCall::kAArch32CheckNotEL2);
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
WriteZExt(dst, src);
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
DEF_COND_SEM(LDRSBT, M8 src1, R32W dst, R32W dst_reg, R32 src2) {
|
|
memory = __remill_sync_hyper_call(state, memory,
|
|
SyncHyperCall::kAArch32CheckNotEL2);
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
WriteSExt(dst, src);
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
DEF_COND_SEM(LDRSHT, M16 src1, R32W dst, R32W dst_reg, R32 src2) {
|
|
memory = __remill_sync_hyper_call(state, memory,
|
|
SyncHyperCall::kAArch32CheckNotEL2);
|
|
auto src = Read(src1);
|
|
auto new_val = Read(src2);
|
|
WriteSExt(dst, src);
|
|
Write(dst_reg, new_val);
|
|
return memory;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
DEF_ISEL(STRH) = STRH;
|
|
DEF_ISEL(STRHp) = STRHp;
|
|
DEF_ISEL(LDRH) = LDRH;
|
|
DEF_ISEL(LDRHp) = LDRHp;
|
|
DEF_ISEL(STRD) = STRD;
|
|
DEF_ISEL(STRDp) = STRDp;
|
|
DEF_ISEL(LDRD) = LDRD;
|
|
DEF_ISEL(LDRDp) = LDRDp;
|
|
DEF_ISEL(LDRSB) = LDRSB;
|
|
DEF_ISEL(LDRSBp) = LDRSBp;
|
|
DEF_ISEL(LDRSH) = LDRSH;
|
|
DEF_ISEL(LDRSHp) = LDRSHp;
|
|
DEF_ISEL(STRHT) = STRHT;
|
|
DEF_ISEL(LDRHT) = LDRHT;
|
|
DEF_ISEL(LDRSBT) = LDRSBT;
|
|
DEF_ISEL(LDRSHT) = LDRSHT;
|
|
|
|
// Load/Store Multiple
|
|
namespace {
|
|
DEF_COND_SEM(LDM, I16 reg_list, R32W dst, R32 dst_new, M32 src_mem, R32W dst0,
|
|
R32W dst1, R32W dst2, R32W dst3, R32W dst4, R32W dst5, R32W dst6,
|
|
R32W dst7, R32W dst8, R32W dst9, R32W dst10, R32W dst11,
|
|
R32W dst12, R32W dst13, R32W dst14, R32W dst15) {
|
|
auto regs = Read(reg_list);
|
|
uint32_t index = 0;
|
|
if (UAnd(regs, uint16_t(0b1u))) {
|
|
Write(dst0, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 1))) {
|
|
Write(dst1, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 2))) {
|
|
Write(dst2, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 3))) {
|
|
Write(dst3, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 4))) {
|
|
Write(dst4, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 5))) {
|
|
Write(dst5, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 6))) {
|
|
Write(dst6, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 7))) {
|
|
Write(dst7, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 8))) {
|
|
Write(dst8, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 9))) {
|
|
Write(dst9, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 10))) {
|
|
Write(dst10, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 11))) {
|
|
Write(dst11, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 12))) {
|
|
Write(dst12, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 13))) {
|
|
Write(dst13, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 14))) {
|
|
Write(dst14, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 15))) {
|
|
Write(dst15, Read(GetElementPtr(src_mem, index++)));
|
|
}
|
|
Write(dst, Read(dst_new));
|
|
return memory;
|
|
}
|
|
|
|
DEF_COND_SEM(STMDB, I16 reg_list, R32W dst, R32 dst_new, M32W dst_mem, R32 src0,
|
|
R32 src1, R32 src2, R32 src3, R32 src4, R32 src5, R32 src6,
|
|
R32 src7, R32 src8, R32 src9, R32 src10, R32 src11, R32 src12,
|
|
R32 src13, R32 src14, R32 src15) {
|
|
auto regs = Read(reg_list);
|
|
uint32_t index = 0;
|
|
if (UAnd(regs, uint16_t(0b1u))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src0));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 1))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src1));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 2))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src2));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 3))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src3));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 4))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src4));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 5))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src5));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 6))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src6));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 7))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src7));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 8))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src8));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 9))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src9));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 10))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src10));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 11))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src11));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 12))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src12));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 13))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src13));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 14))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src14));
|
|
}
|
|
if (UAnd(regs, uint16_t(0b1u << 15))) {
|
|
Write(GetElementPtr(dst_mem, index++), Read(src15));
|
|
}
|
|
Write(dst, Read(dst_new));
|
|
return memory;
|
|
}
|
|
} // namespace
|
|
|
|
DEF_ISEL(STMDA) = STMDB;
|
|
DEF_ISEL(LDMDA) = LDM;
|
|
DEF_ISEL(STM) = STMDB;
|
|
DEF_ISEL(LDM) = LDM;
|
|
|
|
//DEF_ISEL(STMu) = STMu;
|
|
DEF_ISEL(STMDB) = STMDB;
|
|
DEF_ISEL(LDMDB) = LDM;
|
|
|
|
//DEF_ISEL(LDMu) = LDMu;
|
|
DEF_ISEL(STMIB) = STMDB;
|
|
DEF_ISEL(LDMIB) = LDM;
|
|
|
|
//DEF_ISEL(LDMe) = LDMe;
|