util/hexdump: Use a GString for qemu_hexdump_line.
system/qtest: Replace sprintf by qemu_hexdump_line hw/scsi/scsi-disk: Use qemu_hexdump_line to avoid sprintf hw/ide/atapi: Use qemu_hexdump_line to avoid sprintf hw/dma/pl330: Use qemu_hexdump_line to avoid sprintf disas/microblaze: Reorg to avoid intermediate sprintf disas/riscv: Use GString in format_inst -----BEGIN PGP SIGNATURE----- iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmZg1RMdHHJpY2hhcmQu aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV+6mgf6AjEdU91vBXAUxabs kmVl5HaAD3NHU1VCM+ruPQkm6xv4kLlMsTibmkiS7+WZYvHfPlGfozjRJxtvZj8K 8J2Qp9iHjny8NQPkMCValDvmzkxaIT7ZzYCBdS4jfTdIThuYNJnXsI3NNP7ghnl6 xv8O62dQbc5gjWF8G+q6PKWSxY6BEuFJ3Pt82cJ/Fj/8bhsjd48pgiLv66F/+q1z U9Gy8fWqmkKEzTqBigSYU98yae5CA89T6JBKtgFV07pkYa4A7BUyCR5EBirARyhM P0OAqR1GCAbSXWFaJ1sSpU8ATq33FoSQYwWwcmEET7FZYZqvbd6Jd4HtpOPqmu9W Fc4taw== =VgLB -----END PGP SIGNATURE----- Merge tag 'pull-misc-20240605' of https://gitlab.com/rth7680/qemu into staging util/hexdump: Use a GString for qemu_hexdump_line. system/qtest: Replace sprintf by qemu_hexdump_line hw/scsi/scsi-disk: Use qemu_hexdump_line to avoid sprintf hw/ide/atapi: Use qemu_hexdump_line to avoid sprintf hw/dma/pl330: Use qemu_hexdump_line to avoid sprintf disas/microblaze: Reorg to avoid intermediate sprintf disas/riscv: Use GString in format_inst # -----BEGIN PGP SIGNATURE----- # # iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmZg1RMdHHJpY2hhcmQu # aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV+6mgf6AjEdU91vBXAUxabs # kmVl5HaAD3NHU1VCM+ruPQkm6xv4kLlMsTibmkiS7+WZYvHfPlGfozjRJxtvZj8K # 8J2Qp9iHjny8NQPkMCValDvmzkxaIT7ZzYCBdS4jfTdIThuYNJnXsI3NNP7ghnl6 # xv8O62dQbc5gjWF8G+q6PKWSxY6BEuFJ3Pt82cJ/Fj/8bhsjd48pgiLv66F/+q1z # U9Gy8fWqmkKEzTqBigSYU98yae5CA89T6JBKtgFV07pkYa4A7BUyCR5EBirARyhM # P0OAqR1GCAbSXWFaJ1sSpU8ATq33FoSQYwWwcmEET7FZYZqvbd6Jd4HtpOPqmu9W # Fc4taw== # =VgLB # -----END PGP SIGNATURE----- # gpg: Signature made Wed 05 Jun 2024 02:13:55 PM PDT # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [ultimate] * tag 'pull-misc-20240605' of https://gitlab.com/rth7680/qemu: disas/riscv: Use GString in format_inst disas/microblaze: Split get_field_special disas/microblaze: Print registers directly with PRIrfsl disas/microblaze: Print immediates directly with PRIimm disas/microblaze: Print registers directly with PRIreg disas/microblaze: Merge op->name output into each fprintf disas/microblaze: Re-indent print_insn_microblaze disas/microblaze: Split out print_immval_addr hw/dma/pl330: Use qemu_hexdump_line to avoid sprintf hw/ide/atapi: Use qemu_hexdump_line to avoid sprintf hw/scsi/scsi-disk: Use qemu_hexdump_line to avoid sprintf system/qtest: Replace sprintf by qemu_hexdump_line hw/mips/malta: Add re-usable rng_seed_hex_new() method util/hexdump: Inline g_string_append_printf "%02x" util/hexdump: Add unit_len and block_len to qemu_hexdump_line util/hexdump: Use a GString for qemu_hexdump_line Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
db2feb2df8
@ -563,10 +563,7 @@ static const struct op_code_struct {
|
||||
};
|
||||
|
||||
/* prefix for register names */
|
||||
static const char register_prefix[] = "r";
|
||||
static const char fsl_register_prefix[] = "rfsl";
|
||||
static const char pvr_register_prefix[] = "rpvr";
|
||||
|
||||
#define register_prefix "r"
|
||||
|
||||
/* #defines for valid immediate range */
|
||||
#define MIN_IMM ((int) 0x80000000)
|
||||
@ -579,156 +576,64 @@ static const char pvr_register_prefix[] = "rpvr";
|
||||
|
||||
#include "disas/dis-asm.h"
|
||||
|
||||
#define get_field_rd(instr) get_field(instr, RD_MASK, RD_LOW)
|
||||
#define get_field_r1(instr) get_field(instr, RA_MASK, RA_LOW)
|
||||
#define get_field_r2(instr) get_field(instr, RB_MASK, RB_LOW)
|
||||
#define PRIreg register_prefix "%ld"
|
||||
#define PRIrfsl register_prefix "fsl%ld"
|
||||
#define PRIpvr register_prefix "pvr%d"
|
||||
#define PRIimm "%d"
|
||||
|
||||
#define get_field_rd(instr) ((instr & RD_MASK) >> RD_LOW)
|
||||
#define get_field_r1(instr) ((instr & RA_MASK) >> RA_LOW)
|
||||
#define get_field_r2(instr) ((instr & RB_MASK) >> RB_LOW)
|
||||
#define get_field_rfsl(instr) (instr & RFSL_MASK)
|
||||
#define get_field_imm(instr) ((int16_t)instr)
|
||||
#define get_field_imm5(instr) ((int)instr & IMM5_MASK)
|
||||
#define get_field_imm15(instr) ((int)instr & IMM15_MASK)
|
||||
|
||||
#define get_int_field_imm(instr) ((instr & IMM_MASK) >> IMM_LOW)
|
||||
#define get_int_field_r1(instr) ((instr & RA_MASK) >> RA_LOW)
|
||||
|
||||
/* Local function prototypes. */
|
||||
|
||||
static char * get_field (long instr, long mask, unsigned short low);
|
||||
static char * get_field_imm (long instr);
|
||||
static char * get_field_imm5 (long instr);
|
||||
static char * get_field_rfsl (long instr);
|
||||
static char * get_field_imm15 (long instr);
|
||||
#if 0
|
||||
static char * get_field_unsigned_imm (long instr);
|
||||
#endif
|
||||
|
||||
static char *
|
||||
get_field (long instr, long mask, unsigned short low)
|
||||
static int get_field_special(long instr, const struct op_code_struct *op)
|
||||
{
|
||||
char tmpstr[25];
|
||||
snprintf(tmpstr, sizeof(tmpstr), "%s%d", register_prefix,
|
||||
(int)((instr & mask) >> low));
|
||||
return(strdup(tmpstr));
|
||||
return ((instr & IMM_MASK) >> IMM_LOW) ^ op->immval_mask;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_field_imm (long instr)
|
||||
/* Returns NULL for PVR registers, which should be rendered differently. */
|
||||
static const char *get_special_name(int special)
|
||||
{
|
||||
char tmpstr[25];
|
||||
snprintf(tmpstr, sizeof(tmpstr), "%d",
|
||||
(short)((instr & IMM_MASK) >> IMM_LOW));
|
||||
return(strdup(tmpstr));
|
||||
}
|
||||
|
||||
static char *
|
||||
get_field_imm5 (long instr)
|
||||
{
|
||||
char tmpstr[25];
|
||||
snprintf(tmpstr, sizeof(tmpstr), "%d",
|
||||
(short)((instr & IMM5_MASK) >> IMM_LOW));
|
||||
return(strdup(tmpstr));
|
||||
}
|
||||
|
||||
static char *
|
||||
get_field_rfsl (long instr)
|
||||
{
|
||||
char tmpstr[25];
|
||||
snprintf(tmpstr, sizeof(tmpstr), "%s%d", fsl_register_prefix,
|
||||
(short)((instr & RFSL_MASK) >> IMM_LOW));
|
||||
return(strdup(tmpstr));
|
||||
}
|
||||
|
||||
static char *
|
||||
get_field_imm15 (long instr)
|
||||
{
|
||||
char tmpstr[25];
|
||||
snprintf(tmpstr, sizeof(tmpstr), "%d",
|
||||
(short)((instr & IMM15_MASK) >> IMM_LOW));
|
||||
return(strdup(tmpstr));
|
||||
}
|
||||
|
||||
#if 0
|
||||
static char *
|
||||
get_field_unsigned_imm (long instr)
|
||||
{
|
||||
char tmpstr[25];
|
||||
snprintf(tmpstr, sizeof(tmpstr), "%d",
|
||||
(int)((instr & IMM_MASK) >> IMM_LOW));
|
||||
return(strdup(tmpstr));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
char *
|
||||
get_field_special (instr)
|
||||
long instr;
|
||||
{
|
||||
char tmpstr[25];
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "%s%s", register_prefix,
|
||||
(((instr & IMM_MASK) >> IMM_LOW) & REG_MSR_MASK) == 0 ? "pc" : "msr");
|
||||
|
||||
return(strdup(tmpstr));
|
||||
}
|
||||
*/
|
||||
|
||||
static char *
|
||||
get_field_special(long instr, const struct op_code_struct *op)
|
||||
{
|
||||
char tmpstr[25];
|
||||
char spr[6];
|
||||
|
||||
switch ( (((instr & IMM_MASK) >> IMM_LOW) ^ op->immval_mask) ) {
|
||||
|
||||
case REG_MSR_MASK :
|
||||
strcpy(spr, "msr");
|
||||
break;
|
||||
case REG_PC_MASK :
|
||||
strcpy(spr, "pc");
|
||||
break;
|
||||
case REG_EAR_MASK :
|
||||
strcpy(spr, "ear");
|
||||
break;
|
||||
case REG_ESR_MASK :
|
||||
strcpy(spr, "esr");
|
||||
break;
|
||||
case REG_FSR_MASK :
|
||||
strcpy(spr, "fsr");
|
||||
break;
|
||||
case REG_BTR_MASK :
|
||||
strcpy(spr, "btr");
|
||||
break;
|
||||
case REG_EDR_MASK :
|
||||
strcpy(spr, "edr");
|
||||
break;
|
||||
case REG_PID_MASK :
|
||||
strcpy(spr, "pid");
|
||||
break;
|
||||
case REG_ZPR_MASK :
|
||||
strcpy(spr, "zpr");
|
||||
break;
|
||||
case REG_TLBX_MASK :
|
||||
strcpy(spr, "tlbx");
|
||||
break;
|
||||
case REG_TLBLO_MASK :
|
||||
strcpy(spr, "tlblo");
|
||||
break;
|
||||
case REG_TLBHI_MASK :
|
||||
strcpy(spr, "tlbhi");
|
||||
break;
|
||||
case REG_TLBSX_MASK :
|
||||
strcpy(spr, "tlbsx");
|
||||
break;
|
||||
default :
|
||||
{
|
||||
if ( ((((instr & IMM_MASK) >> IMM_LOW) ^ op->immval_mask) & 0xE000) == REG_PVR_MASK) {
|
||||
snprintf(tmpstr, sizeof(tmpstr), "%s%u", pvr_register_prefix,
|
||||
(unsigned short)(((instr & IMM_MASK) >> IMM_LOW) ^
|
||||
op->immval_mask) ^ REG_PVR_MASK);
|
||||
return(strdup(tmpstr));
|
||||
} else {
|
||||
strcpy(spr, "pc");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(tmpstr, sizeof(tmpstr), "%s%s", register_prefix, spr);
|
||||
return(strdup(tmpstr));
|
||||
switch (special) {
|
||||
case REG_MSR_MASK:
|
||||
return register_prefix "msr";
|
||||
case REG_PC_MASK:
|
||||
return register_prefix "pc";
|
||||
case REG_EAR_MASK:
|
||||
return register_prefix "ear";
|
||||
case REG_ESR_MASK:
|
||||
return register_prefix "esr";
|
||||
case REG_FSR_MASK:
|
||||
return register_prefix "fsr";
|
||||
case REG_BTR_MASK:
|
||||
return register_prefix "btr";
|
||||
case REG_EDR_MASK:
|
||||
return register_prefix "edr";
|
||||
case REG_PID_MASK:
|
||||
return register_prefix "pid";
|
||||
case REG_ZPR_MASK:
|
||||
return register_prefix "zpr";
|
||||
case REG_TLBX_MASK:
|
||||
return register_prefix "tlbx";
|
||||
case REG_TLBLO_MASK:
|
||||
return register_prefix "tlblo";
|
||||
case REG_TLBHI_MASK:
|
||||
return register_prefix "tlbhi";
|
||||
case REG_TLBSX_MASK:
|
||||
return register_prefix "tlbsx";
|
||||
default:
|
||||
if ((special & 0xE000) == REG_PVR_MASK) {
|
||||
/* pvr register */
|
||||
return NULL;
|
||||
}
|
||||
return register_prefix "pc";
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
@ -767,185 +672,189 @@ read_insn_microblaze (bfd_vma memaddr,
|
||||
return inst;
|
||||
}
|
||||
|
||||
static void print_immval_addr(struct disassemble_info *info, bool immfound,
|
||||
int immval, unsigned inst, int addend)
|
||||
{
|
||||
if (info->print_address_func && info->symbol_at_address_func) {
|
||||
if (immfound) {
|
||||
immval |= get_int_field_imm(inst) & 0x0000ffff;
|
||||
} else {
|
||||
immval = (int16_t)get_int_field_imm(inst);
|
||||
}
|
||||
immval += addend;
|
||||
if (immval != 0 && info->symbol_at_address_func(immval, info)) {
|
||||
info->fprintf_func(info->stream, "\t// ");
|
||||
info->print_address_func (immval, info);
|
||||
} else if (addend) {
|
||||
info->fprintf_func(info->stream, "\t// %x", immval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
|
||||
print_insn_microblaze(bfd_vma memaddr, struct disassemble_info *info)
|
||||
{
|
||||
fprintf_function fprintf_func = info->fprintf_func;
|
||||
void * stream = info->stream;
|
||||
unsigned long inst, prev_inst;
|
||||
const struct op_code_struct *op, *pop;
|
||||
int immval = 0;
|
||||
bfd_boolean immfound = FALSE;
|
||||
static bfd_vma prev_insn_addr = -1; /*init the prev insn addr */
|
||||
static int prev_insn_vma = -1; /*init the prev insn vma */
|
||||
int curr_insn_vma = info->buffer_vma;
|
||||
fprintf_function fprintf_func = info->fprintf_func;
|
||||
void *stream = info->stream;
|
||||
unsigned long inst, prev_inst;
|
||||
const struct op_code_struct *op, *pop;
|
||||
int immval = 0;
|
||||
bool immfound = false;
|
||||
static bfd_vma prev_insn_addr = -1; /*init the prev insn addr */
|
||||
static int prev_insn_vma = -1; /*init the prev insn vma */
|
||||
int curr_insn_vma = info->buffer_vma;
|
||||
int special;
|
||||
const char *special_name;
|
||||
|
||||
info->bytes_per_chunk = 4;
|
||||
info->bytes_per_chunk = 4;
|
||||
|
||||
inst = read_insn_microblaze (memaddr, info, &op);
|
||||
if (inst == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (prev_insn_vma == curr_insn_vma) {
|
||||
if (memaddr-(info->bytes_per_chunk) == prev_insn_addr) {
|
||||
prev_inst = read_insn_microblaze (prev_insn_addr, info, &pop);
|
||||
if (prev_inst == 0)
|
||||
return -1;
|
||||
if (pop->instr == imm) {
|
||||
immval = (get_int_field_imm(prev_inst) << 16) & 0xffff0000;
|
||||
immfound = TRUE;
|
||||
}
|
||||
else {
|
||||
immval = 0;
|
||||
immfound = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* make curr insn as prev insn */
|
||||
prev_insn_addr = memaddr;
|
||||
prev_insn_vma = curr_insn_vma;
|
||||
|
||||
if (op->name == 0) {
|
||||
fprintf_func (stream, ".short 0x%04lx", inst);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf_func (stream, "%s", op->name);
|
||||
|
||||
switch (op->inst_type)
|
||||
{
|
||||
case INST_TYPE_RD_R1_R2:
|
||||
fprintf_func(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_r2(inst));
|
||||
break;
|
||||
case INST_TYPE_RD_R1_IMM:
|
||||
fprintf_func(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_imm(inst));
|
||||
if (info->print_address_func && get_int_field_r1(inst) == 0 && info->symbol_at_address_func) {
|
||||
if (immfound)
|
||||
immval |= (get_int_field_imm(inst) & 0x0000ffff);
|
||||
else {
|
||||
immval = get_int_field_imm(inst);
|
||||
if (immval & 0x8000)
|
||||
immval |= 0xFFFF0000;
|
||||
}
|
||||
if (immval > 0 && info->symbol_at_address_func(immval, info)) {
|
||||
fprintf_func (stream, "\t// ");
|
||||
info->print_address_func (immval, info);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case INST_TYPE_RD_R1_IMM5:
|
||||
fprintf_func(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_imm5(inst));
|
||||
break;
|
||||
case INST_TYPE_RD_RFSL:
|
||||
fprintf_func(stream, "\t%s, %s", get_field_rd(inst), get_field_rfsl(inst));
|
||||
break;
|
||||
case INST_TYPE_R1_RFSL:
|
||||
fprintf_func(stream, "\t%s, %s", get_field_r1(inst), get_field_rfsl(inst));
|
||||
break;
|
||||
case INST_TYPE_RD_SPECIAL:
|
||||
fprintf_func(stream, "\t%s, %s", get_field_rd(inst), get_field_special(inst, op));
|
||||
break;
|
||||
case INST_TYPE_SPECIAL_R1:
|
||||
fprintf_func(stream, "\t%s, %s", get_field_special(inst, op), get_field_r1(inst));
|
||||
break;
|
||||
case INST_TYPE_RD_R1:
|
||||
fprintf_func(stream, "\t%s, %s", get_field_rd(inst), get_field_r1(inst));
|
||||
break;
|
||||
case INST_TYPE_R1_R2:
|
||||
fprintf_func(stream, "\t%s, %s", get_field_r1(inst), get_field_r2(inst));
|
||||
break;
|
||||
case INST_TYPE_R1_IMM:
|
||||
fprintf_func(stream, "\t%s, %s", get_field_r1(inst), get_field_imm(inst));
|
||||
/* The non-pc relative instructions are returns, which shouldn't
|
||||
have a label printed */
|
||||
if (info->print_address_func && op->inst_offset_type == INST_PC_OFFSET && info->symbol_at_address_func) {
|
||||
if (immfound)
|
||||
immval |= (get_int_field_imm(inst) & 0x0000ffff);
|
||||
else {
|
||||
immval = get_int_field_imm(inst);
|
||||
if (immval & 0x8000)
|
||||
immval |= 0xFFFF0000;
|
||||
}
|
||||
immval += memaddr;
|
||||
if (immval > 0 && info->symbol_at_address_func(immval, info)) {
|
||||
fprintf_func (stream, "\t// ");
|
||||
info->print_address_func (immval, info);
|
||||
} else {
|
||||
fprintf_func (stream, "\t\t// ");
|
||||
fprintf_func (stream, "%x", immval);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case INST_TYPE_RD_IMM:
|
||||
fprintf_func(stream, "\t%s, %s", get_field_rd(inst), get_field_imm(inst));
|
||||
if (info->print_address_func && info->symbol_at_address_func) {
|
||||
if (immfound)
|
||||
immval |= (get_int_field_imm(inst) & 0x0000ffff);
|
||||
else {
|
||||
immval = get_int_field_imm(inst);
|
||||
if (immval & 0x8000)
|
||||
immval |= 0xFFFF0000;
|
||||
}
|
||||
if (op->inst_offset_type == INST_PC_OFFSET)
|
||||
immval += (int) memaddr;
|
||||
if (info->symbol_at_address_func(immval, info)) {
|
||||
fprintf_func (stream, "\t// ");
|
||||
info->print_address_func (immval, info);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case INST_TYPE_IMM:
|
||||
fprintf_func(stream, "\t%s", get_field_imm(inst));
|
||||
if (info->print_address_func && info->symbol_at_address_func && op->instr != imm) {
|
||||
if (immfound)
|
||||
immval |= (get_int_field_imm(inst) & 0x0000ffff);
|
||||
else {
|
||||
immval = get_int_field_imm(inst);
|
||||
if (immval & 0x8000)
|
||||
immval |= 0xFFFF0000;
|
||||
}
|
||||
if (op->inst_offset_type == INST_PC_OFFSET)
|
||||
immval += (int) memaddr;
|
||||
if (immval > 0 && info->symbol_at_address_func(immval, info)) {
|
||||
fprintf_func (stream, "\t// ");
|
||||
info->print_address_func (immval, info);
|
||||
} else if (op->inst_offset_type == INST_PC_OFFSET) {
|
||||
fprintf_func (stream, "\t\t// ");
|
||||
fprintf_func (stream, "%x", immval);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case INST_TYPE_RD_R2:
|
||||
fprintf_func(stream, "\t%s, %s", get_field_rd(inst), get_field_r2(inst));
|
||||
break;
|
||||
case INST_TYPE_R2:
|
||||
fprintf_func(stream, "\t%s", get_field_r2(inst));
|
||||
break;
|
||||
case INST_TYPE_R1:
|
||||
fprintf_func(stream, "\t%s", get_field_r1(inst));
|
||||
break;
|
||||
case INST_TYPE_RD_R1_SPECIAL:
|
||||
fprintf_func(stream, "\t%s, %s", get_field_rd(inst), get_field_r2(inst));
|
||||
break;
|
||||
case INST_TYPE_RD_IMM15:
|
||||
fprintf_func(stream, "\t%s, %s", get_field_rd(inst), get_field_imm15(inst));
|
||||
break;
|
||||
/* For tuqula instruction */
|
||||
case INST_TYPE_RD:
|
||||
fprintf_func(stream, "\t%s", get_field_rd(inst));
|
||||
break;
|
||||
case INST_TYPE_RFSL:
|
||||
fprintf_func(stream, "\t%s", get_field_rfsl(inst));
|
||||
break;
|
||||
default:
|
||||
/* if the disassembler lags the instruction set */
|
||||
fprintf_func (stream, "\tundecoded operands, inst is 0x%04lx", inst);
|
||||
break;
|
||||
}
|
||||
inst = read_insn_microblaze (memaddr, info, &op);
|
||||
if (inst == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Say how many bytes we consumed? */
|
||||
return 4;
|
||||
if (prev_insn_vma == curr_insn_vma) {
|
||||
if (memaddr - info->bytes_per_chunk == prev_insn_addr) {
|
||||
prev_inst = read_insn_microblaze (prev_insn_addr, info, &pop);
|
||||
if (prev_inst == 0)
|
||||
return -1;
|
||||
if (pop->instr == imm) {
|
||||
immval = (get_int_field_imm(prev_inst) << 16) & 0xffff0000;
|
||||
immfound = TRUE;
|
||||
}
|
||||
else {
|
||||
immval = 0;
|
||||
immfound = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* make curr insn as prev insn */
|
||||
prev_insn_addr = memaddr;
|
||||
prev_insn_vma = curr_insn_vma;
|
||||
|
||||
if (op->name == 0) {
|
||||
fprintf_func (stream, ".short 0x%04lx", inst);
|
||||
return 4;
|
||||
}
|
||||
|
||||
switch (op->inst_type) {
|
||||
case INST_TYPE_RD_R1_R2:
|
||||
fprintf_func(stream, "%s\t" PRIreg ", " PRIreg ", " PRIreg,
|
||||
op->name, get_field_rd(inst), get_field_r1(inst),
|
||||
get_field_r2(inst));
|
||||
break;
|
||||
case INST_TYPE_RD_R1_IMM:
|
||||
fprintf_func(stream, "%s\t" PRIreg ", " PRIreg ", " PRIimm,
|
||||
op->name, get_field_rd(inst), get_field_r1(inst),
|
||||
get_field_imm(inst));
|
||||
if (get_int_field_r1(inst) == 0) {
|
||||
print_immval_addr(info, immfound, immval, inst, 0);
|
||||
}
|
||||
break;
|
||||
case INST_TYPE_RD_R1_IMM5:
|
||||
fprintf_func(stream, "%s\t" PRIreg ", " PRIreg ", " PRIimm,
|
||||
op->name, get_field_rd(inst), get_field_r1(inst),
|
||||
get_field_imm5(inst));
|
||||
break;
|
||||
case INST_TYPE_RD_RFSL:
|
||||
fprintf_func(stream, "%s\t" PRIreg ", " PRIrfsl,
|
||||
op->name, get_field_rd(inst), get_field_rfsl(inst));
|
||||
break;
|
||||
case INST_TYPE_R1_RFSL:
|
||||
fprintf_func(stream, "%s\t" PRIreg ", " PRIrfsl,
|
||||
op->name, get_field_r1(inst), get_field_rfsl(inst));
|
||||
break;
|
||||
case INST_TYPE_RD_SPECIAL:
|
||||
special = get_field_special(inst, op);
|
||||
special_name = get_special_name(special);
|
||||
if (special_name) {
|
||||
fprintf_func(stream, "%s\t" PRIreg ", %s",
|
||||
op->name, get_field_rd(inst), special_name);
|
||||
} else {
|
||||
fprintf_func(stream, "%s\t" PRIreg ", " PRIpvr,
|
||||
op->name, get_field_rd(inst), special ^ REG_PVR_MASK);
|
||||
}
|
||||
break;
|
||||
case INST_TYPE_SPECIAL_R1:
|
||||
special = get_field_special(inst, op);
|
||||
special_name = get_special_name(special);
|
||||
if (special_name) {
|
||||
fprintf_func(stream, "%s\t%s, " PRIreg,
|
||||
op->name, special_name, get_field_r1(inst));
|
||||
} else {
|
||||
fprintf_func(stream, "%s\t" PRIpvr ", " PRIreg,
|
||||
op->name, special ^ REG_PVR_MASK, get_field_r1(inst));
|
||||
}
|
||||
break;
|
||||
case INST_TYPE_RD_R1:
|
||||
fprintf_func(stream, "%s\t" PRIreg ", " PRIreg,
|
||||
op->name, get_field_rd(inst), get_field_r1(inst));
|
||||
break;
|
||||
case INST_TYPE_R1_R2:
|
||||
fprintf_func(stream, "%s\t" PRIreg ", " PRIreg,
|
||||
op->name, get_field_r1(inst), get_field_r2(inst));
|
||||
break;
|
||||
case INST_TYPE_R1_IMM:
|
||||
fprintf_func(stream, "%s\t" PRIreg ", " PRIimm,
|
||||
op->name, get_field_r1(inst), get_field_imm(inst));
|
||||
/*
|
||||
* The non-pc relative instructions are returns,
|
||||
* which shouldn't have a label printed.
|
||||
*/
|
||||
if (op->inst_offset_type == INST_PC_OFFSET) {
|
||||
print_immval_addr(info, immfound, immval, inst, memaddr);
|
||||
}
|
||||
break;
|
||||
case INST_TYPE_RD_IMM:
|
||||
fprintf_func(stream, "%s\t" PRIreg ", " PRIimm,
|
||||
op->name, get_field_rd(inst), get_field_imm(inst));
|
||||
print_immval_addr(info, immfound, immval, inst,
|
||||
op->inst_offset_type == INST_PC_OFFSET
|
||||
? memaddr : 0);
|
||||
break;
|
||||
case INST_TYPE_IMM:
|
||||
fprintf_func(stream, "%s\t" PRIimm,
|
||||
op->name, get_field_imm(inst));
|
||||
if (op->instr != imm) {
|
||||
print_immval_addr(info, immfound, immval, inst,
|
||||
op->inst_offset_type == INST_PC_OFFSET
|
||||
? memaddr : 0);
|
||||
}
|
||||
break;
|
||||
case INST_TYPE_RD_R2:
|
||||
fprintf_func(stream, "%s\t" PRIreg ", " PRIreg,
|
||||
op->name, get_field_rd(inst), get_field_r2(inst));
|
||||
break;
|
||||
case INST_TYPE_R2:
|
||||
fprintf_func(stream, "%s\t" PRIreg,
|
||||
op->name, get_field_r2(inst));
|
||||
break;
|
||||
case INST_TYPE_R1:
|
||||
fprintf_func(stream, "%s\t" PRIreg,
|
||||
op->name, get_field_r1(inst));
|
||||
break;
|
||||
case INST_TYPE_RD_R1_SPECIAL:
|
||||
fprintf_func(stream, "%s\t" PRIreg ", " PRIreg,
|
||||
op->name, get_field_rd(inst), get_field_r2(inst));
|
||||
break;
|
||||
case INST_TYPE_RD_IMM15:
|
||||
fprintf_func(stream, "%s\t" PRIreg ", " PRIimm,
|
||||
op->name, get_field_rd(inst), get_field_imm15(inst));
|
||||
break;
|
||||
/* For tuqula instruction */
|
||||
case INST_TYPE_RD:
|
||||
fprintf_func(stream, "%s\t" PRIreg,
|
||||
op->name, get_field_rd(inst));
|
||||
break;
|
||||
case INST_TYPE_RFSL:
|
||||
fprintf_func(stream, "%s\t" PRIrfsl,
|
||||
op->name, get_field_rfsl(inst));
|
||||
break;
|
||||
default:
|
||||
/* if the disassembler lags the instruction set */
|
||||
fprintf_func(stream, "%s\tundecoded operands, inst is 0x%04lx",
|
||||
op->name, inst);
|
||||
break;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
209
disas/riscv.c
209
disas/riscv.c
@ -4820,272 +4820,249 @@ static size_t inst_length(rv_inst inst)
|
||||
|
||||
/* format instruction */
|
||||
|
||||
static void append(char *s1, const char *s2, size_t n)
|
||||
{
|
||||
size_t l1 = strlen(s1);
|
||||
if (n - l1 - 1 > 0) {
|
||||
strncat(s1, s2, n - l1);
|
||||
}
|
||||
}
|
||||
|
||||
static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec)
|
||||
static GString *format_inst(size_t tab, rv_decode *dec)
|
||||
{
|
||||
const rv_opcode_data *opcode_data = dec->opcode_data;
|
||||
char tmp[64];
|
||||
GString *buf = g_string_sized_new(64);
|
||||
const char *fmt;
|
||||
|
||||
fmt = opcode_data[dec->op].format;
|
||||
while (*fmt) {
|
||||
switch (*fmt) {
|
||||
case 'O':
|
||||
append(buf, opcode_data[dec->op].name, buflen);
|
||||
g_string_append(buf, opcode_data[dec->op].name);
|
||||
break;
|
||||
case '(':
|
||||
append(buf, "(", buflen);
|
||||
break;
|
||||
case ',':
|
||||
append(buf, ",", buflen);
|
||||
break;
|
||||
case ')':
|
||||
append(buf, ")", buflen);
|
||||
break;
|
||||
case '-':
|
||||
append(buf, "-", buflen);
|
||||
g_string_append_c(buf, *fmt);
|
||||
break;
|
||||
case 'b':
|
||||
snprintf(tmp, sizeof(tmp), "%d", dec->bs);
|
||||
append(buf, tmp, buflen);
|
||||
g_string_append_printf(buf, "%d", dec->bs);
|
||||
break;
|
||||
case 'n':
|
||||
snprintf(tmp, sizeof(tmp), "%d", dec->rnum);
|
||||
append(buf, tmp, buflen);
|
||||
g_string_append_printf(buf, "%d", dec->rnum);
|
||||
break;
|
||||
case '0':
|
||||
append(buf, rv_ireg_name_sym[dec->rd], buflen);
|
||||
g_string_append(buf, rv_ireg_name_sym[dec->rd]);
|
||||
break;
|
||||
case '1':
|
||||
append(buf, rv_ireg_name_sym[dec->rs1], buflen);
|
||||
g_string_append(buf, rv_ireg_name_sym[dec->rs1]);
|
||||
break;
|
||||
case '2':
|
||||
append(buf, rv_ireg_name_sym[dec->rs2], buflen);
|
||||
g_string_append(buf, rv_ireg_name_sym[dec->rs2]);
|
||||
break;
|
||||
case '3':
|
||||
append(buf, dec->cfg->ext_zfinx ? rv_ireg_name_sym[dec->rd] :
|
||||
rv_freg_name_sym[dec->rd],
|
||||
buflen);
|
||||
if (dec->cfg->ext_zfinx) {
|
||||
g_string_append(buf, rv_ireg_name_sym[dec->rd]);
|
||||
} else {
|
||||
g_string_append(buf, rv_freg_name_sym[dec->rd]);
|
||||
}
|
||||
break;
|
||||
case '4':
|
||||
append(buf, dec->cfg->ext_zfinx ? rv_ireg_name_sym[dec->rs1] :
|
||||
rv_freg_name_sym[dec->rs1],
|
||||
buflen);
|
||||
if (dec->cfg->ext_zfinx) {
|
||||
g_string_append(buf, rv_ireg_name_sym[dec->rs1]);
|
||||
} else {
|
||||
g_string_append(buf, rv_freg_name_sym[dec->rs1]);
|
||||
}
|
||||
break;
|
||||
case '5':
|
||||
append(buf, dec->cfg->ext_zfinx ? rv_ireg_name_sym[dec->rs2] :
|
||||
rv_freg_name_sym[dec->rs2],
|
||||
buflen);
|
||||
if (dec->cfg->ext_zfinx) {
|
||||
g_string_append(buf, rv_ireg_name_sym[dec->rs2]);
|
||||
} else {
|
||||
g_string_append(buf, rv_freg_name_sym[dec->rs2]);
|
||||
}
|
||||
break;
|
||||
case '6':
|
||||
append(buf, dec->cfg->ext_zfinx ? rv_ireg_name_sym[dec->rs3] :
|
||||
rv_freg_name_sym[dec->rs3],
|
||||
buflen);
|
||||
if (dec->cfg->ext_zfinx) {
|
||||
g_string_append(buf, rv_ireg_name_sym[dec->rs3]);
|
||||
} else {
|
||||
g_string_append(buf, rv_freg_name_sym[dec->rs3]);
|
||||
}
|
||||
break;
|
||||
case '7':
|
||||
snprintf(tmp, sizeof(tmp), "%d", dec->rs1);
|
||||
append(buf, tmp, buflen);
|
||||
g_string_append_printf(buf, "%d", dec->rs1);
|
||||
break;
|
||||
case 'i':
|
||||
snprintf(tmp, sizeof(tmp), "%d", dec->imm);
|
||||
append(buf, tmp, buflen);
|
||||
g_string_append_printf(buf, "%d", dec->imm);
|
||||
break;
|
||||
case 'u':
|
||||
snprintf(tmp, sizeof(tmp), "%u", ((uint32_t)dec->imm & 0b111111));
|
||||
append(buf, tmp, buflen);
|
||||
g_string_append_printf(buf, "%u", ((uint32_t)dec->imm & 0b111111));
|
||||
break;
|
||||
case 'j':
|
||||
snprintf(tmp, sizeof(tmp), "%d", dec->imm1);
|
||||
append(buf, tmp, buflen);
|
||||
g_string_append_printf(buf, "%d", dec->imm1);
|
||||
break;
|
||||
case 'o':
|
||||
snprintf(tmp, sizeof(tmp), "%d", dec->imm);
|
||||
append(buf, tmp, buflen);
|
||||
while (strlen(buf) < tab * 2) {
|
||||
append(buf, " ", buflen);
|
||||
g_string_append_printf(buf, "%d", dec->imm);
|
||||
while (buf->len < tab * 2) {
|
||||
g_string_append_c(buf, ' ');
|
||||
}
|
||||
snprintf(tmp, sizeof(tmp), "# 0x%" PRIx64,
|
||||
dec->pc + dec->imm);
|
||||
append(buf, tmp, buflen);
|
||||
g_string_append_printf(buf, "# 0x%" PRIx64, dec->pc + dec->imm);
|
||||
break;
|
||||
case 'U':
|
||||
fmt++;
|
||||
snprintf(tmp, sizeof(tmp), "%d", dec->imm >> 12);
|
||||
append(buf, tmp, buflen);
|
||||
g_string_append_printf(buf, "%d", dec->imm >> 12);
|
||||
if (*fmt == 'o') {
|
||||
while (strlen(buf) < tab * 2) {
|
||||
append(buf, " ", buflen);
|
||||
while (buf->len < tab * 2) {
|
||||
g_string_append_c(buf, ' ');
|
||||
}
|
||||
snprintf(tmp, sizeof(tmp), "# 0x%" PRIx64,
|
||||
dec->pc + dec->imm);
|
||||
append(buf, tmp, buflen);
|
||||
g_string_append_printf(buf, "# 0x%" PRIx64, dec->pc + dec->imm);
|
||||
}
|
||||
break;
|
||||
case 'c': {
|
||||
const char *name = csr_name(dec->imm & 0xfff);
|
||||
if (name) {
|
||||
append(buf, name, buflen);
|
||||
g_string_append(buf, name);
|
||||
} else {
|
||||
snprintf(tmp, sizeof(tmp), "0x%03x", dec->imm & 0xfff);
|
||||
append(buf, tmp, buflen);
|
||||
g_string_append_printf(buf, "0x%03x", dec->imm & 0xfff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'r':
|
||||
switch (dec->rm) {
|
||||
case rv_rm_rne:
|
||||
append(buf, "rne", buflen);
|
||||
g_string_append(buf, "rne");
|
||||
break;
|
||||
case rv_rm_rtz:
|
||||
append(buf, "rtz", buflen);
|
||||
g_string_append(buf, "rtz");
|
||||
break;
|
||||
case rv_rm_rdn:
|
||||
append(buf, "rdn", buflen);
|
||||
g_string_append(buf, "rdn");
|
||||
break;
|
||||
case rv_rm_rup:
|
||||
append(buf, "rup", buflen);
|
||||
g_string_append(buf, "rup");
|
||||
break;
|
||||
case rv_rm_rmm:
|
||||
append(buf, "rmm", buflen);
|
||||
g_string_append(buf, "rmm");
|
||||
break;
|
||||
case rv_rm_dyn:
|
||||
append(buf, "dyn", buflen);
|
||||
g_string_append(buf, "dyn");
|
||||
break;
|
||||
default:
|
||||
append(buf, "inv", buflen);
|
||||
g_string_append(buf, "inv");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
if (dec->pred & rv_fence_i) {
|
||||
append(buf, "i", buflen);
|
||||
g_string_append_c(buf, 'i');
|
||||
}
|
||||
if (dec->pred & rv_fence_o) {
|
||||
append(buf, "o", buflen);
|
||||
g_string_append_c(buf, 'o');
|
||||
}
|
||||
if (dec->pred & rv_fence_r) {
|
||||
append(buf, "r", buflen);
|
||||
g_string_append_c(buf, 'r');
|
||||
}
|
||||
if (dec->pred & rv_fence_w) {
|
||||
append(buf, "w", buflen);
|
||||
g_string_append_c(buf, 'w');
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
if (dec->succ & rv_fence_i) {
|
||||
append(buf, "i", buflen);
|
||||
g_string_append_c(buf, 'i');
|
||||
}
|
||||
if (dec->succ & rv_fence_o) {
|
||||
append(buf, "o", buflen);
|
||||
g_string_append_c(buf, 'o');
|
||||
}
|
||||
if (dec->succ & rv_fence_r) {
|
||||
append(buf, "r", buflen);
|
||||
g_string_append_c(buf, 'r');
|
||||
}
|
||||
if (dec->succ & rv_fence_w) {
|
||||
append(buf, "w", buflen);
|
||||
g_string_append_c(buf, 'w');
|
||||
}
|
||||
break;
|
||||
case '\t':
|
||||
while (strlen(buf) < tab) {
|
||||
append(buf, " ", buflen);
|
||||
while (buf->len < tab) {
|
||||
g_string_append_c(buf, ' ');
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
if (dec->aq) {
|
||||
append(buf, ".aq", buflen);
|
||||
g_string_append(buf, ".aq");
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
if (dec->rl) {
|
||||
append(buf, ".rl", buflen);
|
||||
g_string_append(buf, ".rl");
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
append(buf, ",v0", buflen);
|
||||
g_string_append(buf, ",v0");
|
||||
break;
|
||||
case 'm':
|
||||
if (dec->vm == 0) {
|
||||
append(buf, ",v0.t", buflen);
|
||||
g_string_append(buf, ",v0.t");
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
append(buf, rv_vreg_name_sym[dec->rd], buflen);
|
||||
g_string_append(buf, rv_vreg_name_sym[dec->rd]);
|
||||
break;
|
||||
case 'E':
|
||||
append(buf, rv_vreg_name_sym[dec->rs1], buflen);
|
||||
g_string_append(buf, rv_vreg_name_sym[dec->rs1]);
|
||||
break;
|
||||
case 'F':
|
||||
append(buf, rv_vreg_name_sym[dec->rs2], buflen);
|
||||
g_string_append(buf, rv_vreg_name_sym[dec->rs2]);
|
||||
break;
|
||||
case 'G':
|
||||
append(buf, rv_vreg_name_sym[dec->rs3], buflen);
|
||||
g_string_append(buf, rv_vreg_name_sym[dec->rs3]);
|
||||
break;
|
||||
case 'v': {
|
||||
char nbuf[32] = {0};
|
||||
const int sew = 1 << (((dec->vzimm >> 3) & 0b111) + 3);
|
||||
sprintf(nbuf, "%d", sew);
|
||||
const int lmul = dec->vzimm & 0b11;
|
||||
const int flmul = (dec->vzimm >> 2) & 1;
|
||||
const char *vta = (dec->vzimm >> 6) & 1 ? "ta" : "tu";
|
||||
const char *vma = (dec->vzimm >> 7) & 1 ? "ma" : "mu";
|
||||
append(buf, "e", buflen);
|
||||
append(buf, nbuf, buflen);
|
||||
append(buf, ",m", buflen);
|
||||
|
||||
g_string_append_printf(buf, "e%d,m", sew);
|
||||
if (flmul) {
|
||||
switch (lmul) {
|
||||
case 3:
|
||||
sprintf(nbuf, "f2");
|
||||
g_string_append(buf, "f2");
|
||||
break;
|
||||
case 2:
|
||||
sprintf(nbuf, "f4");
|
||||
g_string_append(buf, "f4");
|
||||
break;
|
||||
case 1:
|
||||
sprintf(nbuf, "f8");
|
||||
break;
|
||||
g_string_append(buf, "f8");
|
||||
break;
|
||||
}
|
||||
append(buf, nbuf, buflen);
|
||||
} else {
|
||||
sprintf(nbuf, "%d", 1 << lmul);
|
||||
append(buf, nbuf, buflen);
|
||||
g_string_append_printf(buf, "%d", 1 << lmul);
|
||||
}
|
||||
append(buf, ",", buflen);
|
||||
append(buf, vta, buflen);
|
||||
append(buf, ",", buflen);
|
||||
append(buf, vma, buflen);
|
||||
g_string_append_c(buf, ',');
|
||||
g_string_append(buf, vta);
|
||||
g_string_append_c(buf, ',');
|
||||
g_string_append(buf, vma);
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
switch (dec->rlist) {
|
||||
case 4:
|
||||
snprintf(tmp, sizeof(tmp), "{ra}");
|
||||
g_string_append(buf, "{ra}");
|
||||
break;
|
||||
case 5:
|
||||
snprintf(tmp, sizeof(tmp), "{ra, s0}");
|
||||
g_string_append(buf, "{ra, s0}");
|
||||
break;
|
||||
case 15:
|
||||
snprintf(tmp, sizeof(tmp), "{ra, s0-s11}");
|
||||
g_string_append(buf, "{ra, s0-s11}");
|
||||
break;
|
||||
default:
|
||||
snprintf(tmp, sizeof(tmp), "{ra, s0-s%d}", dec->rlist - 5);
|
||||
g_string_append_printf(buf, "{ra, s0-s%d}", dec->rlist - 5);
|
||||
break;
|
||||
}
|
||||
append(buf, tmp, buflen);
|
||||
break;
|
||||
}
|
||||
case 'h':
|
||||
append(buf, rv_fli_name_const[dec->imm], buflen);
|
||||
g_string_append(buf, rv_fli_name_const[dec->imm]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fmt++;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* lift instruction to pseudo-instruction */
|
||||
@ -5171,9 +5148,8 @@ static void decode_inst_decompress(rv_decode *dec, rv_isa isa)
|
||||
|
||||
/* disassemble instruction */
|
||||
|
||||
static void
|
||||
disasm_inst(char *buf, size_t buflen, rv_isa isa, uint64_t pc, rv_inst inst,
|
||||
RISCVCPUConfig *cfg)
|
||||
static GString *disasm_inst(rv_isa isa, uint64_t pc, rv_inst inst,
|
||||
RISCVCPUConfig *cfg)
|
||||
{
|
||||
rv_decode dec = { 0 };
|
||||
dec.pc = pc;
|
||||
@ -5220,7 +5196,7 @@ disasm_inst(char *buf, size_t buflen, rv_isa isa, uint64_t pc, rv_inst inst,
|
||||
decode_inst_operands(&dec, isa);
|
||||
decode_inst_decompress(&dec, isa);
|
||||
decode_inst_lift_pseudo(&dec);
|
||||
format_inst(buf, buflen, 24, &dec);
|
||||
return format_inst(24, &dec);
|
||||
}
|
||||
|
||||
#define INST_FMT_2 "%04" PRIx64 " "
|
||||
@ -5231,7 +5207,6 @@ disasm_inst(char *buf, size_t buflen, rv_isa isa, uint64_t pc, rv_inst inst,
|
||||
static int
|
||||
print_insn_riscv(bfd_vma memaddr, struct disassemble_info *info, rv_isa isa)
|
||||
{
|
||||
char buf[128] = { 0 };
|
||||
bfd_byte packet[2];
|
||||
rv_inst inst = 0;
|
||||
size_t len = 2;
|
||||
@ -5272,9 +5247,9 @@ print_insn_riscv(bfd_vma memaddr, struct disassemble_info *info, rv_isa isa)
|
||||
}
|
||||
}
|
||||
|
||||
disasm_inst(buf, sizeof(buf), isa, memaddr, inst,
|
||||
(RISCVCPUConfig *)info->target_info);
|
||||
(*info->fprintf_func)(info->stream, "%s", buf);
|
||||
g_autoptr(GString) str =
|
||||
disasm_inst(isa, memaddr, inst, (RISCVCPUConfig *)info->target_info);
|
||||
(*info->fprintf_func)(info->stream, "%s", str->str);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/sysbus.h"
|
||||
@ -317,22 +318,14 @@ typedef struct PL330InsnDesc {
|
||||
|
||||
static void pl330_hexdump(uint8_t *buf, size_t size)
|
||||
{
|
||||
unsigned int b, i, len;
|
||||
char tmpbuf[80];
|
||||
g_autoptr(GString) str = g_string_sized_new(64);
|
||||
size_t b, len;
|
||||
|
||||
for (b = 0; b < size; b += 16) {
|
||||
len = size - b;
|
||||
if (len > 16) {
|
||||
len = 16;
|
||||
}
|
||||
tmpbuf[0] = '\0';
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((i % 4) == 0) {
|
||||
strcat(tmpbuf, " ");
|
||||
}
|
||||
sprintf(tmpbuf + strlen(tmpbuf), " %02x", buf[b + i]);
|
||||
}
|
||||
trace_pl330_hexdump(b, tmpbuf);
|
||||
for (b = 0; b < size; b += len) {
|
||||
len = MIN(16, size - b);
|
||||
g_string_truncate(str, 0);
|
||||
qemu_hexdump_line(str, buf + b, len, 1, 4);
|
||||
trace_pl330_hexdump(b, str->str);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "scsi/constants.h"
|
||||
@ -1309,14 +1310,9 @@ void ide_atapi_cmd(IDEState *s)
|
||||
trace_ide_atapi_cmd(s, s->io_buffer[0]);
|
||||
|
||||
if (trace_event_get_state_backends(TRACE_IDE_ATAPI_CMD_PACKET)) {
|
||||
/* Each pretty-printed byte needs two bytes and a space; */
|
||||
char *ppacket = g_malloc(ATAPI_PACKET_SIZE * 3 + 1);
|
||||
int i;
|
||||
for (i = 0; i < ATAPI_PACKET_SIZE; i++) {
|
||||
sprintf(ppacket + (i * 3), "%02x ", buf[i]);
|
||||
}
|
||||
trace_ide_atapi_cmd_packet(s, s->lcyl | (s->hcyl << 8), ppacket);
|
||||
g_free(ppacket);
|
||||
g_autoptr(GString) str =
|
||||
qemu_hexdump_line(NULL, buf, ATAPI_PACKET_SIZE, 1, 0);
|
||||
trace_ide_atapi_cmd_packet(s, s->lcyl | (s->hcyl << 8), str->str);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "qemu/units.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/datadir.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "hw/clock.h"
|
||||
#include "hw/southbridge/piix.h"
|
||||
@ -850,15 +851,18 @@ static void G_GNUC_PRINTF(3, 4) prom_set(uint32_t *prom_buf, int index,
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void reinitialize_rng_seed(void *opaque)
|
||||
static GString *rng_seed_hex_new(void)
|
||||
{
|
||||
char *rng_seed_hex = opaque;
|
||||
uint8_t rng_seed[32];
|
||||
|
||||
qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
|
||||
for (size_t i = 0; i < sizeof(rng_seed); ++i) {
|
||||
sprintf(rng_seed_hex + i * 2, "%02x", rng_seed[i]);
|
||||
}
|
||||
return qemu_hexdump_line(NULL, rng_seed, sizeof(rng_seed), 0, 0);
|
||||
}
|
||||
|
||||
static void reinitialize_rng_seed(void *opaque)
|
||||
{
|
||||
g_autoptr(GString) hex = rng_seed_hex_new();
|
||||
memcpy(opaque, hex->str, hex->len);
|
||||
}
|
||||
|
||||
/* Kernel */
|
||||
@ -870,8 +874,6 @@ static uint64_t load_kernel(void)
|
||||
uint32_t *prom_buf;
|
||||
long prom_size;
|
||||
int prom_index = 0;
|
||||
uint8_t rng_seed[32];
|
||||
char rng_seed_hex[sizeof(rng_seed) * 2 + 1];
|
||||
size_t rng_seed_prom_offset;
|
||||
|
||||
kernel_size = load_elf(loaderparams.kernel_filename, NULL,
|
||||
@ -946,14 +948,13 @@ static uint64_t load_kernel(void)
|
||||
prom_set(prom_buf, prom_index++, "modetty0");
|
||||
prom_set(prom_buf, prom_index++, "38400n8r");
|
||||
|
||||
qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
|
||||
for (size_t i = 0; i < sizeof(rng_seed); ++i) {
|
||||
sprintf(rng_seed_hex + i * 2, "%02x", rng_seed[i]);
|
||||
}
|
||||
prom_set(prom_buf, prom_index++, "rngseed");
|
||||
rng_seed_prom_offset = prom_index * ENVP_ENTRY_SIZE +
|
||||
sizeof(uint32_t) * ENVP_NB_ENTRIES;
|
||||
prom_set(prom_buf, prom_index++, "%s", rng_seed_hex);
|
||||
{
|
||||
g_autoptr(GString) hex = rng_seed_hex_new();
|
||||
prom_set(prom_buf, prom_index++, "%s", hex->str);
|
||||
}
|
||||
|
||||
prom_set(prom_buf, prom_index++, NULL);
|
||||
|
||||
|
@ -2648,19 +2648,12 @@ static const SCSIReqOps *const scsi_disk_reqops_dispatch[256] = {
|
||||
|
||||
static void scsi_disk_new_request_dump(uint32_t lun, uint32_t tag, uint8_t *buf)
|
||||
{
|
||||
int i;
|
||||
int len = scsi_cdb_length(buf);
|
||||
char *line_buffer, *p;
|
||||
g_autoptr(GString) str = NULL;
|
||||
|
||||
assert(len > 0 && len <= 16);
|
||||
line_buffer = g_malloc(len * 5 + 1);
|
||||
|
||||
for (i = 0, p = line_buffer; i < len; i++) {
|
||||
p += sprintf(p, " 0x%02x", buf[i]);
|
||||
}
|
||||
trace_scsi_disk_new_request(lun, tag, line_buffer);
|
||||
|
||||
g_free(line_buffer);
|
||||
str = qemu_hexdump_line(NULL, buf, len, 1, 0);
|
||||
trace_scsi_disk_new_request(lun, tag, str->str);
|
||||
}
|
||||
|
||||
static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
||||
|
@ -944,13 +944,15 @@ static int vhost_vdpa_set_config_call(struct vhost_dev *dev,
|
||||
static void vhost_vdpa_dump_config(struct vhost_dev *dev, const uint8_t *config,
|
||||
uint32_t config_len)
|
||||
{
|
||||
int b, len;
|
||||
char line[QEMU_HEXDUMP_LINE_LEN];
|
||||
g_autoptr(GString) str = g_string_sized_new(4 * 16);
|
||||
size_t b, len;
|
||||
|
||||
for (b = 0; b < config_len; b += 16) {
|
||||
len = config_len - b;
|
||||
qemu_hexdump_line(line, config + b, len);
|
||||
trace_vhost_vdpa_dump_config(dev, b, line);
|
||||
for (b = 0; b < config_len; b += len) {
|
||||
len = MIN(config_len - b, 16);
|
||||
|
||||
g_string_truncate(str, 0);
|
||||
qemu_hexdump_line(str, config + b, len, 1, 4);
|
||||
trace_vhost_vdpa_dump_config(dev, b, str->str);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,12 +282,21 @@ static inline const char *yes_no(bool b)
|
||||
*/
|
||||
int parse_debug_env(const char *name, int max, int initial);
|
||||
|
||||
/*
|
||||
* Hexdump a line of a byte buffer into a hexadecimal/ASCII buffer
|
||||
/**
|
||||
* qemu_hexdump_line:
|
||||
* @str: GString into which to append
|
||||
* @buf: buffer to dump
|
||||
* @len: number of bytes to dump
|
||||
* @unit_len: add a space between every @unit_len bytes
|
||||
* @block_len: add an extra space between every @block_len bytes
|
||||
*
|
||||
* Append @len bytes of @buf as hexadecimal into @str.
|
||||
* Add spaces between every @unit_len and @block_len bytes.
|
||||
* If @str is NULL, allocate a new string and return it;
|
||||
* otherwise return @str.
|
||||
*/
|
||||
#define QEMU_HEXDUMP_LINE_BYTES 16 /* Number of bytes to dump */
|
||||
#define QEMU_HEXDUMP_LINE_LEN 75 /* Number of characters in line */
|
||||
void qemu_hexdump_line(char *line, const void *bufptr, size_t len);
|
||||
GString *qemu_hexdump_line(GString *str, const void *buf, size_t len,
|
||||
size_t unit_len, size_t block_len);
|
||||
|
||||
/*
|
||||
* Hexdump a buffer to a file. An optional string prefix is added to every line
|
||||
|
@ -601,9 +601,9 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
|
||||
qtest_send_prefix(chr);
|
||||
qtest_sendf(chr, "OK 0x%016" PRIx64 "\n", value);
|
||||
} else if (strcmp(words[0], "read") == 0) {
|
||||
uint64_t addr, len, i;
|
||||
g_autoptr(GString) enc = NULL;
|
||||
uint64_t addr, len;
|
||||
uint8_t *data;
|
||||
char *enc;
|
||||
int ret;
|
||||
|
||||
g_assert(words[1] && words[2]);
|
||||
@ -618,16 +618,12 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
|
||||
address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,
|
||||
len);
|
||||
|
||||
enc = g_malloc(2 * len + 1);
|
||||
for (i = 0; i < len; i++) {
|
||||
sprintf(&enc[i * 2], "%02x", data[i]);
|
||||
}
|
||||
enc = qemu_hexdump_line(NULL, data, len, 0, 0);
|
||||
|
||||
qtest_send_prefix(chr);
|
||||
qtest_sendf(chr, "OK 0x%s\n", enc);
|
||||
qtest_sendf(chr, "OK 0x%s\n", enc->str);
|
||||
|
||||
g_free(data);
|
||||
g_free(enc);
|
||||
} else if (strcmp(words[0], "b64read") == 0) {
|
||||
uint64_t addr, len;
|
||||
uint8_t *data;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Helper to hexdump a buffer
|
||||
* Helper to hexdump a buffer
|
||||
*
|
||||
* Copyright (c) 2013 Red Hat, Inc.
|
||||
* Copyright (c) 2013 Gerd Hoffmann <kraxel@redhat.com>
|
||||
@ -16,22 +16,47 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/cutils.h"
|
||||
|
||||
void qemu_hexdump_line(char *line, const void *bufptr, size_t len)
|
||||
static inline char hexdump_nibble(unsigned x)
|
||||
{
|
||||
const char *buf = bufptr;
|
||||
int i;
|
||||
return (x < 10 ? '0' : 'a' - 10) + x;
|
||||
}
|
||||
|
||||
if (len > QEMU_HEXDUMP_LINE_BYTES) {
|
||||
len = QEMU_HEXDUMP_LINE_BYTES;
|
||||
}
|
||||
GString *qemu_hexdump_line(GString *str, const void *vbuf, size_t len,
|
||||
size_t unit_len, size_t block_len)
|
||||
{
|
||||
const uint8_t *buf = vbuf;
|
||||
size_t u, b;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i != 0 && (i % 4) == 0) {
|
||||
*line++ = ' ';
|
||||
if (str == NULL) {
|
||||
/* Estimate the length of the output to avoid reallocs. */
|
||||
size_t est = len * 2;
|
||||
if (unit_len) {
|
||||
est += len / unit_len;
|
||||
}
|
||||
line += sprintf(line, " %02x", (unsigned char)buf[i]);
|
||||
if (block_len) {
|
||||
est += len / block_len;
|
||||
}
|
||||
str = g_string_sized_new(est + 1);
|
||||
}
|
||||
*line = '\0';
|
||||
|
||||
for (u = 0, b = 0; len; u++, b++, len--, buf++) {
|
||||
uint8_t c;
|
||||
|
||||
if (unit_len && u == unit_len) {
|
||||
g_string_append_c(str, ' ');
|
||||
u = 0;
|
||||
}
|
||||
if (block_len && b == block_len) {
|
||||
g_string_append_c(str, ' ');
|
||||
b = 0;
|
||||
}
|
||||
|
||||
c = *buf;
|
||||
g_string_append_c(str, hexdump_nibble(c / 16));
|
||||
g_string_append_c(str, hexdump_nibble(c % 16));
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static void asciidump_line(char *line, const void *bufptr, size_t len)
|
||||
@ -49,24 +74,26 @@ static void asciidump_line(char *line, const void *bufptr, size_t len)
|
||||
*line = '\0';
|
||||
}
|
||||
|
||||
#define QEMU_HEXDUMP_LINE_BYTES 16
|
||||
#define QEMU_HEXDUMP_LINE_WIDTH \
|
||||
(QEMU_HEXDUMP_LINE_BYTES * 2 + QEMU_HEXDUMP_LINE_BYTES / 4)
|
||||
|
||||
void qemu_hexdump(FILE *fp, const char *prefix,
|
||||
const void *bufptr, size_t size)
|
||||
{
|
||||
char line[QEMU_HEXDUMP_LINE_LEN];
|
||||
g_autoptr(GString) str = g_string_sized_new(QEMU_HEXDUMP_LINE_WIDTH + 1);
|
||||
char ascii[QEMU_HEXDUMP_LINE_BYTES + 1];
|
||||
size_t b, len;
|
||||
|
||||
for (b = 0; b < size; b += len) {
|
||||
len = MIN(size - b, QEMU_HEXDUMP_LINE_BYTES);
|
||||
|
||||
qemu_hexdump_line(line, bufptr + b, len);
|
||||
g_string_truncate(str, 0);
|
||||
qemu_hexdump_line(str, bufptr + b, len, 1, 4);
|
||||
asciidump_line(ascii, bufptr + b, len);
|
||||
|
||||
fprintf(fp, "%s: %04zx: %-*s %s\n",
|
||||
prefix, b, QEMU_HEXDUMP_LINE_WIDTH, line, ascii);
|
||||
prefix, b, QEMU_HEXDUMP_LINE_WIDTH, str->str, ascii);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user