Files
Sonya 6322f794d1 New arch support (#461)
* 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>
2021-02-24 14:01:09 -05:00

119 lines
3.8 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.
*/
namespace {
#define MAKE_CMPXCHG_XAX(xax, xax_write, xax_read) \
template <typename D, typename S1, typename S2> \
DEF_SEM(CMPXCHG_##xax, D dst, S1 src1, S2 src2) { \
auto desired_val = Read(src2); \
auto check_val = Read(REG_##xax_read); \
auto prev_value = check_val; \
auto swap_flag = UCmpXchg(dst, check_val, desired_val); \
auto sub_res = USub(prev_value, check_val); \
WriteFlagsAddSub<tag_sub>(state, prev_value, check_val, sub_res); \
Write(FLAG_ZF, swap_flag); \
if (!swap_flag) { \
WriteZExt(REG_##xax_write, check_val); \
} \
return memory; \
}
MAKE_CMPXCHG_XAX(AL, AL, AL)
MAKE_CMPXCHG_XAX(AX, AX, AX)
MAKE_CMPXCHG_XAX(EAX, XAX, EAX)
IF_64BIT(MAKE_CMPXCHG_XAX(RAX, RAX, RAX))
DEF_SEM(DoCMPXCHG8B_MEMq, M64W dst, M64 src1) {
auto xdx = Read(REG_EDX);
auto xax = Read(REG_EAX);
auto xcx = Read(REG_ECX);
auto xbx = Read(REG_EBX);
auto desired_val = UOr(UShl(ZExt(xcx), 32), ZExt(xbx));
auto check_val = UOr(UShl(ZExt(xdx), 32), ZExt(xax));
auto swap_flag = UCmpXchg(dst, check_val, desired_val);
Write(FLAG_ZF, swap_flag);
Write(REG_EDX, Trunc(UShr(check_val, 32)));
Write(REG_EAX, Trunc(check_val));
return memory;
}
#if 64 == ADDRESS_SIZE_BITS
DEF_SEM(DoCMPXCHG16B_MEMdq, M128W dst, M128 src1) {
auto xdx = Read(REG_RDX);
auto xax = Read(REG_RAX);
auto xcx = Read(REG_RCX);
auto xbx = Read(REG_RBX);
auto desired_val = UOr(UShl(ZExt(xcx), 64), ZExt(xbx));
auto check_val = UOr(UShl(ZExt(xdx), 64), ZExt(xax));
auto swap_flag = UCmpXchg(dst, check_val, desired_val);
Write(FLAG_ZF, swap_flag);
Write(REG_RDX, Trunc(UShr(check_val, 64)));
Write(REG_RAX, Trunc(check_val));
return memory;
}
#endif // 64 == ADDRESS_SIZE_BITS
} // namespace
DEF_ISEL(CMPXCHG_MEMb_GPR8) = CMPXCHG_AL<M8W, M8, R8>;
DEF_ISEL(CMPXCHG_GPR8_GPR8) = CMPXCHG_AL<R8W, R8, R8>;
DEF_ISEL(CMPXCHG_MEMv_GPRv_8) = CMPXCHG_AL<M8W, M8, R8>;
DEF_ISEL(CMPXCHG_GPRv_GPRv_8) = CMPXCHG_AL<R8W, R8, R8>;
DEF_ISEL(CMPXCHG_MEMv_GPRv_16) = CMPXCHG_AX<M16W, M16, R16>;
DEF_ISEL(CMPXCHG_GPRv_GPRv_16) = CMPXCHG_AX<R16W, R16, R16>;
DEF_ISEL(CMPXCHG_MEMv_GPRv_32) = CMPXCHG_EAX<M32W, M32, R32>;
DEF_ISEL(CMPXCHG_GPRv_GPRv_32) = CMPXCHG_EAX<R32W, R32, R32>;
IF_64BIT(DEF_ISEL(CMPXCHG_MEMv_GPRv_64) = CMPXCHG_RAX<M64W, M64, R64>;)
IF_64BIT(DEF_ISEL(CMPXCHG_GPRv_GPRv_64) = CMPXCHG_RAX<R64W, R64, R64>;)
DEF_ISEL(CMPXCHG8B_MEMq) = DoCMPXCHG8B_MEMq;
#if 64 == ADDRESS_SIZE_BITS
DEF_ISEL(CMPXCHG16B_MEMdq) = DoCMPXCHG16B_MEMdq;
#endif // 64 == ADDRESS_SIZE_BITS
namespace {
// Atomic fetch-add.
template <typename D1, typename S1, typename D2, typename S2>
DEF_SEM(XADD, D1 dst1, S1 src1, D2 dst2, S2 src2) {
// Our lifter only injects atomic begin/end around memory access instructions
// but this instruction is a full memory barrier, even when registers are
// accessed.
if (IsRegister(dst1)) {
BarrierStoreLoad();
}
auto rhs = Read(src1);
auto lhs = Read(src2);
auto sum = UAddFetch(dst2, rhs);
WriteFlagsAddSub<tag_add>(state, rhs, lhs, sum);
WriteZExt(dst1, sum);
return memory;
}
} // namespace
DEF_ISEL(XADD_MEMb_GPR8) = XADD<M8W, M8, R8W, R8>;
DEF_ISEL(XADD_GPR8_GPR8) = XADD<R8W, R8, R8W, R8>;
DEF_ISEL_MnW_Mn_RnW_Rn(XADD_MEMv_GPRv, XADD);
DEF_ISEL_RnW_Rn_RnW_Rn(XADD_GPRv_GPRv, XADD);