From 4965eb9fed617cf7746d4689fc93f41bf3c6aa4e Mon Sep 17 00:00:00 2001 From: Michael Kohn <mike@mikekohn.net> Date: Sun, 28 Jan 2024 10:49:23 -0600 Subject: [PATCH] arm64: Some fixes for simd move. --- asm/arm64.cpp | 76 +++++++++++++++++++++++++++++++++++++++--------- common/version.h | 2 +- disasm/arm64.cpp | 13 +++++---- table/arm64.cpp | 7 +++-- table/arm64.h | 2 +- 5 files changed, 76 insertions(+), 24 deletions(-) diff --git a/asm/arm64.cpp b/asm/arm64.cpp index 67190928..5f9e0391 100644 --- a/asm/arm64.cpp +++ b/asm/arm64.cpp @@ -1128,7 +1128,7 @@ static bool reg_matches(int operand, int wanted) { switch (wanted) { - case ARM64_REG_V: return operand == OPERAND_REG_VECTOR; + case ARM64_REG_V_DOT: return operand == OPERAND_REG_VECTOR; case ARM64_REG_V_SCALAR: return operand == OPERAND_REG_SCALAR; case ARM64_REG_V_ELEMENT: return operand == OPERAND_REG_VECTOR_ELEMENT; case ARM64_REG_B: @@ -1138,18 +1138,68 @@ static bool reg_matches(int operand, int wanted) } } -static bool match_vector_size(int attribute, int type) +static int get_register_size(_operand *operand) { - if (attribute == SIZE_D) + switch (operand->type) { - return type == OPERAND_REG_64; - } - else - { - return type == OPERAND_REG_32; + case OPERAND_REG_32: return 32; + case OPERAND_REG_64: return 64; + case OPERAND_REG_VECTOR: + switch (operand->attribute) + { + case SIZE_8B: return 8; + case SIZE_16B: return 8; + case SIZE_4H: return 16; + case SIZE_8H: return 16; + case SIZE_2S: return 32; + case SIZE_4S: return 32; + case SIZE_1D: return 64; + case SIZE_2D: return 64; + case SIZE_B: return 8; + case SIZE_H: return 16; + case SIZE_S: return 32; + case SIZE_D: return 64; + default: return -4; + } + case OPERAND_REG_VECTOR_ELEMENT: + switch (operand->attribute) + { + case SIZE_8B: return 8; + case SIZE_16B: return 8; + case SIZE_4H: return 16; + case SIZE_8H: return 16; + case SIZE_2S: return 32; + case SIZE_4S: return 32; + case SIZE_1D: return 64; + case SIZE_2D: return 64; + case SIZE_B: return 8; + case SIZE_H: return 16; + case SIZE_S: return 32; + case SIZE_D: return 64; + default: return -4; + } + case OPERAND_REG_SCALAR: + switch (operand->attribute) + { + case 0: return 8; + case 1: return 16; + case 2: return 32; + case 3: return 64; + default: return -3; + } + default: + return -1; } } +static bool match_vector_size(_operand *operands) +{ + int size_d = get_register_size(&operands[0]); + int size_n = get_register_size(&operands[1]); + + return size_d == size_n; +} + static bool encode_vector_element(_operand *operand, int &imm) { switch (operand->attribute) @@ -1434,9 +1484,9 @@ int parse_instruction_arm64(AsmContext *asm_context, char *instr) else if (operands[0].type == OPERAND_REG_VECTOR_ELEMENT) { - if (!match_vector_size(operands[0].attribute, operands[1].type)) + if (!match_vector_size(operands)) { - print_error(asm_context, "Mismatched register sizes."); + print_error(asm_context, "Mismatched register sizes"); return -1; } @@ -1445,9 +1495,9 @@ int parse_instruction_arm64(AsmContext *asm_context, char *instr) else if (operands[1].type == OPERAND_REG_VECTOR_ELEMENT) { - if (!match_vector_size(operands[1].attribute, operands[0].type)) + if (!match_vector_size(operands)) { - print_error(asm_context, "Mismatched register sizes."); + print_error(asm_context, "Mismatched register sizes"); return -1; } @@ -1456,7 +1506,7 @@ int parse_instruction_arm64(AsmContext *asm_context, char *instr) opcode = 0x0e000400 | (table_arm64_simd_copy[n].q << 31) | - (table_arm64_simd_copy[n].op << 29) | + (table_arm64_simd_copy[n].op << 28) | (imm5 << 16) | (imm4 << 11) | (operands[1].value << 5) | diff --git a/common/version.h b/common/version.h index 2006f072..c1e4fad9 100644 --- a/common/version.h +++ b/common/version.h @@ -1,7 +1,7 @@ #ifndef NAKEN_ASM_VERSION_H #define NAKEN_ASM_VERSION_H -#define VERSION "January 11, 2024" +#define VERSION "January 28, 2024" #endif diff --git a/disasm/arm64.cpp b/disasm/arm64.cpp index 5609974a..60db1eaf 100644 --- a/disasm/arm64.cpp +++ b/disasm/arm64.cpp @@ -44,7 +44,7 @@ static const char *get_at(int value) return "???"; } -static const char *decode_imm5_scalar(int imm, int q) +static const char *decode_imm5_vector(int imm, int q) { int size = 0; @@ -79,11 +79,12 @@ static void get_reg_name(char *s, int length, int num, int imm, int type, int q) case ARM64_REG_B: snprintf(s, length, "%c%d", (imm & 8) == 0 ? 'w' : 'x', num); break; - case ARM64_REG_V: - snprintf(s, length, "v%d", num); + case ARM64_REG_V_DOT: + snprintf(s, length, "v%d.%s", num, decode_imm5_vector(imm, q)); break; case ARM64_REG_V_SCALAR: - snprintf(s, length, "v%d.%s", num, decode_imm5_scalar(imm, q)); + decode_imm5_element(imm, size, element); + snprintf(s, length, "%c%d", size, num); break; case ARM64_REG_V_ELEMENT: decode_imm5_element(imm, size, element); @@ -121,12 +122,12 @@ int disasm_arm64( sf = (opcode >> 31) & 0x1; v = (opcode >> 26) & 0x1; - if ((opcode & 0x9fe08400) == 0x0e000400) + if ((opcode & 0x8fe08400) == 0x0e000400) { for (n = 0; table_arm64_simd_copy[n].instr != NULL; n++) { int q = opcode >> 31; - int op = (opcode >> 29) & 1; + int op = (opcode >> 28) & 3; int imm5 = (opcode >> 16) & 0x1f; int imm4 = (opcode >> 11) & 0xf; diff --git a/table/arm64.cpp b/table/arm64.cpp index ae501e1f..ca1ba50f 100644 --- a/table/arm64.cpp +++ b/table/arm64.cpp @@ -338,12 +338,13 @@ struct _table_arm64_uncond_branch table_arm64_uncond_branch[] = // C3.6.5 AdvSIMD copy. struct _table_arm64_simd_copy table_arm64_simd_copy[] = { - { "dup", 0, 0, 0x0, ARM64_REG_V, ARM64_REG_V_ELEMENT }, - { "dup", 0, 0, 0x1, ARM64_REG_V_SCALAR, ARM64_REG_V_ELEMENT }, + { "dup", 0, 0, 0x0, ARM64_REG_V_DOT, ARM64_REG_V_ELEMENT }, + { "dup", 0, 1, 0x0, ARM64_REG_V_SCALAR, ARM64_REG_V_ELEMENT }, + { "dup", 0, 0, 0x1, ARM64_REG_V_DOT, ARM64_REG_B }, { "smov", 0, 0, 0x5, ARM64_REG_B, ARM64_REG_V_ELEMENT }, { "umov", 0, 0, 0x7, ARM64_REG_B, ARM64_REG_V_ELEMENT }, { "ins", 1, 0, 0x3, ARM64_REG_V_ELEMENT, ARM64_REG_V_ELEMENT }, - { "ins", 1, 1, 0x0, ARM64_REG_V_ELEMENT, ARM64_REG_B }, + { "ins", 1, 2, 0x0, ARM64_REG_V_ELEMENT, ARM64_REG_B }, { NULL, 0, 0, 0x0, 0, 0 }, }; diff --git a/table/arm64.h b/table/arm64.h index a4a05c95..0ca145cd 100644 --- a/table/arm64.h +++ b/table/arm64.h @@ -48,8 +48,8 @@ enum enum { ARM64_REG_B, - ARM64_REG_V, ARM64_REG_V_SCALAR, + ARM64_REG_V_DOT, ARM64_REG_V_ELEMENT, };