mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-loongarch-20230920' of https://gitlab.com/gaosong/qemu into staging
Add LASX instructions support. # -----BEGIN PGP SIGNATURE----- # # iLMEAAEIAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCZQqV7wAKCRBAov/yOSY+ # 35GTA/9rXGbr9pIUnlGstUnWzIJb0vs6f4kt9DaKRPF1zyxaF/59sgl3gqCNAjBA # eAKfm5W4B8ABJ+PYR3ZVAg9AcAP9AOEi+qV6DgRwvYPPK3WbGqIpJL7i+7gNMMUs # gppv+IfJEkri8YLXXa7GWffuGOebqdqyD6Pl1B2eiKS4KYSRGw== # =fNr2 # -----END PGP SIGNATURE----- # gpg: Signature made Wed 20 Sep 2023 02:49:19 EDT # gpg: using RSA key B8FF1DA0D2FDCB2DA09C6C2C40A2FFF239263EDF # gpg: Good signature from "Song Gao <m17746591750@163.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: B8FF 1DA0 D2FD CB2D A09C 6C2C 40A2 FFF2 3926 3EDF * tag 'pull-loongarch-20230920' of https://gitlab.com/gaosong/qemu: (57 commits) target/loongarch: CPUCFG support LASX target/loongarch: Move simply DO_XX marcos togther target/loongarch: Implement xvld xvst target/loongarch: Implement xvshuf xvperm{i} xvshuf4i target/loongarch: Implement xvpack xvpick xvilv{l/h} target/loongarch: Implement xvreplve xvinsve0 xvpickve target/loongarch: Implement xvinsgr2vr xvpickve2gr target/loongarch: Implement xvbitsel xvset target/loongarch: Implement xvfcmp target/loongarch: Implement xvseq xvsle xvslt target/loongarch: Implement LASX fpu fcvt instructions target/loongarch: Implement LASX fpu arith instructions target/loongarch: Implement xvfrstp target/loongarch: Implement xvbitclr xvbitset xvbitrev target/loongarch: Implement xvpcnt target/loongarch: Implement xvclo xvclz target/loongarch: Implement xvssrlrn xvssrarn target/loongarch: Implement xvssrln xvssran target/loongarch: Implement xvsrlrn xvsrarn target/loongarch: Implement xvsrln xvsran ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#include "linux-user/trace.h"
|
||||
|
||||
#include "target/loongarch/internals.h"
|
||||
#include "target/loongarch/vec.h"
|
||||
|
||||
/* FP context was used */
|
||||
#define SC_USED_FP (1 << 0)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "cpu-csr.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "tcg/tcg.h"
|
||||
#include "vec.h"
|
||||
|
||||
const char * const regnames[32] = {
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
@@ -54,6 +55,7 @@ static const char * const excp_names[] = {
|
||||
[EXCCODE_DBP] = "Debug breakpoint",
|
||||
[EXCCODE_BCE] = "Bound Check Exception",
|
||||
[EXCCODE_SXD] = "128 bit vector instructions Disable exception",
|
||||
[EXCCODE_ASXD] = "256 bit vector instructions Disable exception",
|
||||
};
|
||||
|
||||
const char *loongarch_exception_name(int32_t exception)
|
||||
@@ -189,6 +191,7 @@ static void loongarch_cpu_do_interrupt(CPUState *cs)
|
||||
case EXCCODE_FPD:
|
||||
case EXCCODE_FPE:
|
||||
case EXCCODE_SXD:
|
||||
case EXCCODE_ASXD:
|
||||
env->CSR_BADV = env->pc;
|
||||
QEMU_FALLTHROUGH;
|
||||
case EXCCODE_BCE:
|
||||
@@ -390,6 +393,7 @@ static void loongarch_la464_initfn(Object *obj)
|
||||
data = FIELD_DP32(data, CPUCFG2, FP_DP, 1);
|
||||
data = FIELD_DP32(data, CPUCFG2, FP_VER, 1);
|
||||
data = FIELD_DP32(data, CPUCFG2, LSX, 1),
|
||||
data = FIELD_DP32(data, CPUCFG2, LASX, 1),
|
||||
data = FIELD_DP32(data, CPUCFG2, LLFTP, 1);
|
||||
data = FIELD_DP32(data, CPUCFG2, LLFTP_VER, 1);
|
||||
data = FIELD_DP32(data, CPUCFG2, LSPW, 1);
|
||||
|
||||
+15
-11
@@ -251,18 +251,20 @@ FIELD(TLB_MISC, ASID, 1, 10)
|
||||
FIELD(TLB_MISC, VPPN, 13, 35)
|
||||
FIELD(TLB_MISC, PS, 48, 6)
|
||||
|
||||
#define LSX_LEN (128)
|
||||
#define LSX_LEN (128)
|
||||
#define LASX_LEN (256)
|
||||
|
||||
typedef union VReg {
|
||||
int8_t B[LSX_LEN / 8];
|
||||
int16_t H[LSX_LEN / 16];
|
||||
int32_t W[LSX_LEN / 32];
|
||||
int64_t D[LSX_LEN / 64];
|
||||
uint8_t UB[LSX_LEN / 8];
|
||||
uint16_t UH[LSX_LEN / 16];
|
||||
uint32_t UW[LSX_LEN / 32];
|
||||
uint64_t UD[LSX_LEN / 64];
|
||||
Int128 Q[LSX_LEN / 128];
|
||||
}VReg;
|
||||
int8_t B[LASX_LEN / 8];
|
||||
int16_t H[LASX_LEN / 16];
|
||||
int32_t W[LASX_LEN / 32];
|
||||
int64_t D[LASX_LEN / 64];
|
||||
uint8_t UB[LASX_LEN / 8];
|
||||
uint16_t UH[LASX_LEN / 16];
|
||||
uint32_t UW[LASX_LEN / 32];
|
||||
uint64_t UD[LASX_LEN / 64];
|
||||
Int128 Q[LASX_LEN / 128];
|
||||
} VReg;
|
||||
|
||||
typedef union fpr_t fpr_t;
|
||||
union fpr_t {
|
||||
@@ -460,6 +462,7 @@ static inline void set_pc(CPULoongArchState *env, uint64_t value)
|
||||
#define HW_FLAGS_CRMD_PG R_CSR_CRMD_PG_MASK /* 0x10 */
|
||||
#define HW_FLAGS_EUEN_FPE 0x04
|
||||
#define HW_FLAGS_EUEN_SXE 0x08
|
||||
#define HW_FLAGS_EUEN_ASXE 0x10
|
||||
#define HW_FLAGS_VA32 0x20
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, vaddr *pc,
|
||||
@@ -470,6 +473,7 @@ static inline void cpu_get_tb_cpu_state(CPULoongArchState *env, vaddr *pc,
|
||||
*flags = env->CSR_CRMD & (R_CSR_CRMD_PLV_MASK | R_CSR_CRMD_PG_MASK);
|
||||
*flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, FPE) * HW_FLAGS_EUEN_FPE;
|
||||
*flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, SXE) * HW_FLAGS_EUEN_SXE;
|
||||
*flags |= FIELD_EX64(env->CSR_EUEN, CSR_EUEN, ASXE) * HW_FLAGS_EUEN_ASXE;
|
||||
*flags |= is_va32(env) * HW_FLAGS_VA32;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@
|
||||
#include "internals.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "gdbstub/helpers.h"
|
||||
#include "vec.h"
|
||||
|
||||
uint64_t read_fcc(CPULoongArchState *env)
|
||||
{
|
||||
|
||||
+326
-305
File diff suppressed because it is too large
Load Diff
+1673
-706
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -21,28 +21,6 @@
|
||||
/* Global bit for huge page */
|
||||
#define LOONGARCH_HGLOBAL_SHIFT 12
|
||||
|
||||
#if HOST_BIG_ENDIAN
|
||||
#define B(x) B[15 - (x)]
|
||||
#define H(x) H[7 - (x)]
|
||||
#define W(x) W[3 - (x)]
|
||||
#define D(x) D[1 - (x)]
|
||||
#define UB(x) UB[15 - (x)]
|
||||
#define UH(x) UH[7 - (x)]
|
||||
#define UW(x) UW[3 - (x)]
|
||||
#define UD(x) UD[1 -(x)]
|
||||
#define Q(x) Q[x]
|
||||
#else
|
||||
#define B(x) B[x]
|
||||
#define H(x) H[x]
|
||||
#define W(x) W[x]
|
||||
#define D(x) D[x]
|
||||
#define UB(x) UB[x]
|
||||
#define UH(x) UH[x]
|
||||
#define UW(x) UW[x]
|
||||
#define UD(x) UD[x]
|
||||
#define Q(x) Q[x]
|
||||
#endif
|
||||
|
||||
void loongarch_translate_init(void);
|
||||
|
||||
void loongarch_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "migration/cpu.h"
|
||||
#include "internals.h"
|
||||
#include "vec.h"
|
||||
|
||||
static const VMStateDescription vmstate_fpu_reg = {
|
||||
.name = "fpu_reg",
|
||||
@@ -76,6 +76,39 @@ static const VMStateDescription vmstate_lsx = {
|
||||
},
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_lasxh_reg = {
|
||||
.name = "lasxh_reg",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT64(UD(2), VReg),
|
||||
VMSTATE_UINT64(UD(3), VReg),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
#define VMSTATE_LASXH_REGS(_field, _state, _start) \
|
||||
VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, 32, 0, \
|
||||
vmstate_lasxh_reg, fpr_t)
|
||||
|
||||
static bool lasx_needed(void *opaque)
|
||||
{
|
||||
LoongArchCPU *cpu = opaque;
|
||||
|
||||
return FIELD_EX64(cpu->env.cpucfg[2], CPUCFG2, LASX);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_lasx = {
|
||||
.name = "cpu/lasx",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = lasx_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_LASXH_REGS(env.fpr, LoongArchCPU, 0),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
};
|
||||
|
||||
/* TLB state */
|
||||
const VMStateDescription vmstate_tlb = {
|
||||
.name = "cpu/tlb",
|
||||
@@ -163,6 +196,7 @@ const VMStateDescription vmstate_loongarch_cpu = {
|
||||
.subsections = (const VMStateDescription*[]) {
|
||||
&vmstate_fpu,
|
||||
&vmstate_lsx,
|
||||
&vmstate_lasx,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ loongarch_tcg_ss.add(files(
|
||||
'op_helper.c',
|
||||
'translate.c',
|
||||
'gdbstub.c',
|
||||
'lsx_helper.c',
|
||||
'vec_helper.c',
|
||||
))
|
||||
loongarch_tcg_ss.add(zlib)
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "fpu/softfloat.h"
|
||||
#include "translate.h"
|
||||
#include "internals.h"
|
||||
#include "vec.h"
|
||||
|
||||
/* Global register indices */
|
||||
TCGv cpu_gpr[32], cpu_pc;
|
||||
@@ -36,6 +37,18 @@ static inline int vec_full_offset(int regno)
|
||||
return offsetof(CPULoongArchState, fpr[regno]);
|
||||
}
|
||||
|
||||
static inline int vec_reg_offset(int regno, int index, MemOp mop)
|
||||
{
|
||||
const uint8_t size = 1 << mop;
|
||||
int offs = index * size;
|
||||
|
||||
if (HOST_BIG_ENDIAN && size < 8 ) {
|
||||
offs ^= (8 - size);
|
||||
}
|
||||
|
||||
return offs + vec_full_offset(regno);
|
||||
}
|
||||
|
||||
static inline void get_vreg64(TCGv_i64 dest, int regno, int index)
|
||||
{
|
||||
tcg_gen_ld_i64(dest, cpu_env,
|
||||
@@ -123,6 +136,10 @@ static void loongarch_tr_init_disas_context(DisasContextBase *dcbase,
|
||||
ctx->vl = LSX_LEN;
|
||||
}
|
||||
|
||||
if (FIELD_EX64(env->cpucfg[2], CPUCFG2, LASX)) {
|
||||
ctx->vl = LASX_LEN;
|
||||
}
|
||||
|
||||
ctx->la64 = is_la64(env);
|
||||
ctx->va32 = (ctx->base.tb->flags & HW_FLAGS_VA32) != 0;
|
||||
|
||||
@@ -261,7 +278,7 @@ static uint64_t make_address_pc(DisasContext *ctx, uint64_t addr)
|
||||
#include "insn_trans/trans_fmemory.c.inc"
|
||||
#include "insn_trans/trans_branch.c.inc"
|
||||
#include "insn_trans/trans_privileged.c.inc"
|
||||
#include "insn_trans/trans_lsx.c.inc"
|
||||
#include "insn_trans/trans_vec.c.inc"
|
||||
|
||||
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#define avail_LSPW(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, LSPW))
|
||||
#define avail_LAM(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, LAM))
|
||||
#define avail_LSX(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, LSX))
|
||||
#define avail_LASX(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, LASX))
|
||||
#define avail_IOCSR(C) (FIELD_EX32((C)->cpucfg1, CPUCFG1, IOCSR))
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* QEMU LoongArch vector utilitites
|
||||
*
|
||||
* Copyright (c) 2023 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#ifndef LOONGARCH_VEC_H
|
||||
#define LOONGARCH_VEC_H
|
||||
|
||||
#if HOST_BIG_ENDIAN
|
||||
#define B(x) B[(x) ^ 15]
|
||||
#define H(x) H[(x) ^ 7]
|
||||
#define W(x) W[(x) ^ 3]
|
||||
#define D(x) D[(x) ^ 1]
|
||||
#define UB(x) UB[(x) ^ 15]
|
||||
#define UH(x) UH[(x) ^ 7]
|
||||
#define UW(x) UW[(x) ^ 3]
|
||||
#define UD(x) UD[(x) ^ 1]
|
||||
#define Q(x) Q[x]
|
||||
#else
|
||||
#define B(x) B[x]
|
||||
#define H(x) H[x]
|
||||
#define W(x) W[x]
|
||||
#define D(x) D[x]
|
||||
#define UB(x) UB[x]
|
||||
#define UH(x) UH[x]
|
||||
#define UW(x) UW[x]
|
||||
#define UD(x) UD[x]
|
||||
#define Q(x) Q[x]
|
||||
#endif /* HOST_BIG_ENDIAN */
|
||||
|
||||
#define DO_ADD(a, b) (a + b)
|
||||
#define DO_SUB(a, b) (a - b)
|
||||
#define DO_VAVG(a, b) ((a >> 1) + (b >> 1) + (a & b & 1))
|
||||
#define DO_VAVGR(a, b) ((a >> 1) + (b >> 1) + ((a | b) & 1))
|
||||
#define DO_VABSD(a, b) ((a > b) ? (a -b) : (b-a))
|
||||
#define DO_VABS(a) ((a < 0) ? (-a) : (a))
|
||||
#define DO_MIN(a, b) (a < b ? a : b)
|
||||
#define DO_MAX(a, b) (a > b ? a : b)
|
||||
#define DO_MUL(a, b) (a * b)
|
||||
#define DO_MADD(a, b, c) (a + b * c)
|
||||
#define DO_MSUB(a, b, c) (a - b * c)
|
||||
|
||||
#define DO_DIVU(N, M) (unlikely(M == 0) ? 0 : N / M)
|
||||
#define DO_REMU(N, M) (unlikely(M == 0) ? 0 : N % M)
|
||||
#define DO_DIV(N, M) (unlikely(M == 0) ? 0 :\
|
||||
unlikely((N == -N) && (M == (__typeof(N))(-1))) ? N : N / M)
|
||||
#define DO_REM(N, M) (unlikely(M == 0) ? 0 :\
|
||||
unlikely((N == -N) && (M == (__typeof(N))(-1))) ? 0 : N % M)
|
||||
|
||||
#define DO_SIGNCOV(a, b) (a == 0 ? 0 : a < 0 ? -b : b)
|
||||
|
||||
#define R_SHIFT(a, b) (a >> b)
|
||||
|
||||
#define DO_CLO_B(N) (clz32(~N & 0xff) - 24)
|
||||
#define DO_CLO_H(N) (clz32(~N & 0xffff) - 16)
|
||||
#define DO_CLO_W(N) (clz32(~N))
|
||||
#define DO_CLO_D(N) (clz64(~N))
|
||||
#define DO_CLZ_B(N) (clz32(N) - 24)
|
||||
#define DO_CLZ_H(N) (clz32(N) - 16)
|
||||
#define DO_CLZ_W(N) (clz32(N))
|
||||
#define DO_CLZ_D(N) (clz64(N))
|
||||
|
||||
#define DO_BITCLR(a, bit) (a & ~(1ull << bit))
|
||||
#define DO_BITSET(a, bit) (a | 1ull << bit)
|
||||
#define DO_BITREV(a, bit) (a ^ (1ull << bit))
|
||||
|
||||
#define VSEQ(a, b) (a == b ? -1 : 0)
|
||||
#define VSLE(a, b) (a <= b ? -1 : 0)
|
||||
#define VSLT(a, b) (a < b ? -1 : 0)
|
||||
|
||||
#define SHF_POS(i, imm) (((i) & 0xfc) + (((imm) >> (2 * ((i) & 0x03))) & 0x03))
|
||||
|
||||
#endif /* LOONGARCH_VEC_H */
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user