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>
196 lines
5.6 KiB
C++
196 lines
5.6 KiB
C++
/*
|
|
* Copyright (c) 2017 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.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
// Disable the "loop not unrolled warnings"
|
|
#pragma clang diagnostic ignored "-Wpass-failed"
|
|
|
|
namespace {
|
|
|
|
template <typename D, typename S, typename DestType>
|
|
DEF_SEM(LEA, D dst, S src) {
|
|
WriteZExt(dst, static_cast<DestType>(AddressOf(src)));
|
|
return memory;
|
|
}
|
|
|
|
DEF_SEM(LEAVE_16BIT) {
|
|
addr_t op_size = 2;
|
|
addr_t link_pointer = Read(REG_XBP);
|
|
addr_t base_pointer =
|
|
Read(ReadPtr<addr_t>(link_pointer _IF_32BIT(REG_SS_BASE)));
|
|
Write(REG_XBP, base_pointer);
|
|
Write(REG_XSP, UAdd(link_pointer, op_size));
|
|
return memory;
|
|
}
|
|
|
|
template <typename T>
|
|
DEF_SEM(LEAVE_FULL) {
|
|
addr_t op_size = TruncTo<addr_t>(sizeof(T));
|
|
addr_t link_pointer = Read(REG_XBP);
|
|
addr_t base_pointer =
|
|
Read(ReadPtr<addr_t>(link_pointer _IF_32BIT(REG_SS_BASE)));
|
|
Write(REG_XBP, base_pointer);
|
|
Write(REG_XSP, UAdd(link_pointer, op_size));
|
|
return memory;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
DEF_ISEL(LEA_GPRv_AGEN_16) = LEA<R16W, M8, uint16_t>;
|
|
DEF_ISEL(LEA_GPRv_AGEN_32) = LEA<R32W, M8, uint32_t>;
|
|
IF_64BIT(DEF_ISEL(LEA_GPRv_AGEN_64) = LEA<R64W, M8, uint64_t>;)
|
|
|
|
DEF_ISEL(LEAVE_16) = LEAVE_16BIT;
|
|
DEF_ISEL_RI32or64(LEAVE, LEAVE_FULL);
|
|
|
|
namespace {
|
|
|
|
// TODO(pag): Handle the case where the operand size and address size disagree.
|
|
// This can happen when using the 66H or 67H prefixes to override the
|
|
// operand or address sizes. For example, and operand size of 32 with
|
|
// an address size of 16 will read `[BP]` instead of `[EBP]`, but the
|
|
// stack pointer will decrement by `4`.
|
|
template <typename T>
|
|
DEF_SEM(ENTER, I16 src1, I8 src2) {
|
|
addr_t op_size = sizeof(T);
|
|
addr_t alloc_size = ZExtTo<addr_t>(Read(src1));
|
|
addr_t nesting_level = ZExtTo<addr_t>(URem(Read(src2), 32_u8));
|
|
addr_t xsp_temp = Read(REG_XSP);
|
|
addr_t frame_temp = USub(xsp_temp, op_size);
|
|
addr_t next_xsp =
|
|
USub(USub(frame_temp, UMul(op_size, nesting_level)), alloc_size);
|
|
|
|
// Detect failure. This should really happen at the end of `ENTER` but we
|
|
// do it here. This is why `frame_temp` is created before the `PUSH` of
|
|
// `RBP`, but displaced to mimic the `PUSH`.
|
|
Write(WritePtr<T>(next_xsp _IF_32BIT(REG_SS_BASE)),
|
|
Read(ReadPtr<T>(next_xsp _IF_32BIT(REG_SS_BASE))));
|
|
|
|
// Push `XBP`.
|
|
addr_t xbp_temp = Read(REG_XBP);
|
|
addr_t xsp_after_push = USub(xsp_temp, op_size);
|
|
Write(REG_XSP, xsp_after_push);
|
|
Write(WritePtr<T>(xsp_after_push _IF_32BIT(REG_SS_BASE)),
|
|
TruncTo<T>(xbp_temp));
|
|
xsp_temp = xsp_after_push;
|
|
|
|
if (nesting_level) {
|
|
if (1 < nesting_level) {
|
|
_Pragma("unroll") for (addr_t i = 1; i <= (nesting_level - 1); ++i) {
|
|
xbp_temp = USub(xbp_temp, op_size); // TODO(pag): Handle 67H prefix.
|
|
|
|
// Copy the display entry to the stack.
|
|
xsp_after_push = USub(xsp_temp, op_size);
|
|
Write(WritePtr<T>(xsp_after_push _IF_32BIT(REG_SS_BASE)),
|
|
Read(ReadPtr<T>(xbp_temp _IF_32BIT(REG_SS_BASE))));
|
|
xsp_temp = xsp_after_push;
|
|
}
|
|
}
|
|
|
|
xsp_temp = xsp_after_push;
|
|
xsp_after_push = USub(xsp_temp, op_size);
|
|
Write(WritePtr<addr_t>(xsp_after_push _IF_32BIT(REG_SS_BASE)), frame_temp);
|
|
xsp_temp = xsp_after_push;
|
|
}
|
|
|
|
Write(REG_XBP, frame_temp);
|
|
Write(REG_XSP, USub(xsp_temp, alloc_size));
|
|
return memory;
|
|
}
|
|
|
|
DEF_SEM(DoNothing) {
|
|
return memory;
|
|
}
|
|
|
|
template <typename... Args>
|
|
DEF_SEM(DoNothingWithParam, Args...) {
|
|
return memory;
|
|
}
|
|
|
|
DEF_SEM(DoCLFLUSH_MEMmprefetch, M8) {
|
|
return memory;
|
|
}
|
|
|
|
|
|
// Good reference for memory barriers and their relationships to instructions:
|
|
// http://g.oswego.edu/dl/jmm/cookbook.html
|
|
|
|
DEF_SEM(DoMFENCE) {
|
|
BarrierStoreLoad();
|
|
return memory;
|
|
}
|
|
|
|
DEF_SEM(DoSFENCE) {
|
|
BarrierStoreStore();
|
|
return memory;
|
|
}
|
|
|
|
DEF_SEM(DoLFENCE) {
|
|
BarrierLoadLoad();
|
|
return memory;
|
|
}
|
|
|
|
DEF_SEM(DoXLAT) {
|
|
addr_t base = Read(REG_XBX);
|
|
addr_t offset = ZExtTo<addr_t>(Read(REG_AL));
|
|
Write(REG_AL,
|
|
Read(ReadPtr<uint8_t>(UAdd(base, offset) _IF_32BIT(REG_DS_BASE))));
|
|
return memory;
|
|
}
|
|
|
|
DEF_SEM(DoCPUID) {
|
|
return __remill_sync_hyper_call(state, memory, SyncHyperCall::kX86CPUID);
|
|
}
|
|
} // namespace
|
|
|
|
DEF_ISEL(ENTER_IMMw_IMMb_16) = ENTER<uint16_t>;
|
|
IF_32BIT(DEF_ISEL(ENTER_IMMw_IMMb_32) = ENTER<uint32_t>;)
|
|
IF_64BIT(DEF_ISEL(ENTER_IMMw_IMMb_64) = ENTER<uint64_t>;)
|
|
|
|
// A `NOP` with a `REP` prefix for hinting. Used for busy-wait loops.
|
|
DEF_ISEL(PAUSE) = DoNothing;
|
|
|
|
// A kind of NOP.
|
|
DEF_ISEL(CLFLUSH_MEMmprefetch) = DoCLFLUSH_MEMmprefetch;
|
|
|
|
DEF_ISEL(MFENCE) = DoMFENCE;
|
|
|
|
DEF_ISEL(SFENCE) = DoSFENCE;
|
|
|
|
DEF_ISEL(LFENCE) = DoLFENCE;
|
|
|
|
DEF_ISEL(XLAT) = DoXLAT;
|
|
|
|
DEF_ISEL(CPUID) = DoCPUID;
|
|
|
|
DEF_ISEL(UD0_GPR32_MEMd) =
|
|
DoNothingWithParam<R32, M32, IF_32BIT_ELSE(R32W, R64W)>;
|
|
|
|
DEF_ISEL(UD1_GPR32_MEMd) =
|
|
DoNothingWithParam<R32, M32, IF_32BIT_ELSE(R32W, R64W)>;
|
|
|
|
DEF_ISEL(UD2) = DoNothingWithParam<IF_32BIT_ELSE(R32W, R64W)>;
|
|
|
|
DEF_ISEL(HLT) = DoNothingWithParam<IF_32BIT_ELSE(R32W, R64W)>;
|
|
|
|
/*
|
|
230 INVPCID INVPCID_GPR64_MEMdq MISC INVPCID INVPCID ATTRIBUTES: NOTSX RING0
|
|
231 INVPCID INVPCID_GPR32_MEMdq MISC INVPCID INVPCID ATTRIBUTES: NOTSX RING0
|
|
639 MONITOR MONITOR MISC SSE3 SSE3 ATTRIBUTES: NOTSX RING0
|
|
1924 MWAIT MWAIT MISC SSE3 SSE3 ATTRIBUTES: NOTSX RING0
|
|
*/
|