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:
Max Filippov 2012-09-19 04:23:54 +04:00 committed by Blue Swirl
parent b81fe822da
commit dd519cbec6
5 changed files with 71 additions and 7 deletions

View File

@ -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;

View File

@ -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];

View File

@ -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"

View File

@ -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);
}

View File

@ -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)