Hexagon HVX (target/hexagon) add Hexagon Vector eXtensions (HVX) to core
HVX is a set of wide vector instructions. Machine state includes vector registers (VRegs) vector predicate registers (QRegs) temporary registers for intermediate values store buffer (masked stores and scatter/gather) Acked-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
This commit is contained in:
parent
375bcf389f
commit
a1559537d1
@ -113,7 +113,66 @@ static void print_reg(FILE *f, CPUHexagonState *env, int regnum)
|
||||
hexagon_regnames[regnum], value);
|
||||
}
|
||||
|
||||
static void hexagon_dump(CPUHexagonState *env, FILE *f)
|
||||
static void print_vreg(FILE *f, CPUHexagonState *env, int regnum,
|
||||
bool skip_if_zero)
|
||||
{
|
||||
if (skip_if_zero) {
|
||||
bool nonzero_found = false;
|
||||
for (int i = 0; i < MAX_VEC_SIZE_BYTES; i++) {
|
||||
if (env->VRegs[regnum].ub[i] != 0) {
|
||||
nonzero_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!nonzero_found) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
qemu_fprintf(f, " v%d = ( ", regnum);
|
||||
qemu_fprintf(f, "0x%02x", env->VRegs[regnum].ub[MAX_VEC_SIZE_BYTES - 1]);
|
||||
for (int i = MAX_VEC_SIZE_BYTES - 2; i >= 0; i--) {
|
||||
qemu_fprintf(f, ", 0x%02x", env->VRegs[regnum].ub[i]);
|
||||
}
|
||||
qemu_fprintf(f, " )\n");
|
||||
}
|
||||
|
||||
void hexagon_debug_vreg(CPUHexagonState *env, int regnum)
|
||||
{
|
||||
print_vreg(stdout, env, regnum, false);
|
||||
}
|
||||
|
||||
static void print_qreg(FILE *f, CPUHexagonState *env, int regnum,
|
||||
bool skip_if_zero)
|
||||
{
|
||||
if (skip_if_zero) {
|
||||
bool nonzero_found = false;
|
||||
for (int i = 0; i < MAX_VEC_SIZE_BYTES / 8; i++) {
|
||||
if (env->QRegs[regnum].ub[i] != 0) {
|
||||
nonzero_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!nonzero_found) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
qemu_fprintf(f, " q%d = ( ", regnum);
|
||||
qemu_fprintf(f, "0x%02x",
|
||||
env->QRegs[regnum].ub[MAX_VEC_SIZE_BYTES / 8 - 1]);
|
||||
for (int i = MAX_VEC_SIZE_BYTES / 8 - 2; i >= 0; i--) {
|
||||
qemu_fprintf(f, ", 0x%02x", env->QRegs[regnum].ub[i]);
|
||||
}
|
||||
qemu_fprintf(f, " )\n");
|
||||
}
|
||||
|
||||
void hexagon_debug_qreg(CPUHexagonState *env, int regnum)
|
||||
{
|
||||
print_qreg(stdout, env, regnum, false);
|
||||
}
|
||||
|
||||
static void hexagon_dump(CPUHexagonState *env, FILE *f, int flags)
|
||||
{
|
||||
HexagonCPU *cpu = env_archcpu(env);
|
||||
|
||||
@ -159,6 +218,17 @@ static void hexagon_dump(CPUHexagonState *env, FILE *f)
|
||||
print_reg(f, env, HEX_REG_CS1);
|
||||
#endif
|
||||
qemu_fprintf(f, "}\n");
|
||||
|
||||
if (flags & CPU_DUMP_FPU) {
|
||||
qemu_fprintf(f, "Vector Registers = {\n");
|
||||
for (int i = 0; i < NUM_VREGS; i++) {
|
||||
print_vreg(f, env, i, true);
|
||||
}
|
||||
for (int i = 0; i < NUM_QREGS; i++) {
|
||||
print_qreg(f, env, i, true);
|
||||
}
|
||||
qemu_fprintf(f, "}\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void hexagon_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
@ -166,12 +236,12 @@ static void hexagon_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
HexagonCPU *cpu = HEXAGON_CPU(cs);
|
||||
CPUHexagonState *env = &cpu->env;
|
||||
|
||||
hexagon_dump(env, f);
|
||||
hexagon_dump(env, f, flags);
|
||||
}
|
||||
|
||||
void hexagon_debug(CPUHexagonState *env)
|
||||
{
|
||||
hexagon_dump(env, stdout);
|
||||
hexagon_dump(env, stdout, CPU_DUMP_FPU);
|
||||
}
|
||||
|
||||
static void hexagon_cpu_set_pc(CPUState *cs, vaddr value)
|
||||
@ -292,7 +362,7 @@ static void hexagon_cpu_class_init(ObjectClass *c, void *data)
|
||||
cc->set_pc = hexagon_cpu_set_pc;
|
||||
cc->gdb_read_register = hexagon_gdb_read_register;
|
||||
cc->gdb_write_register = hexagon_gdb_write_register;
|
||||
cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS;
|
||||
cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS + NUM_VREGS + NUM_QREGS;
|
||||
cc->gdb_stop_before_watchpoint = true;
|
||||
cc->disas_set_info = hexagon_cpu_disas_set_info;
|
||||
cc->tcg_ops = &hexagon_tcg_ops;
|
||||
|
@ -26,6 +26,7 @@ typedef struct CPUHexagonState CPUHexagonState;
|
||||
#include "qemu-common.h"
|
||||
#include "exec/cpu-defs.h"
|
||||
#include "hex_regs.h"
|
||||
#include "mmvec/mmvec.h"
|
||||
|
||||
#define NUM_PREGS 4
|
||||
#define TOTAL_PER_THREAD_REGS 64
|
||||
@ -34,6 +35,7 @@ typedef struct CPUHexagonState CPUHexagonState;
|
||||
#define STORES_MAX 2
|
||||
#define REG_WRITES_MAX 32
|
||||
#define PRED_WRITES_MAX 5 /* 4 insns + endloop */
|
||||
#define VSTORES_MAX 2
|
||||
|
||||
#define TYPE_HEXAGON_CPU "hexagon-cpu"
|
||||
|
||||
@ -52,6 +54,13 @@ typedef struct {
|
||||
uint64_t data64;
|
||||
} MemLog;
|
||||
|
||||
typedef struct {
|
||||
target_ulong va;
|
||||
int size;
|
||||
DECLARE_BITMAP(mask, MAX_VEC_SIZE_BYTES) QEMU_ALIGNED(16);
|
||||
MMVector data QEMU_ALIGNED(16);
|
||||
} VStoreLog;
|
||||
|
||||
#define EXEC_STATUS_OK 0x0000
|
||||
#define EXEC_STATUS_STOP 0x0002
|
||||
#define EXEC_STATUS_REPLAY 0x0010
|
||||
@ -64,6 +73,9 @@ typedef struct {
|
||||
#define CLEAR_EXCEPTION (env->status &= (~EXEC_STATUS_EXCEPTION))
|
||||
#define SET_EXCEPTION (env->status |= EXEC_STATUS_EXCEPTION)
|
||||
|
||||
/* Maximum number of vector temps in a packet */
|
||||
#define VECTOR_TEMPS_MAX 4
|
||||
|
||||
struct CPUHexagonState {
|
||||
target_ulong gpr[TOTAL_PER_THREAD_REGS];
|
||||
target_ulong pred[NUM_PREGS];
|
||||
@ -97,8 +109,27 @@ struct CPUHexagonState {
|
||||
target_ulong llsc_val;
|
||||
uint64_t llsc_val_i64;
|
||||
|
||||
target_ulong is_gather_store_insn;
|
||||
target_ulong gather_issued;
|
||||
MMVector VRegs[NUM_VREGS] QEMU_ALIGNED(16);
|
||||
MMVector future_VRegs[VECTOR_TEMPS_MAX] QEMU_ALIGNED(16);
|
||||
MMVector tmp_VRegs[VECTOR_TEMPS_MAX] QEMU_ALIGNED(16);
|
||||
|
||||
VRegMask VRegs_updated;
|
||||
|
||||
MMQReg QRegs[NUM_QREGS] QEMU_ALIGNED(16);
|
||||
MMQReg future_QRegs[NUM_QREGS] QEMU_ALIGNED(16);
|
||||
QRegMask QRegs_updated;
|
||||
|
||||
/* Temporaries used within instructions */
|
||||
MMVectorPair VuuV QEMU_ALIGNED(16);
|
||||
MMVectorPair VvvV QEMU_ALIGNED(16);
|
||||
MMVectorPair VxxV QEMU_ALIGNED(16);
|
||||
MMVector vtmp QEMU_ALIGNED(16);
|
||||
MMQReg qtmp QEMU_ALIGNED(16);
|
||||
|
||||
VStoreLog vstore[VSTORES_MAX];
|
||||
target_ulong vstore_pending[VSTORES_MAX];
|
||||
bool vtcm_pending;
|
||||
VTCMStoreLog vtcm_log;
|
||||
};
|
||||
|
||||
#define HEXAGON_CPU_CLASS(klass) \
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define HEXAGON_ARCH_TYPES_H
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "mmvec/mmvec.h"
|
||||
#include "qemu/int128.h"
|
||||
|
||||
/*
|
||||
@ -35,4 +36,8 @@ typedef uint64_t size8u_t;
|
||||
typedef int64_t size8s_t;
|
||||
typedef Int128 size16s_t;
|
||||
|
||||
typedef MMVector mmvector_t;
|
||||
typedef MMVectorPair mmvector_pair_t;
|
||||
typedef MMQReg mmqret_t;
|
||||
|
||||
#endif
|
||||
|
@ -67,6 +67,9 @@ struct Packet {
|
||||
bool pkt_has_store_s0;
|
||||
bool pkt_has_store_s1;
|
||||
|
||||
bool pkt_has_hvx;
|
||||
Insn *vhist_insn;
|
||||
|
||||
Insn insn[INSTRUCTIONS_MAX];
|
||||
};
|
||||
|
||||
|
@ -31,6 +31,9 @@
|
||||
|
||||
int hexagon_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
int hexagon_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
|
||||
void hexagon_debug_vreg(CPUHexagonState *env, int regnum);
|
||||
void hexagon_debug_qreg(CPUHexagonState *env, int regnum);
|
||||
void hexagon_debug(CPUHexagonState *env);
|
||||
|
||||
extern const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS];
|
||||
|
82
target/hexagon/mmvec/mmvec.h
Normal file
82
target/hexagon/mmvec/mmvec.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_MMVEC_H
|
||||
#define HEXAGON_MMVEC_H
|
||||
|
||||
#define MAX_VEC_SIZE_LOGBYTES 7
|
||||
#define MAX_VEC_SIZE_BYTES (1 << MAX_VEC_SIZE_LOGBYTES)
|
||||
|
||||
#define NUM_VREGS 32
|
||||
#define NUM_QREGS 4
|
||||
|
||||
typedef uint32_t VRegMask; /* at least NUM_VREGS bits */
|
||||
typedef uint32_t QRegMask; /* at least NUM_QREGS bits */
|
||||
|
||||
#define VECTOR_SIZE_BYTE (fVECSIZE())
|
||||
|
||||
typedef union {
|
||||
uint64_t ud[MAX_VEC_SIZE_BYTES / 8];
|
||||
int64_t d[MAX_VEC_SIZE_BYTES / 8];
|
||||
uint32_t uw[MAX_VEC_SIZE_BYTES / 4];
|
||||
int32_t w[MAX_VEC_SIZE_BYTES / 4];
|
||||
uint16_t uh[MAX_VEC_SIZE_BYTES / 2];
|
||||
int16_t h[MAX_VEC_SIZE_BYTES / 2];
|
||||
uint8_t ub[MAX_VEC_SIZE_BYTES / 1];
|
||||
int8_t b[MAX_VEC_SIZE_BYTES / 1];
|
||||
} MMVector;
|
||||
|
||||
typedef union {
|
||||
uint64_t ud[2 * MAX_VEC_SIZE_BYTES / 8];
|
||||
int64_t d[2 * MAX_VEC_SIZE_BYTES / 8];
|
||||
uint32_t uw[2 * MAX_VEC_SIZE_BYTES / 4];
|
||||
int32_t w[2 * MAX_VEC_SIZE_BYTES / 4];
|
||||
uint16_t uh[2 * MAX_VEC_SIZE_BYTES / 2];
|
||||
int16_t h[2 * MAX_VEC_SIZE_BYTES / 2];
|
||||
uint8_t ub[2 * MAX_VEC_SIZE_BYTES / 1];
|
||||
int8_t b[2 * MAX_VEC_SIZE_BYTES / 1];
|
||||
MMVector v[2];
|
||||
} MMVectorPair;
|
||||
|
||||
typedef union {
|
||||
uint64_t ud[MAX_VEC_SIZE_BYTES / 8 / 8];
|
||||
int64_t d[MAX_VEC_SIZE_BYTES / 8 / 8];
|
||||
uint32_t uw[MAX_VEC_SIZE_BYTES / 4 / 8];
|
||||
int32_t w[MAX_VEC_SIZE_BYTES / 4 / 8];
|
||||
uint16_t uh[MAX_VEC_SIZE_BYTES / 2 / 8];
|
||||
int16_t h[MAX_VEC_SIZE_BYTES / 2 / 8];
|
||||
uint8_t ub[MAX_VEC_SIZE_BYTES / 1 / 8];
|
||||
int8_t b[MAX_VEC_SIZE_BYTES / 1 / 8];
|
||||
} MMQReg;
|
||||
|
||||
typedef struct {
|
||||
MMVector data;
|
||||
DECLARE_BITMAP(mask, MAX_VEC_SIZE_BYTES);
|
||||
target_ulong va[MAX_VEC_SIZE_BYTES];
|
||||
bool op;
|
||||
int op_size;
|
||||
} VTCMStoreLog;
|
||||
|
||||
|
||||
/* Types of vector register assignment */
|
||||
typedef enum {
|
||||
EXT_DFL, /* Default */
|
||||
EXT_NEW, /* New - value used in the same packet */
|
||||
EXT_TMP /* Temp - value used but not stored to register */
|
||||
} VRegWriteType;
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user