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]);
|
GET_REG32(env->uregs[reg->targno & 0xff]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 4: /*f*/
|
||||||
|
GET_REG32(float32_val(env->fregs[reg->targno & 0x0f]));
|
||||||
|
break;
|
||||||
|
|
||||||
case 8: /*a*/
|
case 8: /*a*/
|
||||||
GET_REG32(env->regs[reg->targno & 0x0f]);
|
GET_REG32(env->regs[reg->targno & 0x0f]);
|
||||||
break;
|
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;
|
env->uregs[reg->targno & 0xff] = tmp;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 4: /*f*/
|
||||||
|
env->fregs[reg->targno & 0x0f] = make_float32(tmp);
|
||||||
|
break;
|
||||||
|
|
||||||
case 8: /*a*/
|
case 8: /*a*/
|
||||||
env->regs[reg->targno & 0x0f] = tmp;
|
env->regs[reg->targno & 0x0f] = tmp;
|
||||||
break;
|
break;
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "cpu-defs.h"
|
#include "cpu-defs.h"
|
||||||
|
#include "fpu/softfloat.h"
|
||||||
|
|
||||||
#define TARGET_HAS_ICE 1
|
#define TARGET_HAS_ICE 1
|
||||||
|
|
||||||
@ -325,6 +326,8 @@ typedef struct CPUXtensaState {
|
|||||||
uint32_t sregs[256];
|
uint32_t sregs[256];
|
||||||
uint32_t uregs[256];
|
uint32_t uregs[256];
|
||||||
uint32_t phys_regs[MAX_NAREG];
|
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 itlb[7][MAX_TLB_WAY_SIZE];
|
||||||
xtensa_tlb_entry dtlb[10][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_dbreaka, void, env, i32, i32)
|
||||||
DEF_HELPER_3(wsr_dbreakc, 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"
|
#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;
|
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_ptr cpu_env;
|
||||||
static TCGv_i32 cpu_pc;
|
static TCGv_i32 cpu_pc;
|
||||||
static TCGv_i32 cpu_R[16];
|
static TCGv_i32 cpu_R[16];
|
||||||
|
static TCGv_i32 cpu_FR[16];
|
||||||
static TCGv_i32 cpu_SR[256];
|
static TCGv_i32 cpu_SR[256];
|
||||||
static TCGv_i32 cpu_UR[256];
|
static TCGv_i32 cpu_UR[256];
|
||||||
|
|
||||||
@ -155,6 +156,12 @@ void xtensa_translate_init(void)
|
|||||||
"ar8", "ar9", "ar10", "ar11",
|
"ar8", "ar9", "ar10", "ar11",
|
||||||
"ar12", "ar13", "ar14", "ar15",
|
"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;
|
int i;
|
||||||
|
|
||||||
cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
|
cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
|
||||||
@ -167,6 +174,12 @@ void xtensa_translate_init(void)
|
|||||||
regnames[i]);
|
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) {
|
for (i = 0; i < 256; ++i) {
|
||||||
if (sregnames[i]) {
|
if (sregnames[i]) {
|
||||||
cpu_SR[i] = tcg_global_mem_new_i32(TCG_AREG0,
|
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,
|
static void gen_load_store_alignment(DisasContext *dc, int shift,
|
||||||
TCGv_i32 addr, bool no_hw_alignment)
|
TCGv_i32 addr, bool no_hw_alignment)
|
||||||
{
|
{
|
||||||
@ -1761,13 +1791,11 @@ static void disas_xtensa_insn(DisasContext *dc)
|
|||||||
|
|
||||||
case 15: /*WUR*/
|
case 15: /*WUR*/
|
||||||
gen_window_check1(dc, RRR_T);
|
gen_window_check1(dc, RRR_T);
|
||||||
{
|
if (uregnames[RSR_SR]) {
|
||||||
if (uregnames[RSR_SR]) {
|
gen_wur(RSR_SR, cpu_R[RRR_T]);
|
||||||
tcg_gen_mov_i32(cpu_UR[RSR_SR], cpu_R[RRR_T]);
|
} else {
|
||||||
} else {
|
qemu_log("WUR %d not implemented, ", RSR_SR);
|
||||||
qemu_log("WUR %d not implemented, ", RSR_SR);
|
TBD();
|
||||||
TBD();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
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],
|
cpu_fprintf(f, "AR%02d=%08x%c", i, env->phys_regs[i],
|
||||||
(i % 4) == 3 ? '\n' : ' ');
|
(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)
|
void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, int pc_pos)
|
||||||
|
Loading…
Reference in New Issue
Block a user