target/loongarch: Add LSX data type VReg
Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Song Gao <gaosong@loongson.cn> Message-Id: <20230504122810.4094787-2-gaosong@loongson.cn>
This commit is contained in:
		| @@ -128,7 +128,7 @@ static void setup_sigframe(CPULoongArchState *env, | ||||
|  | ||||
|     fpu_ctx = (struct target_fpu_context *)(info + 1); | ||||
|     for (i = 0; i < 32; ++i) { | ||||
|         __put_user(env->fpr[i], &fpu_ctx->regs[i]); | ||||
|         __put_user(env->fpr[i].vreg.D(0), &fpu_ctx->regs[i]); | ||||
|     } | ||||
|     __put_user(read_fcc(env), &fpu_ctx->fcc); | ||||
|     __put_user(env->fcsr0, &fpu_ctx->fcsr); | ||||
| @@ -193,7 +193,7 @@ static void restore_sigframe(CPULoongArchState *env, | ||||
|         uint64_t fcc; | ||||
|  | ||||
|         for (i = 0; i < 32; ++i) { | ||||
|             __get_user(env->fpr[i], &fpu_ctx->regs[i]); | ||||
|             __get_user(env->fpr[i].vreg.D(0), &fpu_ctx->regs[i]); | ||||
|         } | ||||
|         __get_user(fcc, &fpu_ctx->fcc); | ||||
|         write_fcc(env, fcc); | ||||
|   | ||||
| @@ -656,7 +656,7 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags) | ||||
|     /* fpr */ | ||||
|     if (flags & CPU_DUMP_FPU) { | ||||
|         for (i = 0; i < 32; i++) { | ||||
|             qemu_fprintf(f, " %s %016" PRIx64, fregnames[i], env->fpr[i]); | ||||
|             qemu_fprintf(f, " %s %016" PRIx64, fregnames[i], env->fpr[i].vreg.D(0)); | ||||
|             if ((i & 3) == 3) { | ||||
|                 qemu_fprintf(f, "\n"); | ||||
|             } | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #ifndef LOONGARCH_CPU_H | ||||
| #define LOONGARCH_CPU_H | ||||
|  | ||||
| #include "qemu/int128.h" | ||||
| #include "exec/cpu-defs.h" | ||||
| #include "fpu/softfloat-types.h" | ||||
| #include "hw/registerfields.h" | ||||
| @@ -241,6 +242,24 @@ FIELD(TLB_MISC, ASID, 1, 10) | ||||
| FIELD(TLB_MISC, VPPN, 13, 35) | ||||
| FIELD(TLB_MISC, PS, 48, 6) | ||||
|  | ||||
| #define LSX_LEN   (128) | ||||
| 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; | ||||
|  | ||||
| typedef union fpr_t fpr_t; | ||||
| union fpr_t { | ||||
|     VReg  vreg; | ||||
| }; | ||||
|  | ||||
| struct LoongArchTLB { | ||||
|     uint64_t tlb_misc; | ||||
|     /* Fields corresponding to CSR_TLBELO0/1 */ | ||||
| @@ -253,7 +272,7 @@ typedef struct CPUArchState { | ||||
|     uint64_t gpr[32]; | ||||
|     uint64_t pc; | ||||
|  | ||||
|     uint64_t fpr[32]; | ||||
|     fpr_t fpr[32]; | ||||
|     float_status fp_status; | ||||
|     bool cf[8]; | ||||
|  | ||||
|   | ||||
| @@ -69,7 +69,7 @@ static int loongarch_gdb_get_fpu(CPULoongArchState *env, | ||||
|                                  GByteArray *mem_buf, int n) | ||||
| { | ||||
|     if (0 <= n && n < 32) { | ||||
|         return gdb_get_reg64(mem_buf, env->fpr[n]); | ||||
|         return gdb_get_reg64(mem_buf, env->fpr[n].vreg.D(0)); | ||||
|     } else if (n == 32) { | ||||
|         uint64_t val = read_fcc(env); | ||||
|         return gdb_get_reg64(mem_buf, val); | ||||
| @@ -85,7 +85,7 @@ static int loongarch_gdb_set_fpu(CPULoongArchState *env, | ||||
|     int length = 0; | ||||
|  | ||||
|     if (0 <= n && n < 32) { | ||||
|         env->fpr[n] = ldq_p(mem_buf); | ||||
|         env->fpr[n].vreg.D(0) = ldq_p(mem_buf); | ||||
|         length = 8; | ||||
|     } else if (n == 32) { | ||||
|         uint64_t val = ldq_p(mem_buf); | ||||
|   | ||||
| @@ -21,6 +21,28 @@ | ||||
| /* 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); | ||||
|   | ||||
| @@ -10,6 +10,72 @@ | ||||
| #include "migration/cpu.h" | ||||
| #include "internals.h" | ||||
|  | ||||
| static const VMStateDescription vmstate_fpu_reg = { | ||||
|     .name = "fpu_reg", | ||||
|     .version_id = 1, | ||||
|     .minimum_version_id = 1, | ||||
|     .fields = (VMStateField[]) { | ||||
|         VMSTATE_UINT64(UD(0), VReg), | ||||
|         VMSTATE_END_OF_LIST() | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #define VMSTATE_FPU_REGS(_field, _state, _start)            \ | ||||
|     VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, 32, 0, \ | ||||
|                              vmstate_fpu_reg, fpr_t) | ||||
|  | ||||
| static bool fpu_needed(void *opaque) | ||||
| { | ||||
|     LoongArchCPU *cpu = opaque; | ||||
|  | ||||
|     return FIELD_EX64(cpu->env.cpucfg[2], CPUCFG2, FP); | ||||
| } | ||||
|  | ||||
| static const VMStateDescription vmstate_fpu = { | ||||
|     .name = "cpu/fpu", | ||||
|     .version_id = 1, | ||||
|     .minimum_version_id = 1, | ||||
|     .needed = fpu_needed, | ||||
|     .fields = (VMStateField[]) { | ||||
|         VMSTATE_FPU_REGS(env.fpr, LoongArchCPU, 0), | ||||
|         VMSTATE_UINT32(env.fcsr0, LoongArchCPU), | ||||
|         VMSTATE_BOOL_ARRAY(env.cf, LoongArchCPU, 8), | ||||
|         VMSTATE_END_OF_LIST() | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| static const VMStateDescription vmstate_lsxh_reg = { | ||||
|     .name = "lsxh_reg", | ||||
|     .version_id = 1, | ||||
|     .minimum_version_id = 1, | ||||
|     .fields = (VMStateField[]) { | ||||
|         VMSTATE_UINT64(UD(1), VReg), | ||||
|         VMSTATE_END_OF_LIST() | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #define VMSTATE_LSXH_REGS(_field, _state, _start)           \ | ||||
|     VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, 32, 0, \ | ||||
|                              vmstate_lsxh_reg, fpr_t) | ||||
|  | ||||
| static bool lsx_needed(void *opaque) | ||||
| { | ||||
|     LoongArchCPU *cpu = opaque; | ||||
|  | ||||
|     return FIELD_EX64(cpu->env.cpucfg[2], CPUCFG2, LSX); | ||||
| } | ||||
|  | ||||
| static const VMStateDescription vmstate_lsx = { | ||||
|     .name = "cpu/lsx", | ||||
|     .version_id = 1, | ||||
|     .minimum_version_id = 1, | ||||
|     .needed = lsx_needed, | ||||
|     .fields = (VMStateField[]) { | ||||
|         VMSTATE_LSXH_REGS(env.fpr, LoongArchCPU, 0), | ||||
|         VMSTATE_END_OF_LIST() | ||||
|     }, | ||||
| }; | ||||
|  | ||||
| /* TLB state */ | ||||
| const VMStateDescription vmstate_tlb = { | ||||
|     .name = "cpu/tlb", | ||||
| @@ -24,18 +90,13 @@ const VMStateDescription vmstate_tlb = { | ||||
| }; | ||||
|  | ||||
| /* LoongArch CPU state */ | ||||
|  | ||||
| const VMStateDescription vmstate_loongarch_cpu = { | ||||
|     .name = "cpu", | ||||
|     .version_id = 0, | ||||
|     .minimum_version_id = 0, | ||||
|     .version_id = 1, | ||||
|     .minimum_version_id = 1, | ||||
|     .fields = (VMStateField[]) { | ||||
|  | ||||
|         VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32), | ||||
|         VMSTATE_UINTTL(env.pc, LoongArchCPU), | ||||
|         VMSTATE_UINT64_ARRAY(env.fpr, LoongArchCPU, 32), | ||||
|         VMSTATE_UINT32(env.fcsr0, LoongArchCPU), | ||||
|         VMSTATE_BOOL_ARRAY(env.cf, LoongArchCPU, 8), | ||||
|  | ||||
|         /* Remaining CSRs */ | ||||
|         VMSTATE_UINT64(env.CSR_CRMD, LoongArchCPU), | ||||
| @@ -99,4 +160,8 @@ const VMStateDescription vmstate_loongarch_cpu = { | ||||
|  | ||||
|         VMSTATE_END_OF_LIST() | ||||
|     }, | ||||
|     .subsections = (const VMStateDescription*[]) { | ||||
|         &vmstate_fpu, | ||||
|         &vmstate_lsx, | ||||
|     } | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user