diff --git a/core/ir/aarch64/codec.c b/core/ir/aarch64/codec.c index 845fafbe0cb..9a54551e338 100644 --- a/core/ir/aarch64/codec.c +++ b/core/ir/aarch64/codec.c @@ -9841,6 +9841,12 @@ decode_common(dcontext_t *dcontext, byte *pc, byte *orig_pc, instr_t *instr) opnd_get_reg(instr_get_src(instr, 0)) == DR_REG_NZCV) { eflags |= EFLAGS_READ_NZCV; } + if (opc == OP_mrs && instr_num_srcs(instr) == 1 && + opnd_is_reg(instr_get_src(instr, 0)) && + (opnd_get_reg(instr_get_src(instr, 0)) == DR_REG_RNDR || + opnd_get_reg(instr_get_src(instr, 0)) == DR_REG_RNDRRS)) { + eflags |= EFLAGS_WRITE_NZCV; + } if (opc == OP_msr && instr_num_dsts(instr) == 1 && opnd_is_reg(instr_get_dst(instr, 0)) && opnd_get_reg(instr_get_dst(instr, 0)) == DR_REG_NZCV) { diff --git a/suite/tests/CMakeLists.txt b/suite/tests/CMakeLists.txt index f44df2a9acc..c7956b728e3 100644 --- a/suite/tests/CMakeLists.txt +++ b/suite/tests/CMakeLists.txt @@ -1983,7 +1983,8 @@ message(STATUS "Processing tests and generating expected output patterns") if (ARM) set(sfx "arm") elseif (AARCH64) - set(sfx "aarch64") + # New aarch64 ir tests are added to arch version/feature specific files. + set(sfx "aarch64_legacy") elseif (RISCV64) set(sfx "riscv64") else () @@ -2025,6 +2026,7 @@ if (NOT ANDROID) if (AARCH64) tobuild_api(api.ir_negative api/ir_aarch64_negative.c "" "" OFF OFF OFF) + tobuild_api(api.ir_v80 api/ir_aarch64_v80.c "" "" OFF OFF OFF) tobuild_api(api.ir_v81 api/ir_aarch64_v81.c "" "" OFF OFF OFF) tobuild_api(api.ir_v82 api/ir_aarch64_v82.c "" "" OFF OFF OFF) tobuild_api(api.ir_v83 api/ir_aarch64_v83.c "" "" OFF OFF OFF) diff --git a/suite/tests/api/ir_aarch64.c b/suite/tests/api/ir_aarch64_legacy.c similarity index 99% rename from suite/tests/api/ir_aarch64.c rename to suite/tests/api/ir_aarch64_legacy.c index 15ad4f97448..e0982c311df 100644 --- a/suite/tests/api/ir_aarch64.c +++ b/suite/tests/api/ir_aarch64_legacy.c @@ -7117,6 +7117,10 @@ main(int argc, char *argv[]) ld3r(dcontext); ld4r(dcontext); + /* To add new tests for v8.0 instructions please use the TEST_LOOP*() macros and + * add them to ir_aarch64_v80.c + */ + test_internal_encode(dcontext); test_vector_length(dcontext); diff --git a/suite/tests/api/ir_aarch64.expect b/suite/tests/api/ir_aarch64_legacy.expect similarity index 100% rename from suite/tests/api/ir_aarch64.expect rename to suite/tests/api/ir_aarch64_legacy.expect diff --git a/suite/tests/api/ir_aarch64_v80.c b/suite/tests/api/ir_aarch64_v80.c new file mode 100644 index 00000000000..3dc6514f48c --- /dev/null +++ b/suite/tests/api/ir_aarch64_v80.c @@ -0,0 +1,249 @@ +/* ********************************************************** + * Copyright (c) 2024 ARM Limited. All rights reserved. + * **********************************************************/ + +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of ARM Limited nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL ARM LIMITED OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +/* Define DR_FAST_IR to verify that everything compiles when we call the inline + * versions of these routines. + */ +#ifndef STANDALONE_DECODER +# define DR_FAST_IR 1 +#endif + +/* Uses the DR API, using DR as a standalone library, rather than + * being a client library working with DR on a target program. + */ + +#include "configure.h" +#include "dr_api.h" +#include "tools.h" + +#include "ir_aarch64.h" + +TEST_INSTR(mrs) +{ + /* Testing MRS , # */ + static const reg_id_t systemreg[] = { + DR_REG_NZCV, + DR_REG_FPCR, + DR_REG_FPSR, + DR_REG_MDCCSR_EL0, + DR_REG_DBGDTR_EL0, + DR_REG_DBGDTRRX_EL0, + DR_REG_SP_EL0, + DR_REG_SPSEL, + DR_REG_CURRENTEL, + DR_REG_PAN, + DR_REG_UAO, + DR_REG_CTR_EL0, + DR_REG_DCZID_EL0, + DR_REG_RNDR, + DR_REG_RNDRRS, + DR_REG_DAIF, + DR_REG_DIT, + DR_REG_SSBS, + DR_REG_TCO, + DR_REG_DSPSR_EL0, + DR_REG_DLR_EL0, + DR_REG_PMCR_EL0, + DR_REG_PMCNTENSET_EL0, + DR_REG_PMCNTENCLR_EL0, + DR_REG_PMOVSCLR_EL0, + DR_REG_PMSWINC_EL0, + DR_REG_PMSELR_EL0, + DR_REG_PMCEID0_EL0, + DR_REG_PMCEID1_EL0, + DR_REG_PMCCNTR_EL0, + DR_REG_PMXEVTYPER_EL0, + DR_REG_PMXEVCNTR_EL0, + DR_REG_PMUSERENR_EL0, + DR_REG_PMOVSSET_EL0, + DR_REG_SCXTNUM_EL0, + DR_REG_CNTFRQ_EL0, + DR_REG_CNTPCT_EL0, + DR_REG_CNTP_TVAL_EL0, + DR_REG_CNTP_CTL_EL0, + DR_REG_CNTP_CVAL_EL0, + DR_REG_CNTV_TVAL_EL0, + DR_REG_CNTV_CTL_EL0, + DR_REG_CNTV_CVAL_EL0, + DR_REG_PMEVTYPER0_EL0, + DR_REG_PMEVTYPER1_EL0, + DR_REG_PMEVTYPER2_EL0, + DR_REG_PMEVTYPER3_EL0, + DR_REG_PMEVTYPER4_EL0, + DR_REG_PMEVTYPER5_EL0, + DR_REG_PMEVTYPER6_EL0, + DR_REG_PMEVTYPER7_EL0, + DR_REG_PMEVTYPER8_EL0, + DR_REG_PMEVTYPER9_EL0, + DR_REG_PMEVTYPER10_EL0, + DR_REG_PMEVTYPER11_EL0, + DR_REG_PMEVTYPER12_EL0, + DR_REG_PMEVTYPER13_EL0, + DR_REG_PMEVTYPER14_EL0, + DR_REG_PMEVTYPER15_EL0, + DR_REG_PMEVTYPER16_EL0, + DR_REG_PMEVTYPER17_EL0, + DR_REG_PMEVTYPER18_EL0, + DR_REG_PMEVTYPER19_EL0, + DR_REG_PMEVTYPER20_EL0, + DR_REG_PMEVTYPER21_EL0, + DR_REG_PMEVTYPER22_EL0, + DR_REG_PMEVTYPER23_EL0, + DR_REG_PMEVTYPER24_EL0, + DR_REG_PMEVTYPER25_EL0, + DR_REG_PMEVTYPER26_EL0, + DR_REG_PMEVTYPER27_EL0, + DR_REG_PMEVTYPER28_EL0, + DR_REG_PMEVTYPER29_EL0, + DR_REG_PMEVTYPER30_EL0, + DR_REG_PMCCFILTR_EL0, + DR_REG_SPSR_IRQ, + DR_REG_SPSR_ABT, + DR_REG_SPSR_UND, + DR_REG_SPSR_FIQ, + DR_REG_ID_AA64ISAR0_EL1, + DR_REG_ID_AA64ISAR1_EL1, + DR_REG_ID_AA64ISAR2_EL1, + DR_REG_ID_AA64PFR0_EL1, + DR_REG_ID_AA64MMFR1_EL1, + DR_REG_ID_AA64DFR0_EL1, + DR_REG_ID_AA64ZFR0_EL1, + DR_REG_ID_AA64PFR1_EL1, + DR_REG_ID_AA64MMFR2_EL1, + DR_REG_MIDR_EL1, + DR_REG_MPIDR_EL1, + DR_REG_REVIDR_EL1, + }; + static const size_t sysreg_count = sizeof(systemreg) / sizeof(systemreg[0]); + + TEST_LOOP_EXPECT( + mrs, sysreg_count, + INSTR_CREATE_mrs(dc, opnd_create_reg(DR_REG_X0 + (i % 31)), + opnd_create_reg(systemreg[i])), + { + EXPECT_DISASSEMBLY( + /* clang-format off */ + "mrs %nzcv -> %x0", "mrs %fpcr -> %x1", + "mrs %fpsr -> %x2", "mrs %mdccsr_el0 -> %x3", + "mrs %dbgdtr_el0 -> %x4", "mrs %dbgdtrrx_el0 -> %x5", + "mrs %sp_el0 -> %x6", "mrs %spsel -> %x7", + "mrs %currentel -> %x8", "mrs %pan -> %x9", + "mrs %uao -> %x10", "mrs %ctr_el0 -> %x11", + "mrs %dczid_el0 -> %x12", "mrs %rndr -> %x13", + "mrs %rndrrs -> %x14", "mrs %daif -> %x15", + "mrs %dit -> %x16", "mrs %ssbs -> %x17", + "mrs %tco -> %x18", "mrs %dspsr_el0 -> %x19", + "mrs %dlr_el0 -> %x20", "mrs %pmcr_el0 -> %x21", + "mrs %pmcntenset_el0 -> %x22", "mrs %pmcntenclr_el0 -> %x23", + "mrs %pmovsclr_el0 -> %x24", "mrs %pmswinc_el0 -> %x25", + "mrs %pmselr_el0 -> %x26", "mrs %pmceid0_el0 -> %x27", + "mrs %pmceid1_el0 -> %x28", "mrs %pmccntr_el0 -> %x29", + "mrs %pmxevtyper_el0 -> %x30", "mrs %pmxevcntr_el0 -> %x0", + "mrs %pmuserenr_el0 -> %x1", "mrs %pmovsset_el0 -> %x2", + "mrs %scxtnum_el0 -> %x3", "mrs %cntfrq_el0 -> %x4", + "mrs %cntpct_el0 -> %x5", "mrs %cntp_tval_el0 -> %x6", + "mrs %cntp_ctl_el0 -> %x7", "mrs %cntp_cval_el0 -> %x8", + "mrs %cntv_tval_el0 -> %x9", "mrs %cntv_ctl_el0 -> %x10", + "mrs %cntv_cval_el0 -> %x11", "mrs %pmevtyper0_el0 -> %x12", + "mrs %pmevtyper1_el0 -> %x13", "mrs %pmevtyper2_el0 -> %x14", + "mrs %pmevtyper3_el0 -> %x15", "mrs %pmevtyper4_el0 -> %x16", + "mrs %pmevtyper5_el0 -> %x17", "mrs %pmevtyper6_el0 -> %x18", + "mrs %pmevtyper7_el0 -> %x19", "mrs %pmevtyper8_el0 -> %x20", + "mrs %pmevtyper9_el0 -> %x21", "mrs %pmevtyper10_el0 -> %x22", + "mrs %pmevtyper11_el0 -> %x23", "mrs %pmevtyper12_el0 -> %x24", + "mrs %pmevtyper13_el0 -> %x25", "mrs %pmevtyper14_el0 -> %x26", + "mrs %pmevtyper15_el0 -> %x27", "mrs %pmevtyper16_el0 -> %x28", + "mrs %pmevtyper17_el0 -> %x29", "mrs %pmevtyper18_el0 -> %x30", + "mrs %pmevtyper19_el0 -> %x0", "mrs %pmevtyper20_el0 -> %x1", + "mrs %pmevtyper21_el0 -> %x2", "mrs %pmevtyper22_el0 -> %x3", + "mrs %pmevtyper23_el0 -> %x4", "mrs %pmevtyper24_el0 -> %x5", + "mrs %pmevtyper25_el0 -> %x6", "mrs %pmevtyper26_el0 -> %x7", + "mrs %pmevtyper27_el0 -> %x8", "mrs %pmevtyper28_el0 -> %x9", + "mrs %pmevtyper29_el0 -> %x10", "mrs %pmevtyper30_el0 -> %x11", + "mrs %pmccfiltr_el0 -> %x12", "mrs %spsr_irq -> %x13", + "mrs %spsr_abt -> %x14", "mrs %spsr_und -> %x15", + "mrs %spsr_fiq -> %x16", "mrs %id_aa64isar0_el1 -> %x17", + "mrs %id_aa64isar1_el1 -> %x18","mrs %id_aa64isar2_el1 -> %x19", + "mrs %id_aa64pfr0_el1 -> %x20", "mrs %id_aa64mmfr1_el1 -> %x21", + "mrs %id_aa64dfr0_el1 -> %x22", "mrs %id_aa64zfr0_el1 -> %x23", + "mrs %id_aa64pfr1_el1 -> %x24", "mrs %id_aa64mmfr2_el1 -> %x25", + "mrs %midr_el1 -> %x26", "mrs %mpidr_el1 -> %x27", + "mrs %revidr_el1 -> %x28", + /* clang-format on */ + ); + switch (systemreg[i]) { + case DR_REG_NZCV: + EXPECT_TRUE(TEST(EFLAGS_READ_NZCV, + instr_get_arith_flags(instr, DR_QUERY_INCLUDE_ALL))); + EXPECT_FALSE(TEST(EFLAGS_WRITE_NZCV, + instr_get_arith_flags(instr, DR_QUERY_INCLUDE_ALL))); + break; + case DR_REG_RNDR: + case DR_REG_RNDRRS: + EXPECT_FALSE(TEST(EFLAGS_READ_NZCV, + instr_get_arith_flags(instr, DR_QUERY_INCLUDE_ALL))); + EXPECT_TRUE(TEST(EFLAGS_WRITE_NZCV, + instr_get_arith_flags(instr, DR_QUERY_INCLUDE_ALL))); + break; + default: + EXPECT_FALSE(TEST(EFLAGS_READ_NZCV, + instr_get_arith_flags(instr, DR_QUERY_INCLUDE_ALL))); + EXPECT_FALSE(TEST(EFLAGS_WRITE_NZCV, + instr_get_arith_flags(instr, DR_QUERY_INCLUDE_ALL))); + } + }); +} + +int +main(int argc, char *argv[]) +{ +#ifdef STANDALONE_DECODER + void *dcontext = GLOBAL_DCONTEXT; +#else + void *dcontext = dr_standalone_init(); +#endif + bool result = true; + bool test_result; + instr_t *instr; + + enable_all_test_cpu_features(); + + RUN_INSTR_TEST(mrs); + + print("All v8.0 tests complete.\n"); +#ifndef STANDALONE_DECODER + dr_standalone_exit(); +#endif + if (result) + return 0; + return 1; +} diff --git a/suite/tests/api/ir_aarch64_v80.expect b/suite/tests/api/ir_aarch64_v80.expect new file mode 100644 index 00000000000..80111e4bfe7 --- /dev/null +++ b/suite/tests/api/ir_aarch64_v80.expect @@ -0,0 +1 @@ +All v8.0 tests complete.