diff --git a/disas/meson.build b/disas/meson.build index 815523ab85e0..96eb6f73f61f 100644 --- a/disas/meson.build +++ b/disas/meson.build @@ -9,7 +9,8 @@ common_ss.add(when: 'CONFIG_NIOS2_DIS', if_true: files('nios2.c')) common_ss.add(when: 'CONFIG_RISCV_DIS', if_true: files( 'riscv.c', 'riscv-xthead.c', - 'riscv-xventana.c' + 'riscv-xventana.c', + 'riscv-zbr.c' )) common_ss.add(when: 'CONFIG_SH4_DIS', if_true: files('sh4.c')) common_ss.add(when: 'CONFIG_SPARC_DIS', if_true: files('sparc.c')) diff --git a/disas/riscv-zbr.c b/disas/riscv-zbr.c new file mode 100644 index 000000000000..79b0db34dd48 --- /dev/null +++ b/disas/riscv-zbr.c @@ -0,0 +1,76 @@ +/* + * QEMU RISC-V Disassembler for Zbr + * + * Copyright (c) 2023 Rivos Inc + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "disas/riscv.h" +#include "disas/riscv-zbr.h" + +typedef enum { + /* 0 is reserved for rv_op_illegal. */ + rv_op_crc32_b = 1, + rv_op_crc32_h = 2, + rv_op_crc32_w = 3, + rv_op_crc32_d = 4, + rv_op_crc32c_b = 5, + rv_op_crc32c_h = 6, + rv_op_crc32c_w = 7, + rv_op_crc32c_d = 8, +} rv_zbr_op; + +const rv_opcode_data rv_zbr_opcode_data[] = { + { "illegal", rv_codec_illegal, rv_fmt_none, NULL, 0, 0, 0 }, + { "crc32.b", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, + { "crc32.h", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, + { "crc32.w", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, + { "crc32.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, + { "crc32c.b", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, + { "crc32c.h", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, + { "crc32c.w", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, + { "crc32c.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, +}; + +void decode_zbr(rv_decode *dec, rv_isa isa) +{ + rv_inst inst = dec->inst; + rv_opcode op = rv_op_illegal; + + switch ((inst >> 0) & 0b1111111) { + case 0b0010011: + switch ((inst >> 12) & 0b111) { + case 0b001: + switch ((inst >> 20 & 0b111111111111)) { + case 0b011000010000: + op = rv_op_crc32_b; + break; + case 0b011000010001: + op = rv_op_crc32_h; + break; + case 0b011000010010: + op = rv_op_crc32_w; + break; + case 0b011000010011: + op = rv_op_crc32_d; + break; + case 0b011000011000: + op = rv_op_crc32c_b; + break; + case 0b011000011001: + op = rv_op_crc32c_h; + break; + case 0b011000011010: + op = rv_op_crc32c_w; + break; + case 0b011000011011: + op = rv_op_crc32c_d; + break; + } + break; + } + break; + } + dec->op = op; +} diff --git a/disas/riscv-zbr.h b/disas/riscv-zbr.h new file mode 100644 index 000000000000..366040ed53c2 --- /dev/null +++ b/disas/riscv-zbr.h @@ -0,0 +1,18 @@ +/* + * QEMU RISC-V Disassembler for Zbr + * + * Copyright (c) 2023 Rivos Inc + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef DISAS_RISCV_ZBR_H +#define DISAS_RISCV_ZBR_H + +#include "disas/riscv.h" + +extern const rv_opcode_data rv_zbr_opcode_data[]; + +void decode_zbr(rv_decode *, rv_isa); + +#endif /* DISAS_RISCV_ZBR_H */ diff --git a/disas/riscv.c b/disas/riscv.c index 769d1f1cc722..8ac3ed966d51 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -27,6 +27,9 @@ #include "disas/riscv-xthead.h" #include "disas/riscv-xventana.h" +/* Extensions that are not yet upstream */ +#include "disas/riscv-zbr.h" + typedef enum { /* 0 is reserved for rv_op_illegal. */ rv_op_lui = 1, @@ -862,14 +865,6 @@ typedef enum { rv_op_fltq_q = 831, rv_op_fleq_h = 832, rv_op_fltq_h = 833, - rv_op_crc32_b = 834, - rv_op_crc32_h = 835, - rv_op_crc32_w = 836, - rv_op_crc32_d = 837, - rv_op_crc32c_b = 838, - rv_op_crc32c_h = 839, - rv_op_crc32c_w = 840, - rv_op_crc32c_d = 841, } rv_op; /* register names */ @@ -2016,14 +2011,6 @@ const rv_opcode_data rvi_opcode_data[] = { { "fltq.q", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, { "fleq.h", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, { "fltq.h", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, - { "crc32.b", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "crc32.h", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "crc32.w", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "crc32.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "crc32c.b", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "crc32c.h", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "crc32c.w", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, - { "crc32c.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 } }; /* CSR names */ @@ -2620,12 +2607,6 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) /* 0b0000011 */ case 0b0000100: op = rv_op_sext_b; break; case 0b0000101: op = rv_op_sext_h; break; - case 0b0010000: op = rv_op_crc32_b; break; - case 0b0010001: op = rv_op_crc32_h; break; - case 0b0010010: op = rv_op_crc32_w; break; - case 0b0011000: op = rv_op_crc32c_b; break; - case 0b0011001: op = rv_op_crc32c_h; break; - case 0b0011010: op = rv_op_crc32c_w; break; } break; } @@ -5004,6 +4985,9 @@ disasm_inst(char *buf, size_t buflen, rv_isa isa, uint64_t pc, rv_inst inst, { has_xtheadmempair_p, xthead_opcode_data, decode_xtheadmempair }, { has_xtheadsync_p, xthead_opcode_data, decode_xtheadsync }, { has_XVentanaCondOps_p, ventana_opcode_data, decode_xventanacondops }, + + /* Instructions that are not yet upstream */ + { has_zbr_p, rv_zbr_opcode_data, decode_zbr }, }; for (size_t i = 0; i < ARRAY_SIZE(decoders); i++) { diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 077f90ff6da8..f6e984af1bc4 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -183,4 +183,7 @@ MATERIALISE_EXT_PREDICATE(xtheadmempair) MATERIALISE_EXT_PREDICATE(xtheadsync) MATERIALISE_EXT_PREDICATE(XVentanaCondOps) +/* Extensions that are not yet upstream */ +MATERIALISE_EXT_PREDICATE(zbr); + #endif