diff --git a/suite/cstest/include/test_detail.h b/suite/cstest/include/test_detail.h index c849d4769a..df34d7e8f0 100644 --- a/suite/cstest/include/test_detail.h +++ b/suite/cstest/include/test_detail.h @@ -12,6 +12,7 @@ #include "test_detail_aarch64.h" #include "test_detail_arm.h" #include "test_detail_evm.h" +#include "test_detail_loongarch.h" #include "test_detail_mos65xx.h" #include "test_detail_ppc.h" #include "test_detail_riscv.h" @@ -51,10 +52,10 @@ typedef struct { TestDetailTMS320c64x *tms320c64x; TestDetailMos65xx *mos65xx; TestDetailEVM *evm; + TestDetailLoongArch *loongarch; // cs_x86_test x86; // cs_m68k_test m68k; // cs_wasm_test wasm; - // cs_loongarch_test loongarch; char **regs_read; uint8_t regs_read_count; @@ -123,6 +124,9 @@ static const cyaml_schema_field_t test_detail_mapping_schema[] = { CYAML_FIELD_MAPPING_PTR("evm", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL, TestDetail, evm, test_detail_evm_mapping_schema), + CYAML_FIELD_MAPPING_PTR( + "loongarch", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL, + TestDetail, loongarch, test_detail_loongarch_mapping_schema), CYAML_FIELD_SEQUENCE("regs_read", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL, TestDetail, regs_read, ®_group_schema, 0, 255), diff --git a/suite/cstest/include/test_detail_loongarch.h b/suite/cstest/include/test_detail_loongarch.h new file mode 100644 index 0000000000..2042200594 --- /dev/null +++ b/suite/cstest/include/test_detail_loongarch.h @@ -0,0 +1,77 @@ +// Copyright © 2024 Rot127 +// SPDX-License-Identifier: BSD-3 + +#ifndef TEST_DETAIL_LOONGARCH_H +#define TEST_DETAIL_LOONGARCH_H + +#include +#include + +typedef struct { + char *type; + char *access; + + char *reg; + uint64_t imm; + char *mem_base; + char *mem_index; + int64_t mem_disp; +} TestDetailLoongArchOp; + +static const cyaml_schema_field_t test_detail_loongarch_op_mapping_schema[] = { + CYAML_FIELD_STRING_PTR("type", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL, + TestDetailLoongArchOp, type, 0, CYAML_UNLIMITED), + CYAML_FIELD_STRING_PTR( + "access", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL, + TestDetailLoongArchOp, access, 0, CYAML_UNLIMITED), + CYAML_FIELD_STRING_PTR("reg", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL, + TestDetailLoongArchOp, reg, 0, CYAML_UNLIMITED), + CYAML_FIELD_INT("imm", CYAML_FLAG_OPTIONAL, TestDetailLoongArchOp, imm), + CYAML_FIELD_STRING_PTR( + "mem_base", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL, + TestDetailLoongArchOp, mem_base, 0, CYAML_UNLIMITED), + CYAML_FIELD_STRING_PTR( + "mem_index", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL, + TestDetailLoongArchOp, mem_index, 0, CYAML_UNLIMITED), + CYAML_FIELD_INT("mem_disp", CYAML_FLAG_OPTIONAL, TestDetailLoongArchOp, + mem_disp), + CYAML_FIELD_END +}; + +static const cyaml_schema_value_t test_detail_loongarch_op_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, TestDetailLoongArchOp, + test_detail_loongarch_op_mapping_schema), +}; + +typedef struct { + char *format; + TestDetailLoongArchOp **operands; + uint32_t operands_count; +} TestDetailLoongArch; + +static const cyaml_schema_field_t test_detail_loongarch_mapping_schema[] = { + CYAML_FIELD_STRING_PTR("format", + CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL, + TestDetailLoongArch, format, 0, CYAML_UNLIMITED), + CYAML_FIELD_SEQUENCE("operands", + CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL, + TestDetailLoongArch, operands, + &test_detail_loongarch_op_schema, 0, + CYAML_UNLIMITED), // 0-MAX options + CYAML_FIELD_END +}; + +TestDetailLoongArch *test_detail_loongarch_new(); +TestDetailLoongArch * +test_detail_loongarch_clone(const TestDetailLoongArch *detail); +void test_detail_loongarch_free(TestDetailLoongArch *detail); + +TestDetailLoongArchOp *test_detail_loongarch_op_new(); +TestDetailLoongArchOp * +test_detail_loongarch_op_clone(const TestDetailLoongArchOp *detail); +void test_detail_loongarch_op_free(TestDetailLoongArchOp *detail); + +bool test_expected_loongarch(csh *handle, const cs_loongarch *actual, + const TestDetailLoongArch *expected); + +#endif // TEST_DETAIL_LOONGARCH_H diff --git a/suite/cstest/include/test_mapping.h b/suite/cstest/include/test_mapping.h index d4625f2aa6..6de4c22e21 100644 --- a/suite/cstest/include/test_mapping.h +++ b/suite/cstest/include/test_mapping.h @@ -458,6 +458,251 @@ static const cs_enum_id_map cs_enum_map[] = { { .str = "HPPA_OP_MEM", .val = HPPA_OP_MEM }, { .str = "HPPA_OP_REG", .val = HPPA_OP_REG }, { .str = "HPPA_OP_TARGET", .val = HPPA_OP_TARGET }, + { .str = "LOONGARCH_FEATURE_HASLAGLOBALWITHABS", + .val = LOONGARCH_FEATURE_HASLAGLOBALWITHABS }, + { .str = "LOONGARCH_FEATURE_HASLAGLOBALWITHPCREL", + .val = LOONGARCH_FEATURE_HASLAGLOBALWITHPCREL }, + { .str = "LOONGARCH_FEATURE_HASLALOCALWITHABS", + .val = LOONGARCH_FEATURE_HASLALOCALWITHABS }, + { .str = "LOONGARCH_FEATURE_ISLA32", .val = LOONGARCH_FEATURE_ISLA32 }, + { .str = "LOONGARCH_FEATURE_ISLA64", .val = LOONGARCH_FEATURE_ISLA64 }, + { .str = "LOONGARCH_GRP_BRANCH_RELATIVE", + .val = LOONGARCH_GRP_BRANCH_RELATIVE }, + { .str = "LOONGARCH_GRP_CALL", .val = LOONGARCH_GRP_CALL }, + { .str = "LOONGARCH_GRP_INT", .val = LOONGARCH_GRP_INT }, + { .str = "LOONGARCH_GRP_IRET", .val = LOONGARCH_GRP_IRET }, + { .str = "LOONGARCH_GRP_JUMP", .val = LOONGARCH_GRP_JUMP }, + { .str = "LOONGARCH_GRP_PRIVILEGE", .val = LOONGARCH_GRP_PRIVILEGE }, + { .str = "LOONGARCH_GRP_RET", .val = LOONGARCH_GRP_RET }, + { .str = "LOONGARCH_INSN_FORM_FMT1RI13_VI", + .val = LOONGARCH_INSN_FORM_FMT1RI13_VI }, + { .str = "LOONGARCH_INSN_FORM_FMT1RI13_XI", + .val = LOONGARCH_INSN_FORM_FMT1RI13_XI }, + { .str = "LOONGARCH_INSN_FORM_FMT1RI20", + .val = LOONGARCH_INSN_FORM_FMT1RI20 }, + { .str = "LOONGARCH_INSN_FORM_FMT1RI21", + .val = LOONGARCH_INSN_FORM_FMT1RI21 }, + { .str = "LOONGARCH_INSN_FORM_FMT1RI4", + .val = LOONGARCH_INSN_FORM_FMT1RI4 }, + { .str = "LOONGARCH_INSN_FORM_FMT1RI5I8", + .val = LOONGARCH_INSN_FORM_FMT1RI5I8 }, + { .str = "LOONGARCH_INSN_FORM_FMT1RI8", + .val = LOONGARCH_INSN_FORM_FMT1RI8 }, + { .str = "LOONGARCH_INSN_FORM_FMT2R", + .val = LOONGARCH_INSN_FORM_FMT2R }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI10_VRI", + .val = LOONGARCH_INSN_FORM_FMT2RI10_VRI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI10_XRI", + .val = LOONGARCH_INSN_FORM_FMT2RI10_XRI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI11_VRI", + .val = LOONGARCH_INSN_FORM_FMT2RI11_VRI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI11_XRI", + .val = LOONGARCH_INSN_FORM_FMT2RI11_XRI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI12", + .val = LOONGARCH_INSN_FORM_FMT2RI12 }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI12_VRI", + .val = LOONGARCH_INSN_FORM_FMT2RI12_VRI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI12_XRI", + .val = LOONGARCH_INSN_FORM_FMT2RI12_XRI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI14", + .val = LOONGARCH_INSN_FORM_FMT2RI14 }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI16", + .val = LOONGARCH_INSN_FORM_FMT2RI16 }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI1_RVI", + .val = LOONGARCH_INSN_FORM_FMT2RI1_RVI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI1_VRI", + .val = LOONGARCH_INSN_FORM_FMT2RI1_VRI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI1_VVI", + .val = LOONGARCH_INSN_FORM_FMT2RI1_VVI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI1_XXI", + .val = LOONGARCH_INSN_FORM_FMT2RI1_XXI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI2_RVI", + .val = LOONGARCH_INSN_FORM_FMT2RI2_RVI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI2_RXI", + .val = LOONGARCH_INSN_FORM_FMT2RI2_RXI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI2_VRI", + .val = LOONGARCH_INSN_FORM_FMT2RI2_VRI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI2_VVI", + .val = LOONGARCH_INSN_FORM_FMT2RI2_VVI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI2_XRI", + .val = LOONGARCH_INSN_FORM_FMT2RI2_XRI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI2_XXI", + .val = LOONGARCH_INSN_FORM_FMT2RI2_XXI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI3", + .val = LOONGARCH_INSN_FORM_FMT2RI3 }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI3_RVI", + .val = LOONGARCH_INSN_FORM_FMT2RI3_RVI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI3_RXI", + .val = LOONGARCH_INSN_FORM_FMT2RI3_RXI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI3_VRI", + .val = LOONGARCH_INSN_FORM_FMT2RI3_VRI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI3_VVI", + .val = LOONGARCH_INSN_FORM_FMT2RI3_VVI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI3_XRI", + .val = LOONGARCH_INSN_FORM_FMT2RI3_XRI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI3_XXI", + .val = LOONGARCH_INSN_FORM_FMT2RI3_XXI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI4", + .val = LOONGARCH_INSN_FORM_FMT2RI4 }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI4_RVI", + .val = LOONGARCH_INSN_FORM_FMT2RI4_RVI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI4_VRI", + .val = LOONGARCH_INSN_FORM_FMT2RI4_VRI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI4_VVI", + .val = LOONGARCH_INSN_FORM_FMT2RI4_VVI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI4_XXI", + .val = LOONGARCH_INSN_FORM_FMT2RI4_XXI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI5", + .val = LOONGARCH_INSN_FORM_FMT2RI5 }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI5_VVI", + .val = LOONGARCH_INSN_FORM_FMT2RI5_VVI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI5_XXI", + .val = LOONGARCH_INSN_FORM_FMT2RI5_XXI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI6", + .val = LOONGARCH_INSN_FORM_FMT2RI6 }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI6_VVI", + .val = LOONGARCH_INSN_FORM_FMT2RI6_VVI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI6_XXI", + .val = LOONGARCH_INSN_FORM_FMT2RI6_XXI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI7_VVI", + .val = LOONGARCH_INSN_FORM_FMT2RI7_VVI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI7_XXI", + .val = LOONGARCH_INSN_FORM_FMT2RI7_XXI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI8", + .val = LOONGARCH_INSN_FORM_FMT2RI8 }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI8I1_VRII", + .val = LOONGARCH_INSN_FORM_FMT2RI8I1_VRII }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI8I2_VRII", + .val = LOONGARCH_INSN_FORM_FMT2RI8I2_VRII }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI8I2_XRII", + .val = LOONGARCH_INSN_FORM_FMT2RI8I2_XRII }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI8I3_VRII", + .val = LOONGARCH_INSN_FORM_FMT2RI8I3_VRII }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI8I3_XRII", + .val = LOONGARCH_INSN_FORM_FMT2RI8I3_XRII }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI8I4_VRII", + .val = LOONGARCH_INSN_FORM_FMT2RI8I4_VRII }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI8I4_XRII", + .val = LOONGARCH_INSN_FORM_FMT2RI8I4_XRII }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI8I5_XRII", + .val = LOONGARCH_INSN_FORM_FMT2RI8I5_XRII }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI8_VVI", + .val = LOONGARCH_INSN_FORM_FMT2RI8_VVI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI8_XXI", + .val = LOONGARCH_INSN_FORM_FMT2RI8_XXI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI9_VRI", + .val = LOONGARCH_INSN_FORM_FMT2RI9_VRI }, + { .str = "LOONGARCH_INSN_FORM_FMT2RI9_XRI", + .val = LOONGARCH_INSN_FORM_FMT2RI9_XRI }, + { .str = "LOONGARCH_INSN_FORM_FMT2R_CV", + .val = LOONGARCH_INSN_FORM_FMT2R_CV }, + { .str = "LOONGARCH_INSN_FORM_FMT2R_CX", + .val = LOONGARCH_INSN_FORM_FMT2R_CX }, + { .str = "LOONGARCH_INSN_FORM_FMT2R_VR", + .val = LOONGARCH_INSN_FORM_FMT2R_VR }, + { .str = "LOONGARCH_INSN_FORM_FMT2R_VV", + .val = LOONGARCH_INSN_FORM_FMT2R_VV }, + { .str = "LOONGARCH_INSN_FORM_FMT2R_XR", + .val = LOONGARCH_INSN_FORM_FMT2R_XR }, + { .str = "LOONGARCH_INSN_FORM_FMT2R_XX", + .val = LOONGARCH_INSN_FORM_FMT2R_XX }, + { .str = "LOONGARCH_INSN_FORM_FMT3R", + .val = LOONGARCH_INSN_FORM_FMT3R }, + { .str = "LOONGARCH_INSN_FORM_FMT3RI2", + .val = LOONGARCH_INSN_FORM_FMT3RI2 }, + { .str = "LOONGARCH_INSN_FORM_FMT3RI3", + .val = LOONGARCH_INSN_FORM_FMT3RI3 }, + { .str = "LOONGARCH_INSN_FORM_FMT3R_VRR", + .val = LOONGARCH_INSN_FORM_FMT3R_VRR }, + { .str = "LOONGARCH_INSN_FORM_FMT3R_VVR", + .val = LOONGARCH_INSN_FORM_FMT3R_VVR }, + { .str = "LOONGARCH_INSN_FORM_FMT3R_VVV", + .val = LOONGARCH_INSN_FORM_FMT3R_VVV }, + { .str = "LOONGARCH_INSN_FORM_FMT3R_XRR", + .val = LOONGARCH_INSN_FORM_FMT3R_XRR }, + { .str = "LOONGARCH_INSN_FORM_FMT3R_XXR", + .val = LOONGARCH_INSN_FORM_FMT3R_XXR }, + { .str = "LOONGARCH_INSN_FORM_FMT3R_XXX", + .val = LOONGARCH_INSN_FORM_FMT3R_XXX }, + { .str = "LOONGARCH_INSN_FORM_FMT4R_VVVV", + .val = LOONGARCH_INSN_FORM_FMT4R_VVVV }, + { .str = "LOONGARCH_INSN_FORM_FMT4R_XXXX", + .val = LOONGARCH_INSN_FORM_FMT4R_XXXX }, + { .str = "LOONGARCH_INSN_FORM_FMTASRT", + .val = LOONGARCH_INSN_FORM_FMTASRT }, + { .str = "LOONGARCH_INSN_FORM_FMTBSTR_D", + .val = LOONGARCH_INSN_FORM_FMTBSTR_D }, + { .str = "LOONGARCH_INSN_FORM_FMTBSTR_W", + .val = LOONGARCH_INSN_FORM_FMTBSTR_W }, + { .str = "LOONGARCH_INSN_FORM_FMTCACOP", + .val = LOONGARCH_INSN_FORM_FMTCACOP }, + { .str = "LOONGARCH_INSN_FORM_FMTCSR", + .val = LOONGARCH_INSN_FORM_FMTCSR }, + { .str = "LOONGARCH_INSN_FORM_FMTCSRXCHG", + .val = LOONGARCH_INSN_FORM_FMTCSRXCHG }, + { .str = "LOONGARCH_INSN_FORM_FMTGR2SCR", + .val = LOONGARCH_INSN_FORM_FMTGR2SCR }, + { .str = "LOONGARCH_INSN_FORM_FMTI15", + .val = LOONGARCH_INSN_FORM_FMTI15 }, + { .str = "LOONGARCH_INSN_FORM_FMTI26", + .val = LOONGARCH_INSN_FORM_FMTI26 }, + { .str = "LOONGARCH_INSN_FORM_FMTI32", + .val = LOONGARCH_INSN_FORM_FMTI32 }, + { .str = "LOONGARCH_INSN_FORM_FMTINVTLB", + .val = LOONGARCH_INSN_FORM_FMTINVTLB }, + { .str = "LOONGARCH_INSN_FORM_FMTJISCR", + .val = LOONGARCH_INSN_FORM_FMTJISCR }, + { .str = "LOONGARCH_INSN_FORM_FMTLDPTE", + .val = LOONGARCH_INSN_FORM_FMTLDPTE }, + { .str = "LOONGARCH_INSN_FORM_FMTMFTOP", + .val = LOONGARCH_INSN_FORM_FMTMFTOP }, + { .str = "LOONGARCH_INSN_FORM_FMTMTTOP", + .val = LOONGARCH_INSN_FORM_FMTMTTOP }, + { .str = "LOONGARCH_INSN_FORM_FMTPRELD", + .val = LOONGARCH_INSN_FORM_FMTPRELD }, + { .str = "LOONGARCH_INSN_FORM_FMTPRELDX", + .val = LOONGARCH_INSN_FORM_FMTPRELDX }, + { .str = "LOONGARCH_INSN_FORM_FMTSCR2GR", + .val = LOONGARCH_INSN_FORM_FMTSCR2GR }, + { .str = "LOONGARCH_INSN_FORM_FPFMT2R", + .val = LOONGARCH_INSN_FORM_FPFMT2R }, + { .str = "LOONGARCH_INSN_FORM_FPFMT2RI12", + .val = LOONGARCH_INSN_FORM_FPFMT2RI12 }, + { .str = "LOONGARCH_INSN_FORM_FPFMT3R", + .val = LOONGARCH_INSN_FORM_FPFMT3R }, + { .str = "LOONGARCH_INSN_FORM_FPFMT4R", + .val = LOONGARCH_INSN_FORM_FPFMT4R }, + { .str = "LOONGARCH_INSN_FORM_FPFMTBR", + .val = LOONGARCH_INSN_FORM_FPFMTBR }, + { .str = "LOONGARCH_INSN_FORM_FPFMTFCMP", + .val = LOONGARCH_INSN_FORM_FPFMTFCMP }, + { .str = "LOONGARCH_INSN_FORM_FPFMTFSEL", + .val = LOONGARCH_INSN_FORM_FPFMTFSEL }, + { .str = "LOONGARCH_INSN_FORM_FPFMTMEM", + .val = LOONGARCH_INSN_FORM_FPFMTMEM }, + { .str = "LOONGARCH_INSN_FORM_FPFMTMOV", + .val = LOONGARCH_INSN_FORM_FPFMTMOV }, + { .str = "LOONGARCH_INSN_FORM_NODSTFMT1R", + .val = LOONGARCH_INSN_FORM_NODSTFMT1R }, + { .str = "LOONGARCH_INSN_FORM_NODSTFMT1RI3", + .val = LOONGARCH_INSN_FORM_NODSTFMT1RI3 }, + { .str = "LOONGARCH_INSN_FORM_NODSTFMT1RI4", + .val = LOONGARCH_INSN_FORM_NODSTFMT1RI4 }, + { .str = "LOONGARCH_INSN_FORM_NODSTFMT1RI5", + .val = LOONGARCH_INSN_FORM_NODSTFMT1RI5 }, + { .str = "LOONGARCH_INSN_FORM_NODSTFMT1RI5I4", + .val = LOONGARCH_INSN_FORM_NODSTFMT1RI5I4 }, + { .str = "LOONGARCH_INSN_FORM_NODSTFMT1RI6", + .val = LOONGARCH_INSN_FORM_NODSTFMT1RI6 }, + { .str = "LOONGARCH_INSN_FORM_NODSTFMT2R", + .val = LOONGARCH_INSN_FORM_NODSTFMT2R }, + { .str = "LOONGARCH_INSN_FORM_NODSTFMT2RI4", + .val = LOONGARCH_INSN_FORM_NODSTFMT2RI4 }, + { .str = "LOONGARCH_INSN_FORM_PSEUDO", + .val = LOONGARCH_INSN_FORM_PSEUDO }, + { .str = "LOONGARCH_OP_IMM", .val = LOONGARCH_OP_IMM }, + { .str = "LOONGARCH_OP_MEM", .val = LOONGARCH_OP_MEM }, + { .str = "LOONGARCH_OP_REG", .val = LOONGARCH_OP_REG }, { .str = "M680X_FIRST_OP_IN_MNEM", .val = M680X_FIRST_OP_IN_MNEM }, { .str = "M680X_GRP_BRAREL", .val = M680X_GRP_BRAREL }, { .str = "M680X_GRP_CALL", .val = M680X_GRP_CALL }, diff --git a/suite/cstest/src/test_detail.c b/suite/cstest/src/test_detail.c index 582f233574..154f198b23 100644 --- a/suite/cstest/src/test_detail.c +++ b/suite/cstest/src/test_detail.c @@ -98,6 +98,10 @@ TestDetail *test_detail_clone(TestDetail *detail) if (detail->evm) { clone->evm = test_detail_evm_clone(detail->evm); } + if (detail->loongarch) { + clone->loongarch = + test_detail_loongarch_clone(detail->loongarch); + } return clone; } @@ -174,6 +178,9 @@ void test_detail_free(TestDetail *detail) if (detail->evm) { test_detail_evm_free(detail->evm); } + if (detail->loongarch) { + test_detail_loongarch_free(detail->loongarch); + } cs_mem_free(detail); } @@ -278,5 +285,9 @@ bool test_expected_detail(csh *handle, const cs_insn *insn, if (expected->evm) { return test_expected_evm(handle, &actual->evm, expected->evm); } + if (expected->loongarch) { + return test_expected_loongarch(handle, &actual->loongarch, + expected->loongarch); + } return true; } diff --git a/suite/cstest/src/test_detail_loongarch.c b/suite/cstest/src/test_detail_loongarch.c new file mode 100644 index 0000000000..3a86bbcf63 --- /dev/null +++ b/suite/cstest/src/test_detail_loongarch.c @@ -0,0 +1,114 @@ +// Copyright © 2024 Rot127 +// SPDX-License-Identifier: BSD-3 + +#include "test_compare.h" +#include "test_detail_loongarch.h" +#include +#include +#include + +TestDetailLoongArch *test_detail_loongarch_new() +{ + return cs_mem_calloc(sizeof(TestDetailLoongArch), 1); +} + +void test_detail_loongarch_free(TestDetailLoongArch *detail) +{ + if (!detail) { + return; + } + for (size_t i = 0; i < detail->operands_count; ++i) { + test_detail_loongarch_op_free(detail->operands[i]); + } + cs_mem_free(detail->operands); + cs_mem_free(detail->format); + cs_mem_free(detail); +} + +TestDetailLoongArch * +test_detail_loongarch_clone(const TestDetailLoongArch *detail) +{ + TestDetailLoongArch *clone = test_detail_loongarch_new(); + + clone->format = detail->format ? strdup(detail->format) : NULL; + clone->operands_count = detail->operands_count; + if (detail->operands_count > 0) { + clone->operands = cs_mem_calloc(sizeof(TestDetailLoongArchOp *), + detail->operands_count); + } + for (size_t i = 0; i < detail->operands_count; ++i) { + clone->operands[i] = + test_detail_loongarch_op_clone(detail->operands[i]); + } + + return clone; +} + +TestDetailLoongArchOp *test_detail_loongarch_op_new() +{ + return cs_mem_calloc(sizeof(TestDetailLoongArchOp), 1); +} + +TestDetailLoongArchOp * +test_detail_loongarch_op_clone(const TestDetailLoongArchOp *op) +{ + TestDetailLoongArchOp *clone = test_detail_loongarch_op_new(); + + clone->type = op->type ? strdup(op->type) : NULL; + clone->access = op->access ? strdup(op->access) : NULL; + clone->reg = op->reg ? strdup(op->reg) : NULL; + clone->imm = op->imm; + clone->mem_base = op->mem_base ? strdup(op->mem_base) : NULL; + clone->mem_disp = op->mem_disp; + + return clone; +} + +void test_detail_loongarch_op_free(TestDetailLoongArchOp *op) +{ + if (!op) { + return; + } + cs_mem_free(op->type); + cs_mem_free(op->access); + cs_mem_free(op->reg); + cs_mem_free(op->mem_base); + cs_mem_free(op); +} + +bool test_expected_loongarch(csh *handle, const cs_loongarch *actual, + const TestDetailLoongArch *expected) +{ + assert(handle && actual && expected); + + compare_uint8_ret(actual->op_count, expected->operands_count, false); + compare_enum_ret(actual->format, expected->format, false); + for (size_t i = 0; i < actual->op_count; ++i) { + const cs_loongarch_op *op = &actual->operands[i]; + TestDetailLoongArchOp *eop = expected->operands[i]; + compare_enum_ret(op->type, eop->type, false); + compare_enum_ret(op->access, eop->access, false); + switch (op->type) { + default: + fprintf(stderr, + "loongarch op type %" PRId32 " not handled.\n", + op->type); + return false; + case LOONGARCH_OP_REG: + compare_reg_ret(*handle, op->reg, eop->reg, false); + break; + case LOONGARCH_OP_IMM: + compare_uint64_ret(op->imm, eop->imm, false); + break; + case LOONGARCH_OP_MEM: + compare_reg_ret(*handle, op->mem.base, eop->mem_base, + false); + compare_reg_ret(*handle, op->mem.index, eop->mem_index, + false); + compare_int64_ret(op->mem.disp, eop->mem_disp, false); + break; + } + } + + return true; +} diff --git a/tests/details/loongarch.yaml b/tests/details/loongarch.yaml new file mode 100644 index 0000000000..0fd5a79e26 --- /dev/null +++ b/tests/details/loongarch.yaml @@ -0,0 +1,107 @@ +test_cases: + - + input: + bytes: [ 0x0c, 0x00, 0x08, 0x14, 0x8c, 0xfd, 0xbf, 0x02 ] + arch: "loongarch" + options: [ CS_OPT_DETAIL, CS_MODE_LOONGARCH32 ] + address: 0x0 + expected: + insns: + - + asm_text: "lu12i.w $t0, 0x4000" + details: + loongarch: + operands: + - + type: LOONGARCH_OP_REG + reg: t0 + - + type: LOONGARCH_OP_IMM + imm: 0x4000 + - + asm_text: "addi.w $t0, $t0, -1" + details: + loongarch: + operands: + - + type: LOONGARCH_OP_REG + reg: t0 + - + type: LOONGARCH_OP_REG + reg: t0 + - + type: LOONGARCH_OP_IMM + imm: -1 + - + input: + bytes: [ 0x80, 0x80, 0x00, 0x40, 0x63, 0x80, 0xff, 0x02, 0x78, 0x20, 0xc0, 0x29, 0x00, 0x84, 0x00, 0x01, 0x00, 0xa4, 0x14, 0x01 ] + arch: "loongarch" + options: [ CS_OPT_DETAIL, CS_MODE_LOONGARCH64] + address: 0x0 + expected: + insns: + - + asm_text: "beqz $a0, 0x80" + details: + loongarch: + operands: + - + type: LOONGARCH_OP_REG + reg: a0 + - + type: LOONGARCH_OP_IMM + imm: 0x80 + groups: [ LOONGARCH_GRP_JUMP, LOONGARCH_GRP_BRANCH_RELATIVE ] + - + asm_text: "addi.d $sp, $sp, -0x20" + details: + loongarch: + operands: + - + type: LOONGARCH_OP_REG + reg: sp + - + type: LOONGARCH_OP_REG + reg: sp + - + type: LOONGARCH_OP_IMM + imm: -0x20 + groups: [ LOONGARCH_FEATURE_ISLA64 ] + - + asm_text: "st.d $s1, $sp, 8" + details: + loongarch: + operands: + - + type: LOONGARCH_OP_REG + reg: s1 + - + type: LOONGARCH_OP_MEM + mem_base: sp + mem_disp: 0x8 + groups: [ LOONGARCH_FEATURE_ISLA64 ] + - + asm_text: "fadd.s $fa0, $fa0, $fa1" + details: + loongarch: + operands: + - + type: LOONGARCH_OP_REG + reg: fa0 + - + type: LOONGARCH_OP_REG + reg: fa0 + - + type: LOONGARCH_OP_REG + reg: fa1 + - + asm_text: "movgr2fr.w $fa0, $zero" + details: + loongarch: + operands: + - + type: LOONGARCH_OP_REG + reg: fa0 + - + type: LOONGARCH_OP_REG + reg: zero