Upstream: https://gitlab.com/qemu-project/qemu.git Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
466 lines
13 KiB
C
466 lines
13 KiB
C
/*
|
|
* QEMU RISC-V Disassembler for xthead.
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "disas/riscv.h"
|
|
#include "disas/riscv-xthead.h"
|
|
|
|
#define OP(N, ...) static const rv_opcode_data op_##N = { __VA_ARGS__ };
|
|
#include "riscv-xthead-op.c.inc"
|
|
#undef OP
|
|
|
|
const rv_opcode_data *decode_xtheadba(rv_decode *dec, rv_isa isa)
|
|
{
|
|
rv_inst inst = dec->inst;
|
|
|
|
switch (((inst >> 0) & 0b11)) {
|
|
case 3:
|
|
switch (((inst >> 2) & 0b11111)) {
|
|
case 2:
|
|
/* custom-0 */
|
|
switch ((inst >> 12) & 0b111) {
|
|
case 1:
|
|
switch ((inst >> 25) & 0b1111111) {
|
|
case 0b0000000:
|
|
case 0b0000001:
|
|
case 0b0000010:
|
|
case 0b0000011: return &op_th_addsl;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
/* custom-0 */
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const rv_opcode_data *decode_xtheadbb(rv_decode *dec, rv_isa isa)
|
|
{
|
|
rv_inst inst = dec->inst;
|
|
|
|
switch (((inst >> 0) & 0b11)) {
|
|
case 3:
|
|
switch (((inst >> 2) & 0b11111)) {
|
|
case 2:
|
|
/* custom-0 */
|
|
switch ((inst >> 12) & 0b111) {
|
|
case 1:
|
|
switch ((inst >> 25) & 0b1111111) {
|
|
case 0b0001010: return &op_th_srriw;
|
|
case 0b1000000:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_tstnbz;
|
|
}
|
|
break;
|
|
case 0b1000001:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_rev;
|
|
}
|
|
break;
|
|
case 0b1000010:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_ff0;
|
|
}
|
|
break;
|
|
case 0b1000011:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_ff1;
|
|
}
|
|
break;
|
|
case 0b1000100:
|
|
case 0b1001000:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_revw;
|
|
}
|
|
break;
|
|
case 0b0001000:
|
|
case 0b0001001:
|
|
return &op_th_srri;
|
|
break;
|
|
}
|
|
break;
|
|
case 2: return &op_th_ext;
|
|
case 3: return &op_th_extu;
|
|
}
|
|
break;
|
|
/* custom-0 */
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const rv_opcode_data *decode_xtheadbs(rv_decode *dec, rv_isa isa)
|
|
{
|
|
rv_inst inst = dec->inst;
|
|
|
|
switch (((inst >> 0) & 0b11)) {
|
|
case 3:
|
|
switch (((inst >> 2) & 0b11111)) {
|
|
case 2:
|
|
/* custom-0 */
|
|
switch ((inst >> 12) & 0b111) {
|
|
case 1:
|
|
switch ((inst >> 26) & 0b111111) {
|
|
case 0b100010: return &op_th_tst;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
/* custom-0 */
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const rv_opcode_data *decode_xtheadcmo(rv_decode *dec, rv_isa isa)
|
|
{
|
|
rv_inst inst = dec->inst;
|
|
|
|
switch (((inst >> 0) & 0b11)) {
|
|
case 3:
|
|
switch (((inst >> 2) & 0b11111)) {
|
|
case 2:
|
|
/* custom-0 */
|
|
switch ((inst >> 12) & 0b111) {
|
|
case 0:
|
|
switch ((inst >> 20 & 0b111111111111)) {
|
|
case 0b000000000001:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_dcache_call;
|
|
}
|
|
break;
|
|
case 0b000000000011:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_dcache_ciall;
|
|
}
|
|
break;
|
|
case 0b000000000010:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_dcache_iall;
|
|
}
|
|
break;
|
|
case 0b000000101001: return &op_th_dcache_cpa;
|
|
case 0b000000101011: return &op_th_dcache_cipa;
|
|
case 0b000000101010: return &op_th_dcache_ipa;
|
|
case 0b000000100101: return &op_th_dcache_cva;
|
|
case 0b000000100111: return &op_th_dcache_civa;
|
|
case 0b000000100110: return &op_th_dcache_iva;
|
|
case 0b000000100001: return &op_th_dcache_csw;
|
|
case 0b000000100011: return &op_th_dcache_cisw;
|
|
case 0b000000100010: return &op_th_dcache_isw;
|
|
case 0b000000101000: return &op_th_dcache_cpal1;
|
|
case 0b000000100100: return &op_th_dcache_cval1;
|
|
case 0b000000010000:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_icache_iall;
|
|
}
|
|
break;
|
|
case 0b000000010001:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_icache_ialls;
|
|
}
|
|
break;
|
|
case 0b000000111000: return &op_th_icache_ipa;
|
|
case 0b000000110000: return &op_th_icache_iva;
|
|
case 0b000000010101:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_l2cache_call;
|
|
}
|
|
break;
|
|
case 0b000000010111:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_l2cache_ciall;
|
|
}
|
|
break;
|
|
case 0b000000010110:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_l2cache_iall;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
/* custom-0 */
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const rv_opcode_data *decode_xtheadcondmov(rv_decode *dec, rv_isa isa)
|
|
{
|
|
rv_inst inst = dec->inst;
|
|
|
|
switch (((inst >> 0) & 0b11)) {
|
|
case 3:
|
|
switch (((inst >> 2) & 0b11111)) {
|
|
case 2:
|
|
/* custom-0 */
|
|
switch ((inst >> 12) & 0b111) {
|
|
case 1:
|
|
switch ((inst >> 25) & 0b1111111) {
|
|
case 0b0100000: return &op_th_mveqz;
|
|
case 0b0100001: return &op_th_mvnez;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
/* custom-0 */
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const rv_opcode_data *decode_xtheadfmemidx(rv_decode *dec, rv_isa isa)
|
|
{
|
|
rv_inst inst = dec->inst;
|
|
|
|
switch (((inst >> 0) & 0b11)) {
|
|
case 3:
|
|
switch (((inst >> 2) & 0b11111)) {
|
|
case 2:
|
|
/* custom-0 */
|
|
switch ((inst >> 12) & 0b111) {
|
|
case 6:
|
|
switch ((inst >> 27) & 0b11111) {
|
|
case 8: return &op_th_flrw;
|
|
case 10: return &op_th_flurw;
|
|
case 12: return &op_th_flrd;
|
|
case 14: return &op_th_flurd;
|
|
}
|
|
break;
|
|
case 7:
|
|
switch ((inst >> 27) & 0b11111) {
|
|
case 8: return &op_th_fsrw;
|
|
case 10: return &op_th_fsurw;
|
|
case 12: return &op_th_fsrd;
|
|
case 14: return &op_th_fsurd;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
/* custom-0 */
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const rv_opcode_data *decode_xtheadfmv(rv_decode *dec, rv_isa isa)
|
|
{
|
|
rv_inst inst = dec->inst;
|
|
|
|
switch (((inst >> 0) & 0b11)) {
|
|
case 3:
|
|
switch (((inst >> 2) & 0b11111)) {
|
|
case 2:
|
|
/* custom-0 */
|
|
switch ((inst >> 12) & 0b111) {
|
|
case 1:
|
|
switch ((inst >> 25) & 0b1111111) {
|
|
case 0b1010000:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_fmv_hw_x;
|
|
}
|
|
break;
|
|
case 0b1100000:
|
|
if (((inst >> 20) & 0b11111) == 0) {
|
|
return &op_th_fmv_x_hw;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
/* custom-0 */
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const rv_opcode_data *decode_xtheadmac(rv_decode *dec, rv_isa isa)
|
|
{
|
|
rv_inst inst = dec->inst;
|
|
|
|
switch (((inst >> 0) & 0b11)) {
|
|
case 3:
|
|
switch (((inst >> 2) & 0b11111)) {
|
|
case 2:
|
|
/* custom-0 */
|
|
switch ((inst >> 12) & 0b111) {
|
|
case 1:
|
|
switch ((inst >> 25) & 0b1111111) {
|
|
case 0b0010000: return &op_th_mula;
|
|
case 0b0010001: return &op_th_muls;
|
|
case 0b0010010: return &op_th_mulaw;
|
|
case 0b0010011: return &op_th_mulsw;
|
|
case 0b0010100: return &op_th_mulah;
|
|
case 0b0010101: return &op_th_mulsh;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
/* custom-0 */
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const rv_opcode_data *decode_xtheadmemidx(rv_decode *dec, rv_isa isa)
|
|
{
|
|
rv_inst inst = dec->inst;
|
|
|
|
switch (((inst >> 0) & 0b11)) {
|
|
case 3:
|
|
switch (((inst >> 2) & 0b11111)) {
|
|
case 2:
|
|
/* custom-0 */
|
|
switch ((inst >> 12) & 0b111) {
|
|
case 4:
|
|
switch ((inst >> 27) & 0b11111) {
|
|
case 0: return &op_th_lrb;
|
|
case 1: return &op_th_lbib;
|
|
case 2: return &op_th_lurb;
|
|
case 3: return &op_th_lbia;
|
|
case 4: return &op_th_lrh;
|
|
case 5: return &op_th_lhib;
|
|
case 6: return &op_th_lurh;
|
|
case 7: return &op_th_lhia;
|
|
case 8: return &op_th_lrw;
|
|
case 9: return &op_th_lwib;
|
|
case 10: return &op_th_lurw;
|
|
case 11: return &op_th_lwia;
|
|
case 12: return &op_th_lrd;
|
|
case 13: return &op_th_ldib;
|
|
case 14: return &op_th_lurd;
|
|
case 15: return &op_th_ldia;
|
|
case 16: return &op_th_lrbu;
|
|
case 17: return &op_th_lbuib;
|
|
case 18: return &op_th_lurbu;
|
|
case 19: return &op_th_lbuia;
|
|
case 20: return &op_th_lrhu;
|
|
case 21: return &op_th_lhuib;
|
|
case 22: return &op_th_lurhu;
|
|
case 23: return &op_th_lhuia;
|
|
case 24: return &op_th_lrwu;
|
|
case 25: return &op_th_lwuib;
|
|
case 26: return &op_th_lurwu;
|
|
case 27: return &op_th_lwuia;
|
|
}
|
|
break;
|
|
case 5:
|
|
switch ((inst >> 27) & 0b11111) {
|
|
case 0: return &op_th_srb;
|
|
case 1: return &op_th_sbib;
|
|
case 2: return &op_th_surb;
|
|
case 3: return &op_th_sbia;
|
|
case 4: return &op_th_srh;
|
|
case 5: return &op_th_shib;
|
|
case 6: return &op_th_surh;
|
|
case 7: return &op_th_shia;
|
|
case 8: return &op_th_srw;
|
|
case 9: return &op_th_swib;
|
|
case 10: return &op_th_surw;
|
|
case 11: return &op_th_swia;
|
|
case 12: return &op_th_srd;
|
|
case 13: return &op_th_sdib;
|
|
case 14: return &op_th_surd;
|
|
case 15: return &op_th_sdia;
|
|
}
|
|
break;
|
|
break;
|
|
}
|
|
break;
|
|
/* custom-0 */
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const rv_opcode_data *decode_xtheadmempair(rv_decode *dec, rv_isa isa)
|
|
{
|
|
rv_inst inst = dec->inst;
|
|
|
|
switch (((inst >> 0) & 0b11)) {
|
|
case 3:
|
|
switch (((inst >> 2) & 0b11111)) {
|
|
case 2:
|
|
/* custom-0 */
|
|
switch ((inst >> 12) & 0b111) {
|
|
case 4:
|
|
switch ((inst >> 27) & 0b11111) {
|
|
case 28: return &op_th_lwd;
|
|
case 30: return &op_th_lwud;
|
|
case 31: return &op_th_ldd;
|
|
}
|
|
break;
|
|
case 5:
|
|
switch ((inst >> 27) & 0b11111) {
|
|
case 28: return &op_th_swd;
|
|
case 31: return &op_th_sdd;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
/* custom-0 */
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const rv_opcode_data *decode_xtheadsync(rv_decode *dec, rv_isa isa)
|
|
{
|
|
rv_inst inst = dec->inst;
|
|
|
|
switch (((inst >> 0) & 0b11)) {
|
|
case 3:
|
|
switch (((inst >> 2) & 0b11111)) {
|
|
case 2:
|
|
/* custom-0 */
|
|
switch ((inst >> 12) & 0b111) {
|
|
case 0:
|
|
switch ((inst >> 25) & 0b1111111) {
|
|
case 0b0000010: return &op_th_sfence_vmas;
|
|
case 0b0000000:
|
|
switch ((inst >> 20) & 0b11111) {
|
|
case 0b11000: return &op_th_sync;
|
|
case 0b11010: return &op_th_sync_i;
|
|
case 0b11011: return &op_th_sync_is;
|
|
case 0b11001: return &op_th_sync_s;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
/* custom-0 */
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|