target-xtensa: add FP registers
There are 16 32-bit FP registers (f0 - f15), control and status user registers (fcr, fsr). See ISA, 4.3.10 for more details. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
parent
b81fe822da
commit
dd519cbec6
@ -1696,6 +1696,10 @@ static int cpu_gdb_read_register(CPUXtensaState *env, uint8_t *mem_buf, int n)
|
||||
GET_REG32(env->uregs[reg->targno & 0xff]);
|
||||
break;
|
||||
|
||||
case 4: /*f*/
|
||||
GET_REG32(float32_val(env->fregs[reg->targno & 0x0f]));
|
||||
break;
|
||||
|
||||
case 8: /*a*/
|
||||
GET_REG32(env->regs[reg->targno & 0x0f]);
|
||||
break;
|
||||
@ -1736,6 +1740,10 @@ static int cpu_gdb_write_register(CPUXtensaState *env, uint8_t *mem_buf, int n)
|
||||
env->uregs[reg->targno & 0xff] = tmp;
|
||||
break;
|
||||
|
||||
case 4: /*f*/
|
||||
env->fregs[reg->targno & 0x0f] = make_float32(tmp);
|
||||
break;
|
||||
|
||||
case 8: /*a*/
|
||||
env->regs[reg->targno & 0x0f] = tmp;
|
||||
break;
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "config.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu-defs.h"
|
||||
#include "fpu/softfloat.h"
|
||||
|
||||
#define TARGET_HAS_ICE 1
|
||||
|
||||
@ -325,6 +326,8 @@ typedef struct CPUXtensaState {
|
||||
uint32_t sregs[256];
|
||||
uint32_t uregs[256];
|
||||
uint32_t phys_regs[MAX_NAREG];
|
||||
float32 fregs[16];
|
||||
float_status fp_status;
|
||||
|
||||
xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
|
||||
xtensa_tlb_entry dtlb[10][MAX_TLB_WAY_SIZE];
|
||||
|
@ -36,4 +36,6 @@ DEF_HELPER_3(wsr_ibreaka, void, env, i32, i32)
|
||||
DEF_HELPER_3(wsr_dbreaka, void, env, i32, i32)
|
||||
DEF_HELPER_3(wsr_dbreakc, void, env, i32, i32)
|
||||
|
||||
DEF_HELPER_2(wur_fcr, void, env, i32)
|
||||
|
||||
#include "def-helper.h"
|
||||
|
@ -771,3 +771,16 @@ void HELPER(wsr_dbreakc)(CPUXtensaState *env, uint32_t i, uint32_t v)
|
||||
}
|
||||
env->sregs[DBREAKC + i] = v;
|
||||
}
|
||||
|
||||
void HELPER(wur_fcr)(CPUXtensaState *env, uint32_t v)
|
||||
{
|
||||
static const int rounding_mode[] = {
|
||||
float_round_nearest_even,
|
||||
float_round_to_zero,
|
||||
float_round_up,
|
||||
float_round_down,
|
||||
};
|
||||
|
||||
env->uregs[FCR] = v & 0xfffff07f;
|
||||
set_float_rounding_mode(rounding_mode[v & 3], &env->fp_status);
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ typedef struct DisasContext {
|
||||
static TCGv_ptr cpu_env;
|
||||
static TCGv_i32 cpu_pc;
|
||||
static TCGv_i32 cpu_R[16];
|
||||
static TCGv_i32 cpu_FR[16];
|
||||
static TCGv_i32 cpu_SR[256];
|
||||
static TCGv_i32 cpu_UR[256];
|
||||
|
||||
@ -155,6 +156,12 @@ void xtensa_translate_init(void)
|
||||
"ar8", "ar9", "ar10", "ar11",
|
||||
"ar12", "ar13", "ar14", "ar15",
|
||||
};
|
||||
static const char * const fregnames[] = {
|
||||
"f0", "f1", "f2", "f3",
|
||||
"f4", "f5", "f6", "f7",
|
||||
"f8", "f9", "f10", "f11",
|
||||
"f12", "f13", "f14", "f15",
|
||||
};
|
||||
int i;
|
||||
|
||||
cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
|
||||
@ -167,6 +174,12 @@ void xtensa_translate_init(void)
|
||||
regnames[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
cpu_FR[i] = tcg_global_mem_new_i32(TCG_AREG0,
|
||||
offsetof(CPUXtensaState, fregs[i]),
|
||||
fregnames[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; ++i) {
|
||||
if (sregnames[i]) {
|
||||
cpu_SR[i] = tcg_global_mem_new_i32(TCG_AREG0,
|
||||
@ -692,6 +705,23 @@ static void gen_wsr(DisasContext *dc, uint32_t sr, TCGv_i32 s)
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_wur(uint32_t ur, TCGv_i32 s)
|
||||
{
|
||||
switch (ur) {
|
||||
case FCR:
|
||||
gen_helper_wur_fcr(cpu_env, s);
|
||||
break;
|
||||
|
||||
case FSR:
|
||||
tcg_gen_andi_i32(cpu_UR[ur], s, 0xffffff80);
|
||||
break;
|
||||
|
||||
default:
|
||||
tcg_gen_mov_i32(cpu_UR[ur], s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_load_store_alignment(DisasContext *dc, int shift,
|
||||
TCGv_i32 addr, bool no_hw_alignment)
|
||||
{
|
||||
@ -1761,13 +1791,11 @@ static void disas_xtensa_insn(DisasContext *dc)
|
||||
|
||||
case 15: /*WUR*/
|
||||
gen_window_check1(dc, RRR_T);
|
||||
{
|
||||
if (uregnames[RSR_SR]) {
|
||||
tcg_gen_mov_i32(cpu_UR[RSR_SR], cpu_R[RRR_T]);
|
||||
} else {
|
||||
qemu_log("WUR %d not implemented, ", RSR_SR);
|
||||
TBD();
|
||||
}
|
||||
if (uregnames[RSR_SR]) {
|
||||
gen_wur(RSR_SR, cpu_R[RRR_T]);
|
||||
} else {
|
||||
qemu_log("WUR %d not implemented, ", RSR_SR);
|
||||
TBD();
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2730,6 +2758,16 @@ void cpu_dump_state(CPUXtensaState *env, FILE *f, fprintf_function cpu_fprintf,
|
||||
cpu_fprintf(f, "AR%02d=%08x%c", i, env->phys_regs[i],
|
||||
(i % 4) == 3 ? '\n' : ' ');
|
||||
}
|
||||
|
||||
if (xtensa_option_enabled(env->config, XTENSA_OPTION_FP_COPROCESSOR)) {
|
||||
cpu_fprintf(f, "\n");
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
cpu_fprintf(f, "F%02d=%08x (%+10.8e)%c", i,
|
||||
float32_val(env->fregs[i]),
|
||||
*(float *)&env->fregs[i], (i % 2) == 1 ? '\n' : ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, int pc_pos)
|
||||
|
Loading…
Reference in New Issue
Block a user