mirror of
https://github.com/lifting-bits/remill
synced 2026-06-21 13:56:07 +00:00
c743aa4f85
* Minor reformatting, re-enabling test of CCMP. * Modified post-decoder of CCMP_n_CONDCMP_IMM, added more tests for it. Also added post-decoders, but NO tests for the register-register variant * Fixes #144. * Tests for LDP and STP. Decoder and semantics, but no tests for LDR and STR on the B, H, S, D, and Q vector sub-regs. * Minor fix * Minor fix, I think, to pre-index memops * Minor simplifying code to pre- and post-index address operand handling
114 lines
3.7 KiB
C++
114 lines
3.7 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 {
|
|
|
|
template <bool (*check_cond)(const State &), typename D,
|
|
typename S1, typename S2>
|
|
DEF_SEM(CSEL, D dst, S1 src1, S2 src2) {
|
|
auto val = check_cond(state) ? Read(src1) : Read(src2);
|
|
WriteZExt(dst, val);
|
|
return memory;
|
|
}
|
|
} // namespace
|
|
|
|
#define DEF_COND_ISEL(isel, sem, ...) \
|
|
DEF_ISEL(isel ## _GE) = sem<CondGE, __VA_ARGS__>; \
|
|
DEF_ISEL(isel ## _GT) = sem<CondGT, __VA_ARGS__>; \
|
|
DEF_ISEL(isel ## _LE) = sem<CondLE, __VA_ARGS__>; \
|
|
DEF_ISEL(isel ## _LT) = sem<CondLT, __VA_ARGS__>; \
|
|
DEF_ISEL(isel ## _EQ) = sem<CondEQ, __VA_ARGS__>; \
|
|
DEF_ISEL(isel ## _NE) = sem<CondNE, __VA_ARGS__>; \
|
|
DEF_ISEL(isel ## _CS) = sem<CondCS, __VA_ARGS__>; \
|
|
DEF_ISEL(isel ## _CC) = sem<CondCC, __VA_ARGS__>; \
|
|
DEF_ISEL(isel ## _MI) = sem<CondMI, __VA_ARGS__>; \
|
|
DEF_ISEL(isel ## _PL) = sem<CondPL, __VA_ARGS__>; \
|
|
DEF_ISEL(isel ## _VS) = sem<CondVS, __VA_ARGS__>; \
|
|
DEF_ISEL(isel ## _VC) = sem<CondVC, __VA_ARGS__>; \
|
|
DEF_ISEL(isel ## _HI) = sem<CondHI, __VA_ARGS__>; \
|
|
DEF_ISEL(isel ## _LS) = sem<CondLS, __VA_ARGS__>; \
|
|
DEF_ISEL(isel ## _AL) = sem<CondAL, __VA_ARGS__>;
|
|
|
|
DEF_COND_ISEL(CSEL_32_CONDSEL, CSEL, R32W, R32, R32)
|
|
DEF_COND_ISEL(CSEL_64_CONDSEL, CSEL, R64W, R64, R64)
|
|
|
|
namespace {
|
|
|
|
template <bool (*check_cond)(const State &), typename D,
|
|
typename S1, typename S2>
|
|
DEF_SEM(CSNEG, D dst, S1 src1, S2 src2) {
|
|
WriteZExt(dst, Select(check_cond(state),
|
|
Read(src1),
|
|
UAdd(UNot(Read(src2)), ZExtTo<S2>(1))));
|
|
return memory;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
|
|
DEF_COND_ISEL(CSNEG_32_CONDSEL, CSNEG, R32W, R32, R32)
|
|
DEF_COND_ISEL(CSNEG_64_CONDSEL, CSNEG, R64W, R64, R64)
|
|
|
|
namespace {
|
|
|
|
template <bool (*check_cond)(const State &), typename D,
|
|
typename S1, typename S2>
|
|
DEF_SEM(CSINC, D dst, S1 src1, S2 src2) {
|
|
WriteZExt(dst, Select(check_cond(state), Read(src1), UAdd(Read(src2), 1)));
|
|
return memory;
|
|
}
|
|
} // namespace
|
|
|
|
DEF_COND_ISEL(CSINC_32_CONDSEL, CSINC, R32W, R32, R32)
|
|
DEF_COND_ISEL(CSINC_64_CONDSEL, CSINC, R64W, R64, R64)
|
|
|
|
namespace {
|
|
|
|
template <bool (*check_cond)(const State &), typename D,
|
|
typename S1, typename S2>
|
|
DEF_SEM(CSINV, D dst, S1 src1, S2 src2) {
|
|
WriteZExt(dst, Select(check_cond(state), Read(src1), UNot(Read(src2))));
|
|
return memory;
|
|
}
|
|
} // namespace
|
|
|
|
DEF_COND_ISEL(CSINV_32_CONDSEL, CSINV, R32W, R32, R32)
|
|
DEF_COND_ISEL(CSINV_64_CONDSEL, CSINV, R64W, R64, R64)
|
|
|
|
namespace {
|
|
template <bool (*check_cond)(const State &), typename S1, typename S2>
|
|
DEF_SEM(CCMP, S1 src1, S2 src2, S2 nzcv) {
|
|
using T = typename BaseType<S1>::BT;
|
|
if (check_cond(state)) {
|
|
(void) AddWithCarryNZCV(state, Read(src1), UNot(Read(src2)), T(1));
|
|
} else {
|
|
auto nzcv_val = Read(nzcv);
|
|
FLAG_V = UCmpNeq(UAnd(nzcv_val, T(1)), T(0));
|
|
FLAG_C = UCmpNeq(UAnd(nzcv_val, T(2)), T(0));
|
|
FLAG_Z = UCmpNeq(UAnd(nzcv_val, T(4)), T(0));
|
|
FLAG_N = UCmpNeq(UAnd(nzcv_val, T(8)), T(0));
|
|
}
|
|
return memory;
|
|
}
|
|
} // namespace
|
|
|
|
DEF_COND_ISEL(CCMP_32_CONDCMP_IMM, CCMP, R32, I32)
|
|
DEF_COND_ISEL(CCMP_64_CONDCMP_IMM, CCMP, R64, I64)
|
|
|
|
DEF_COND_ISEL(CCMP_32_CONDCMP_REG, CCMP, R32, R32)
|
|
DEF_COND_ISEL(CCMP_64_CONDCMP_REG, CCMP, R64, R64)
|